Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Celtic Minstrel
185fca8444 Misc WIP 2016-09-18 18:12:38 -04:00
Celtic Minstrel
6d8e44a4f0 Try floating textbox as popup instead of a standalone widget 2016-09-18 17:37:27 -04:00
Celtic Minstrel
916f8f63ca Use GUI2 for floating textboxes (WIP) 2016-09-18 16:00:07 -04:00
15 changed files with 281 additions and 143 deletions

View file

@ -103,6 +103,7 @@
{_GUI_DEFINITION "default_large" "default, large font size" () LARGE () DEFAULT }
{_GUI_DEFINITION "default_small" "default, small font size" () SMALL () DEFAULT }
{_GUI_DEFINITION "default_tiny" "default, small font size" () TINY () DEFAULT }
{_GUI_DEFINITION "gold" "gold label" () DEFAULT () TITLE }
{_GUI_DEFINITION "gold_small" "small gold label" () SMALL () TITLE }
{_GUI_DEFINITION "monospace" "fixed width scroll label" monospace DEFAULT () DEFAULT }

View file

@ -0,0 +1,83 @@
#textdomain wesnoth-lib
[window_definition]
id = "floating"
description = "Floating popup window with no background or scrollbars"
[resolution]
left_border = 2
right_border = 2
top_border = 2
bottom_border = 2
[background]
[draw]
[/draw]
[/background]
[foreground]
[draw]
[/draw]
[/foreground]
[/resolution]
[/window_definition]
[window]
id = "floating_textbox"
description = "Floating textbox for in-game chat, etc"
[resolution]
definition = "floating"
automatic_placement = "true"
vertical_placement = "bottom"
horizontal_placement = "left"
[tooltip]
id = "tooltip"
[/tooltip]
[helptip]
id = "tooltip"
[/helptip]
[grid]
[row]
[column]
border = "left,right"
border_size = 10
[label]
definition = "gold"
id = "label"
text_alignment = "left"
[/label]
[/column]
[column]
grow_factor = 1
[text_box]
definition = "transparent"
id = "box"
[/text_box]
[/column]
[/row]
[row]
[column]
[toggle_button]
definition = "default"
id = "mode_toggle"
[/toggle_button]
[/column]
[column]
[spacer][/spacer]
[/column]
[/row]
[/grid]
[/resolution]
[/window]

View file

@ -14,8 +14,6 @@
#pragma once
#include "font.hpp"
#include "sdl/utils.hpp"
#include <string>

View file

@ -15,6 +15,12 @@
#include "global.hpp"
#include "floating_textbox.hpp"
#include "gui/auxiliary/find_widget.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/text_box.hpp"
#include "gui/widgets/toggle_button.hpp"
#include "gui/widgets/window.hpp"
#include "gui/dialogs/dialog.hpp"
#include "display_chat_manager.hpp"
#include "floating_label.hpp"
@ -28,56 +34,64 @@
static lg::log_domain log_display("display");
#define ERR_DP LOG_STREAM(err, log_display)
namespace gui{
floating_textbox::floating_textbox() :
box_(nullptr),
namespace gui2 {
REGISTER_DIALOG(floating_textbox);
tfloating_textbox::tfloating_textbox(game_display& gui, MODE mode, const std::string& label, const std::string& check_label, bool checked) :
// ttext_box(),
// gui_(gui),
check_(nullptr),
mode_(TEXTBOX_NONE),
label_string_(),
label_(0)
{}
void floating_textbox::close(game_display& gui)
{
if(!active()) {
return;
}
if(check_ != nullptr) {
if(mode_ == TEXTBOX_MESSAGE) {
preferences::set_message_private(check_->checked());
}
}
box_.reset(nullptr);
check_.reset(nullptr);
font::remove_floating_label(label_);
mode_ = TEXTBOX_NONE;
gui.invalidate_all();
mode_(mode),
label_string_(label),
check_label_(check_label),
initially_checked_(checked),
active_(false)
{/*
set_definition("transparent");
CVideo& video = CVideo::get_singleton();
if(!video.faked()) {
connect_signal<event::DRAW>(std::bind(&tfloating_textbox::draw, this, std::ref(video)));
}*/
}
void floating_textbox::update_location(game_display& gui)
/*
tfloating_textbox::~tfloating_textbox()
{
if (box_ == nullptr)
return;
if(check_ && mode_ == MESSAGE) {
preferences::set_message_private(check_->get_value_bool());
}
font::remove_floating_label(label_);
gui_.invalidate_all();
}
void tfloating_textbox::draw(CVideo& video)
{
surface& frame_buffer = video.getSurface();
draw_background(frame_buffer, 0, 0);
draw_children(frame_buffer, 0, 0);
draw_foreground(frame_buffer, 0, 0);
}
*/
void tfloating_textbox::pre_show(twindow& window)
{
active_ = true;
find_widget<tcontrol>(&window, "label", false).set_label(label_string_);
box_ = find_widget<ttext_box>(&window, "box", false, true);
const SDL_Rect& area = gui.map_outside_area();
check_ = find_widget<ttoggle_button>(&window, "mode_toggle", false, true);
if(check_label_.empty()) {
check_->set_visible(twindow::tvisible::invisible);
} else {
check_->set_label(check_label_);
check_->set_value_bool(initially_checked_);
}
/*
const SDL_Rect& area = gui_.map_outside_area();
const int border_size = 10;
const int ypos = area.y+area.h-30 - (check_ != nullptr ? check_->height() + border_size : 0);
if (label_ != 0)
font::remove_floating_label(label_);
font::floating_label flabel(label_string_);
flabel.set_color(font::YELLOW_COLOR);
flabel.set_position(area.x + border_size, ypos);
flabel.set_alignment(font::LEFT_ALIGN);
flabel.set_clip_rect(area);
label_ = font::add_floating_label(flabel);
if (label_ == 0)
return;
const int check_height = check_ ? check_->get_best_size().y : 0;
const int ypos = area.y+area.h-30 - check_height;
const SDL_Rect& label_area = font::get_floating_label_rect(label_);
const int textbox_width = area.w - label_area.w - border_size*3;
@ -87,60 +101,66 @@ namespace gui{
return;
}
if(box_ != nullptr) {
box_->set_volatile(true);
const SDL_Rect rect = sdl::create_rect(
area.x + label_area.w + border_size * 2
, ypos
, textbox_width
, box_->height());
tpoint origin(area.x + label_area.w + border_size * 2, ypos);
tpoint size(textbox_width, get_best_size().y);
set_origin(origin);
place(origin, size);
box_->set_location(rect);
}
if(check_ != nullptr) {
check_->set_volatile(true);
check_->set_location(box_->location().x,box_->location().y + box_->location().h + border_size);
}
if(check_) {
tpoint origin(get_x(), get_y() + get_height());
tpoint size = check_->get_best_size();
check_->set_origin(origin);
check_->place(origin, size);
}*/
}
void floating_textbox::show(gui::TEXTBOX_MODE mode, const std::string& label,
const std::string& check_label, bool checked, game_display& gui)
/*
void tfloating_textbox::show(MODE mode, const std::string& label, const std::string& check_label, bool checked)
{
close(gui);
label_string_ = label;
mode_ = mode;
if(check_label != "") {
check_.reset(new gui::button(gui.video(),check_label,gui::button::TYPE_CHECK));
check_->set_check(checked);
// set_label(label);
set_font_size(font::SIZE_PLUS);
connect();
// box_.reset(new gui::textbox(gui.video(),100,"",true,256,font::SIZE_PLUS,0.8,0.6));
if(!check_label.empty()) {
check_.reset(new ttoggle_button);
check_->set_definition("default");
check_->set_label(check_label);
check_->set_value_bool(checked);
check_->set_parent(this);
check_->connect();
}
box_.reset(new gui::textbox(gui.video(),100,"",true,256,font::SIZE_PLUS,0.8,0.6));
update_location(gui);
update_location();
fire(event::DRAW, *this);
}
void floating_textbox::tab(const std::set<std::string>& dictionary)
*/
void tfloating_textbox::tab(const std::set<std::string>& dictionary)
{
if(active() == false) {
return;
}
std::string text = box_->text();
std::string text = box_->get_value();
std::vector<std::string> matches(dictionary.begin(), dictionary.end());
const bool line_start = utils::word_completion(text, matches);
if (matches.empty()) return;
if (matches.size() == 1 && mode_ == gui::TEXTBOX_MESSAGE) {
if (matches.size() == 1 && mode_ == MESSAGE) {
text.append(line_start ? ": " : " ");
} else if (matches.size() > 1) {
std::string completion_list = utils::join(matches, " ");
resources::screen->get_chat_manager().add_chat_message(time(nullptr), "", 0, completion_list,
events::chat_handler::MESSAGE_PRIVATE, false);
}
box_->set_text(text);
box_->set_value(text);
}
bool tfloating_textbox::checked() const
{
return check_ ? check_->get_value_bool() : false;
}
std::string tfloating_textbox::get_value() const
{
return box_->get_value();
}
}

View file

@ -16,8 +16,7 @@
#ifndef FLOATING_TEXTBOX_H_INCLUDED
#define FLOATING_TEXTBOX_H_INCLUDED
// Scoped_resource can't use a pointer to an incomplete pointer with MSVC.
#include "widgets/textbox.hpp"
#include "gui/dialogs/popup.hpp"
#include <memory>
#include <set>
@ -26,36 +25,38 @@ class game_display;
class team;
class unit_map;
namespace gui{
namespace gui2 {
class ttoggle_button;
class ttext_box;
}
class button;
namespace gui2 {
enum TEXTBOX_MODE { TEXTBOX_NONE, TEXTBOX_SEARCH, TEXTBOX_MESSAGE,
TEXTBOX_COMMAND, TEXTBOX_AI };
class floating_textbox{
class tfloating_textbox : public tpopup {
public:
floating_textbox();
enum MODE { NONE, SEARCH, MESSAGE, COMMAND, AI };
tfloating_textbox(game_display& gui, MODE mode, const std::string& label, const std::string& check_label = "", bool checked = false);
//~tfloating_textbox();
TEXTBOX_MODE mode() const { return mode_; }
const std::unique_ptr<gui::button>& check() const { return check_; }
const std::unique_ptr<gui::textbox>& box() const { return box_; }
MODE mode() const { return mode_; }
bool checked() const;
bool active() const { return active_; }
std::string get_value() const;
void close(game_display& gui);
void update_location(game_display& gui);
void show(gui::TEXTBOX_MODE mode, const std::string& label,
const std::string& check_label, bool checked, game_display& gui);
//void update_location();
void tab(const std::set<std::string>& dictionary);
bool active() const { return box_.get() != nullptr; }
void show(CVideo& video) { tpopup::show(video, true); }
private:
std::unique_ptr<gui::textbox> box_;
std::unique_ptr<gui::button> check_;
virtual const std::string& window_id() const;
void pre_show(twindow& window);
ttoggle_button* check_;
ttext_box* box_;
//game_display& gui_;
MODE mode_;
TEXTBOX_MODE mode_;
std::string label_string_;
int label_;
std::string label_string_, check_label_;
bool initially_checked_, active_;
};
}

View file

@ -30,6 +30,7 @@
#include "floating_label.hpp"
#include "game_board.hpp"
#include "game_preferences.hpp"
#include "floating_textbox.hpp"
#include "halo.hpp"
#include "log.hpp"
#include "map/map.hpp"
@ -284,6 +285,7 @@ void game_display::draw_invalidated()
void game_display::post_commit()
{
halo_man_->render();
textbox_info_->
}
void game_display::draw_hex(const map_location& loc)

View file

@ -31,6 +31,10 @@ class game_board;
#include <deque>
namespace gui2 {
class tfloating_textbox;
}
// This needs to be separate from display.h because of the static
// singleton member, which will otherwise trigger link failure
// when building the editor.
@ -262,6 +266,7 @@ private:
bool needs_rebuild_;
std::shared_ptr<gui2::tfloating_textbox> textbox_info_;
};
#endif

View file

@ -532,7 +532,7 @@ void thandler::draw(const bool force)
}
if(!dispatchers_.empty()) {
CVideo& video = dynamic_cast<twindow&>(*dispatchers_.back()).video();
CVideo& video = CVideo::get_singleton();
video.flip();
}

View file

@ -193,7 +193,7 @@ tpoint twidget::get_best_size() const
if(result == tpoint()) {
result = calculate_best_size();
//Adjust to linked widget size if linked widget size was already calculated.
if(!get_window()->get_need_layout() && !linked_group_.empty())
if(get_window() && !get_window()->get_need_layout() && !linked_group_.empty())
{
tpoint linked_size = get_window()->get_linked_size(linked_group_);
result.x = std::max(result.x, linked_size.x);

View file

@ -549,7 +549,7 @@ void twindow::show_non_modal(/*const unsigned auto_close_timeout*/)
invalidate_layout();
suspend_drawing_ = false;
events::pump();
//events::pump();
}
int twindow::show(const bool restore, const unsigned auto_close_timeout)

View file

@ -58,6 +58,7 @@
#include "gui/dialogs/unit_recruit.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/window.hpp"
#include "floating_textbox.hpp"
#include "help/help.hpp"
#include "log.hpp"
#include "map/map.hpp"
@ -115,10 +116,19 @@ unit_map& menu_handler::units() { return gamestate().board_.units_; }
std::vector<team>& menu_handler::teams() const { return gamestate().board_.teams_; }
const gamemap& menu_handler::map() { return gamestate().board_.map(); }
gui::floating_textbox& menu_handler::get_textbox(){
const std::shared_ptr<gui2::tfloating_textbox> menu_handler::get_textbox(){
return textbox_info_;
}
void menu_handler::close_textbox() {
textbox_info_.reset();
}
void menu_handler::set_gui(game_display* gui) {
close_textbox();
gui_ = gui;
}
void menu_handler::objectives()
{
if (!gamestate().lua_kernel_) {
@ -216,9 +226,13 @@ void menu_handler::show_help()
void menu_handler::speak()
{
textbox_info_.show(gui::TEXTBOX_MESSAGE,_("Message:"),
has_friends() ? board().is_observer() ? _("Send to observers only") : _("Send to allies only")
: "", preferences::message_private(), *gui_);
const std::string check_label = has_friends()
? board().is_observer()
? _("Send to observers only")
: _("Send to allies only")
: "";
textbox_info_.reset(new gui2::tfloating_textbox(*gui_, gui2::tfloating_textbox::MESSAGE, _("Message:"), check_label, preferences::message_private()));
textbox_info_->show(gui_->video());
}
void menu_handler::whisper()
@ -947,13 +961,15 @@ void menu_handler::search()
msg << " [" << last_search_ << "]";
}
msg << ':';
textbox_info_.show(gui::TEXTBOX_SEARCH,msg.str(), "", false, *gui_);
textbox_info_.reset(new gui2::tfloating_textbox(*gui_, gui2::tfloating_textbox::SEARCH, msg.str()));
textbox_info_->show(gui_->video());
}
void menu_handler::do_speak(){
//None of the two parameters really needs to be passed since the information belong to members of the class.
//But since it makes the called method more generic, it is done anyway.
chat_handler::do_speak(textbox_info_.box()->text(),textbox_info_.check() != nullptr ? textbox_info_.check()->checked() : false);
assert(textbox_info_);
chat_handler::do_speak(textbox_info_->get_value(),textbox_info_->checked());
}
@ -1380,7 +1396,7 @@ void console_handler::do_droid() {
symbols["side"] = side_s;
command_failed(vgettext("Can't droid a local ai side: '$side'.", symbols));
}
menu_handler_.textbox_info_.close(*menu_handler_.gui_);
menu_handler_.textbox_info_.reset();
}
void console_handler::do_idle() {
@ -1418,7 +1434,7 @@ void console_handler::do_idle() {
}
}
}
menu_handler_.textbox_info_.close(*menu_handler_.gui_);
menu_handler_.textbox_info_.reset();
}
void console_handler::do_theme() {
@ -1467,7 +1483,7 @@ void console_handler::do_control() {
return;
}
menu_handler_.request_control_change(side_num,player);
menu_handler_.textbox_info_.close(*(menu_handler_.gui_));
menu_handler_.textbox_info_.reset();
}
void console_handler::do_controller()
{
@ -1909,7 +1925,8 @@ void menu_handler::do_ai_formula(const std::string& str,
void menu_handler::user_command()
{
textbox_info_.show(gui::TEXTBOX_COMMAND, translation::sgettext("prompt^Command:"), "", false, *gui_);
textbox_info_.reset(new gui2::tfloating_textbox(*gui_, gui2::tfloating_textbox::COMMAND, translation::sgettext("prompt^Command:")));
textbox_info_->show(gui_->video());
}
void menu_handler::request_control_change ( int side_num, const std::string& player )
@ -1943,7 +1960,8 @@ void menu_handler::custom_command()
void menu_handler::ai_formula()
{
if (!pc_.is_networked_mp()) {
textbox_info_.show(gui::TEXTBOX_AI, translation::sgettext("prompt^Command:"), "", false, *gui_);
textbox_info_.reset(new gui2::tfloating_textbox(*gui_, gui2::tfloating_textbox::AI, translation::sgettext("prompt^Command:")));
textbox_info_->show(gui_->video());
}
}

View file

@ -18,7 +18,6 @@
#include "global.hpp"
#include "chat_events.hpp"
#include "floating_textbox.hpp"
#include "units/map.hpp"
#include <vector>
@ -36,6 +35,11 @@ namespace events {
class mouse_handler;
}
namespace gui2 {
class tfloating_textbox;
}
class game_display;
struct fallback_ai_to_human_exception {};
namespace events {
@ -46,8 +50,9 @@ public:
const config& game_config);
virtual ~menu_handler();
gui::floating_textbox& get_textbox();
void set_gui(game_display* gui) { gui_ = gui; }
const std::shared_ptr<gui2::tfloating_textbox> get_textbox();
void close_textbox();
void set_gui(game_display* gui);
void objectives();
void show_statistics(int side_num);
@ -129,7 +134,6 @@ private:
const config& game_config_;
gui::floating_textbox textbox_info_;
std::string last_search_;
map_location last_search_hit_;
};

View file

@ -39,6 +39,7 @@
#include "gettext.hpp"
#include "gui/dialogs/loadscreen.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "floating_textbox.hpp"
#include "hotkey/command_executor.hpp"
#include "log.hpp"
#include "pathfind/teleport.hpp"
@ -581,44 +582,49 @@ bool play_controller::enemies_visible() const
void play_controller::enter_textbox()
{
if(menu_handler_.get_textbox().active() == false) {
if(!menu_handler_.get_textbox()) {
return;
}
const std::string str = menu_handler_.get_textbox().box()->text();
gui2::tfloating_textbox& box = *menu_handler_.get_textbox();
const std::string str = box.get_value();
const unsigned int team_num = current_side();
events::mouse_handler& mousehandler = mouse_handler_;
switch(menu_handler_.get_textbox().mode()) {
case gui::TEXTBOX_SEARCH:
switch(box.mode()) {
case gui2::tfloating_textbox::SEARCH:
menu_handler_.do_search(str);
menu_handler_.get_textbox().close(*gui_);
menu_handler_.close_textbox();
break;
case gui::TEXTBOX_MESSAGE:
case gui2::tfloating_textbox::MESSAGE:
menu_handler_.do_speak();
menu_handler_.get_textbox().close(*gui_); //need to close that one after executing do_speak() !
menu_handler_.close_textbox(); //need to close that one after executing do_speak() !
break;
case gui::TEXTBOX_COMMAND:
menu_handler_.get_textbox().close(*gui_);
case gui2::tfloating_textbox::COMMAND:
menu_handler_.close_textbox();
menu_handler_.do_command(str);
break;
case gui::TEXTBOX_AI:
menu_handler_.get_textbox().close(*gui_);
case gui2::tfloating_textbox::AI:
menu_handler_.close_textbox();
menu_handler_.do_ai_formula(str, team_num, mousehandler);
break;
default:
menu_handler_.get_textbox().close(*gui_);
menu_handler_.close_textbox();
ERR_DP << "unknown textbox mode" << std::endl;
}
}
void play_controller::tab()
{
gui::TEXTBOX_MODE mode = menu_handler_.get_textbox().mode();
if(!menu_handler_.get_textbox()) {
return;
}
gui2::tfloating_textbox::MODE mode = menu_handler_.get_textbox()->mode();
std::set<std::string> dictionary;
switch(mode) {
case gui::TEXTBOX_SEARCH:
case gui2::tfloating_textbox::SEARCH:
{
for (const unit& u : gamestate().board_.units()){
const map_location& loc = u.get_location();
@ -629,13 +635,13 @@ void play_controller::tab()
//TODO List map labels
break;
}
case gui::TEXTBOX_COMMAND:
case gui2::tfloating_textbox::COMMAND:
{
std::vector<std::string> commands = menu_handler_.get_commands_list();
dictionary.insert(commands.begin(), commands.end());
// no break here, we also want player names from the next case
}
case gui::TEXTBOX_MESSAGE:
case gui2::tfloating_textbox::MESSAGE:
{
for (const team& t : gamestate().board_.teams()) {
if(!t.is_empty())
@ -669,7 +675,7 @@ void play_controller::tab()
ERR_DP << "unknown textbox mode" << std::endl;
} //switch(mode)
menu_handler_.get_textbox().tab(dictionary);
menu_handler_.get_textbox()->tab(dictionary);
}
team& play_controller::current_team()
@ -752,13 +758,13 @@ game_display& play_controller::get_display()
bool play_controller::have_keyboard_focus()
{
return !menu_handler_.get_textbox().active();
return menu_handler_.get_textbox() == nullptr;
}
void play_controller::process_focus_keydown_event(const SDL_Event& event)
{
if(event.key.keysym.sym == SDLK_ESCAPE) {
menu_handler_.get_textbox().close(*gui_);
menu_handler_.close_textbox();
} else if(event.key.keysym.sym == SDLK_TAB) {
tab();
} else if(event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == SDLK_KP_ENTER) {

View file

@ -75,7 +75,7 @@ playsingle_controller::playsingle_controller(const config& level,
CVideo& video, bool skip_replay)
: play_controller(level, state_of_game, game_config, tdata, video, skip_replay)
, cursor_setter(cursor::NORMAL)
, textbox_info_()
// , textbox_info_()
, replay_sender_(*resources::recorder)
, network_reader_([this](config& cfg) {return recieve_from_wesnothd(cfg);})
, turn_data_(replay_sender_, network_reader_)

View file

@ -81,7 +81,7 @@ protected:
void store_gold(bool obs = false);
const cursor::setter cursor_setter;
gui::floating_textbox textbox_info_;
// std::unique_ptr<gui2::tfloating_textbox> textbox_info_;
replay_network_sender replay_sender_;
playturn_network_adapter network_reader_;