From 0e49adb27658d62f59f02464bcd0cb06381f16de Mon Sep 17 00:00:00 2001 From: fendrin Date: Sat, 13 Apr 2013 02:04:17 +0200 Subject: [PATCH] Based the editor palette on a new button like widget. --- src/CMakeLists.txt | 1 + src/SConscript | 1 + src/editor/palette/common_palette.hpp | 10 +- src/editor/palette/editor_palettes.cpp | 135 +++--- src/editor/palette/editor_palettes.hpp | 20 +- src/editor/palette/empty_palette.hpp | 12 +- src/editor/palette/palette_manager.cpp | 64 +-- src/editor/palette/palette_manager.hpp | 53 +-- src/editor/palette/terrain_palettes.cpp | 14 +- src/editor/palette/terrain_palettes.hpp | 2 +- src/editor/palette/tristate_button.cpp | 519 ++++++++++++++++++++++++ src/editor/palette/tristate_button.hpp | 121 ++++++ src/editor/palette/unit_palette.cpp | 6 +- src/editor/palette/unit_palette.hpp | 2 +- 14 files changed, 768 insertions(+), 192 deletions(-) create mode 100644 src/editor/palette/tristate_button.cpp create mode 100644 src/editor/palette/tristate_button.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a8f9b1c8808..4db9a6f8c99 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -659,6 +659,7 @@ set(wesnoth-main_SRC editor/map/map_context.cpp editor/map/map_fragment.cpp editor/palette/palette_manager.cpp + editor/palette/tristate_button.cpp editor/toolkit/brush.cpp editor/palette/editor_palettes.cpp editor/palette/terrain_palettes.cpp diff --git a/src/SConscript b/src/SConscript index 26ffb5c9f3f..5967d92bef7 100644 --- a/src/SConscript +++ b/src/SConscript @@ -235,6 +235,7 @@ wesnoth_sources = Split(""" editor/map/context_manager.cpp editor/palette/editor_palettes.cpp editor/palette/terrain_palettes.cpp + editor/palette/tristate_button.cpp editor/palette/unit_palette.cpp editor/palette/palette_manager.cpp editor/editor_controller.cpp diff --git a/src/editor/palette/common_palette.hpp b/src/editor/palette/common_palette.hpp index 3c02e9cdcbe..9ea17eced17 100644 --- a/src/editor/palette/common_palette.hpp +++ b/src/editor/palette/common_palette.hpp @@ -16,6 +16,7 @@ #define COMMON_PALETTES_H_INCLUDED #include "config.hpp" +#include "gui/widgets/widget.hpp" struct SDL_Rect; @@ -44,8 +45,11 @@ public: virtual ~common_palette() {} //event handling - virtual bool left_mouse_click(const int x, const int y) = 0; - virtual bool right_mouse_click(const int x, const int y) = 0; + + virtual handler_vector handler_members() { return handler_vector(); }; + + virtual void select_fg_item(const std::string& item_id) = 0; + virtual void select_bg_item(const std::string& item_id) = 0; /** Scroll the editor-palette up one step if possible. */ virtual bool scroll_up() = 0; @@ -57,7 +61,7 @@ public: //drawing virtual void adjust_size(const SDL_Rect& target) = 0; - virtual void draw(bool) = 0; + virtual void draw(bool force) = 0; //group virtual void set_group(size_t index) = 0; diff --git a/src/editor/palette/editor_palettes.cpp b/src/editor/palette/editor_palettes.cpp index db765ec5c13..90450f22ce2 100644 --- a/src/editor/palette/editor_palettes.cpp +++ b/src/editor/palette/editor_palettes.cpp @@ -28,6 +28,18 @@ namespace editor { +template +handler_vector editor_palette::handler_members() +{ + handler_vector h; + BOOST_FOREACH(gui::widget& b, buttons_) { + h.push_back(&b); + } + return h; +} +template handler_vector editor_palette::handler_members(); +template handler_vector editor_palette::handler_members(); + template void editor_palette::expand_palette_groups_menu(std::vector& items) { @@ -59,32 +71,6 @@ void editor_palette::expand_palette_groups_menu(std::vector& template void editor_palette::expand_palette_groups_menu(std::vector& items); template void editor_palette::expand_palette_groups_menu(std::vector& items); -template -bool editor_palette::left_mouse_click(const int mousex, const int mousey) -{ - int tselect = tile_selected(mousex, mousey); - if(tselect >= 0 && (items_start_+tselect) < active_group().size()) { - select_fg_item(active_group()[items_start_+tselect]); - return true; - } - return false; -} -template bool editor_palette::left_mouse_click(const int mousex, const int mousey); -template bool editor_palette::left_mouse_click(const int mousex, const int mousey); - -template -bool editor_palette::right_mouse_click(const int mousex, const int mousey) -{ - int tselect = tile_selected(mousex, mousey); - if(tselect >= 0 && (items_start_+tselect) < active_group().size()) { - select_bg_item(active_group()[items_start_+tselect]); - return true; - } - return false; -} -template bool editor_palette::right_mouse_click(const int mousex, const int mousey); -template bool editor_palette::right_mouse_click(const int mousex, const int mousey); - template bool editor_palette::scroll_up() { @@ -211,6 +197,7 @@ void editor_palette::adjust_size(const SDL_Rect& target) static_cast (space_for_items / item_space_) * item_width_; nitems_ = std::min(items_fitting, nmax_items_); + buttons_.resize(nitems_, gui::tristate_button(gui_.video(), "", this)); } template void editor_palette::adjust_size(const SDL_Rect& target); template void editor_palette::adjust_size(const SDL_Rect& target); @@ -253,9 +240,9 @@ template size_t editor_palette::num_items(); template size_t editor_palette::num_items(); template -void editor_palette::draw(bool dirty) +void editor_palette::draw(bool force) { - if (!dirty) return; + if (!force) return; unsigned int y = palette_y_; unsigned int x = palette_x_; unsigned int starting = items_start_; @@ -269,47 +256,25 @@ void editor_palette::draw(bool dirty) gui::button* downscroll_button = gui_.find_button("downscroll-button-editor"); downscroll_button->enable(ending != num_items()); - for(unsigned int counter = starting; counter < ending; counter++){ - const int counter_from_zero = counter - starting; - SDL_Rect dstrect; - dstrect.x = x + (counter_from_zero % item_width_) * item_space_; - dstrect.y = y; - dstrect.w = item_size_; - dstrect.h = item_size_; + unsigned int counter = starting; + for (unsigned int i = 0 ; i < buttons_.size() ; i++) { + //TODO check if the conditions still hold for the counter variable + //for (unsigned int counter = starting; counter < ending; counter++) - std::stringstream tooltip_text; + gui::tristate_button& tile = buttons_[i]; + + tile.hide(true); + + if (i >= ending) continue; const std::string item_id = active_group()[counter]; - typedef std::map item_map_wurscht; - typename item_map_wurscht::iterator item = item_map_.find(item_id); - draw_item(dstrect, (*item).second, tooltip_text); - - surface screen = gui_.video().getSurface(); - Uint32 color; - - if (get_id((*item).second) == selected_bg_item_ - && get_id((*item).second) == selected_fg_item_) { - color = SDL_MapRGB(screen->format,0xFF,0x00,0xFF); - } - else if (get_id((*item).second) == selected_bg_item_) { - color = SDL_MapRGB(screen->format,0x00,0x00,0xFF); - } - else if (get_id((*item).second) == selected_fg_item_) { - color = SDL_MapRGB(screen->format,0xFF,0x00,0x00); - } - else { - color = SDL_MapRGB(screen->format,0x00,0x00,0x00); - } - - draw_rectangle(dstrect.x, dstrect.y, dstrect.w, dstrect.h, color, screen); - /* TODO The call above overdraws the border of the terrain image. - The following call is doing better but causing other drawing glitches. - draw_rectangle(dstrect.x -1, dstrect.y -1, image->w +2, image->h +2, color, screen); - */ + surface item_image(NULL); + std::stringstream tooltip_text; + draw_item((*item).second, item_image, tooltip_text); bool is_core = non_core_items_.find(get_id((*item).second)) == non_core_items_.end(); if (!is_core) { @@ -319,29 +284,41 @@ void editor_palette::draw(bool dirty) << _("Will not work in game without extra care.") << ""; } - tooltips::add_tooltip(dstrect, tooltip_text.str()); + + const int counter_from_zero = counter - starting; + SDL_Rect dstrect; + dstrect.x = x + (counter_from_zero % item_width_) * item_space_; + dstrect.y = y; + dstrect.w = item_size_ + 2; + dstrect.h = item_size_ + 2; + + tile.set_location(dstrect); + tile.set_help_string(tooltip_text.str()); + tile.set_item_image(item_image); + tile.set_item_id(item_id); + + if (get_id((*item).second) == selected_bg_item_ + && get_id((*item).second) == selected_fg_item_) { + tile.set_pressed(gui::tristate_button::BOTH); + } else if (get_id((*item).second) == selected_bg_item_) { + tile.set_pressed(gui::tristate_button::RIGHT); + } else if (get_id((*item).second) == selected_fg_item_) { + tile.set_pressed(gui::tristate_button::LEFT); + } else { + tile.set_pressed(gui::tristate_button::NONE); + } + + tile.set_dirty(true); + tile.hide(false); + + // Adjust location if (counter_from_zero % item_width_ == item_width_ - 1) y += item_space_; + counter++; } } template void editor_palette::draw(bool); template void editor_palette::draw(bool); -template -int editor_palette::tile_selected(const int x, const int y) const -{ - for(unsigned int i = 0; i != nitems_; i++) { - const int px = palette_x_ + (i % item_width_) * item_space_; - const int py = palette_y_ + (i / item_width_) * item_space_; - const int pw = item_space_; - const int ph = item_space_; - - if(x > px && x < px + pw && y > py && y < py + ph) { - return i; - } - } - return -1; -} - } // end namespace editor diff --git a/src/editor/palette/editor_palettes.hpp b/src/editor/palette/editor_palettes.hpp index 49ced9035e0..8e2c0e7261e 100644 --- a/src/editor/palette/editor_palettes.hpp +++ b/src/editor/palette/editor_palettes.hpp @@ -17,6 +17,7 @@ #include "../editor_display.hpp" #include "common_palette.hpp" +#include "tristate_button.hpp" namespace editor { @@ -31,7 +32,8 @@ public: , gui_(gui) , item_size_(item_size) , item_width_(item_width) - , item_space_(item_size + 3) +//TODO avoid magic number + , item_space_(item_size + 5) , palette_y_(0) , palette_x_(0) , group_map_() @@ -44,9 +46,12 @@ public: , selected_fg_item_() , selected_bg_item_() , active_mouse_action_(active_mouse_action) + , buttons_() { }; + virtual handler_vector handler_members(); + void set_start_item(size_t index) { items_start_ = index; }; size_t start_num(void) { return items_start_; }; @@ -58,10 +63,7 @@ public: const std::vector& get_groups() const { return groups_; }; - virtual void draw(bool); - - bool left_mouse_click(const int, const int); - bool right_mouse_click(const int, const int); + virtual void draw(bool force); void next_group() { set_group( (active_group_index() +1) % (groups_.size() -1) ); @@ -92,9 +94,6 @@ public: private: - /** Return the number of the tile that is at coordinates (x, y) in the panel. */ - int tile_selected(const int x, const int y) const; - /** TODO */ size_t active_group_index(); @@ -104,7 +103,7 @@ private: /** Scroll the editor-palette to the bottom. */ void scroll_bottom(); - virtual void draw_item(SDL_Rect& dstrect, const Item& item, std::stringstream& tooltip) = 0; + virtual void draw_item(const Item& item, surface& item_image, std::stringstream& tooltip) = 0; virtual const std::string& get_id(const Item& item) = 0; @@ -116,7 +115,7 @@ private: /** Return the number of items in the palette. */ size_t num_items(); - void draw_old(bool); + //void draw_old(bool); protected: /** @@ -163,6 +162,7 @@ private: std::string selected_bg_item_; mouse_action** active_mouse_action_; + std::vector buttons_; }; diff --git a/src/editor/palette/empty_palette.hpp b/src/editor/palette/empty_palette.hpp index b9ce23492f3..fb84c4fd6f8 100644 --- a/src/editor/palette/empty_palette.hpp +++ b/src/editor/palette/empty_palette.hpp @@ -31,25 +31,32 @@ public: empty_palette(display& gui) : gui_(gui), empty_() {}; //event handling - virtual bool left_mouse_click(const int /*x*/, const int /*y*/) { return false;}; - virtual bool right_mouse_click(const int /*x*/, const int /*y*/) { return false;}; + virtual bool mouse_click() { return false;}; virtual bool scroll_up() { return false;}; virtual bool can_scroll_up() { return false;}; virtual bool scroll_down() { return false;}; virtual bool can_scroll_down() { return false;}; + virtual void select_fg_item(const std::string& /*item_id*/) {}; + virtual void select_bg_item(const std::string& /*item_id*/) {}; + //drawing virtual void adjust_size(const SDL_Rect& /*target*/) {}; virtual void draw(bool) { + //TODO + /* gui::button* upscroll_button = gui_.find_button("upscroll-button-editor"); upscroll_button->hide(true); gui::button* downscroll_button = gui_.find_button("downscroll-button-editor"); downscroll_button->hide(true); gui::button* palette_menu_button = gui_.find_button("menu-editor-terrain"); palette_menu_button->hide(true); + */ }; + std::vector* get_widgets() { return NULL; }; + //group virtual void set_group(size_t /*index*/) {}; virtual void next_group() {}; @@ -69,7 +76,6 @@ public: private: display& gui_; std::vector empty_; - }; diff --git a/src/editor/palette/palette_manager.cpp b/src/editor/palette/palette_manager.cpp index 9042e830eb1..eb549f79b8b 100644 --- a/src/editor/palette/palette_manager.cpp +++ b/src/editor/palette/palette_manager.cpp @@ -19,6 +19,7 @@ #include "tooltips.hpp" #include "editor/action/mouse/mouse_action.hpp" +#include namespace editor { @@ -127,46 +128,39 @@ void palette_manager::draw(bool force) gui::button* palette_menu_button = gui_.find_button("menu-editor-terrain"); palette_menu_button->hide(false); - active_palette().draw(force); + bg_restore(loc); + active_palette().draw(dirty() || force); update_rect(loc); set_dirty(false); } +handler_vector palette_manager::handler_members() +{ + //handler_vector h; +// BOOST_FOREACH(gui::widget& b, active_palette().get_widgets()) { +// h.push_back(&b); +// } + //return h; + return active_palette().handler_members(); +} + void palette_manager::handle_event(const SDL_Event& event) { if (event.type == SDL_MOUSEMOTION) { // If the mouse is inside the palette, give it focus. if (point_in_rect(event.button.x, event.button.y, location())) { - if (!focus(&event)) { - set_focus(true); - } + if (!focus(&event)) set_focus(true); } // If the mouse is outside, remove focus. - else { - if (focus(&event)) { - set_focus(false); - } - } + else if (focus(&event)) set_focus(false); } if (!focus(&event)) { return; } - int mousex, mousey; - SDL_GetMouseState(&mousex,&mousey); + const SDL_MouseButtonEvent mouse_button_event = event.button; if (mouse_button_event.type == SDL_MOUSEBUTTONDOWN) { - if (mouse_button_event.button == SDL_BUTTON_LEFT) { - left_mouse_click(mousex, mousey); - } - /* TODO - if (mouse_button_event.button == SDL_BUTTON_MIDDLE) { - middle_mouse_click(mousex, mousey); - } - */ - if (mouse_button_event.button == SDL_BUTTON_RIGHT) { - right_mouse_click(mousex, mousey); - } if (mouse_button_event.button == SDL_BUTTON_WHEELUP) { scroll_up(); } @@ -181,30 +175,16 @@ void palette_manager::handle_event(const SDL_Event& event) { active_palette().next_group(); scroll_top(); } + //set_dirty(true); } + if (mouse_button_event.type == SDL_MOUSEBUTTONUP) { - if (mouse_button_event.button == SDL_BUTTON_LEFT) { - //TODO What is missing here? - } - } -} - -void palette_manager::left_mouse_click(const int mousex, const int mousey) -{ - if ( active_palette().left_mouse_click(mousex, mousey) ) { - set_dirty(); - gui_.invalidate_game_status(); - } -} - -void palette_manager::right_mouse_click(const int mousex, const int mousey) -{ - if ( active_palette().right_mouse_click(mousex, mousey) ) { - set_dirty(); - gui_.invalidate_game_status(); + //set_dirty(true); +// draw(true); +// set_dirty(active_palette().mouse_click()); +// gui_.invalidate_game_status(); } } } //Namespace editor - diff --git a/src/editor/palette/palette_manager.hpp b/src/editor/palette/palette_manager.hpp index 816db04f385..ebdc08ba990 100644 --- a/src/editor/palette/palette_manager.hpp +++ b/src/editor/palette/palette_manager.hpp @@ -21,9 +21,9 @@ #include "common_palette.hpp" +#include "empty_palette.hpp" #include "terrain_palettes.hpp" #include "unit_palette.hpp" -#include "empty_palette.hpp" namespace editor { @@ -32,81 +32,54 @@ class palette_manager : public gui::widget { public: - //palette_manager(); - palette_manager(editor_display &gui, const config& cfg , mouse_action** active_mouse_action); void set_group(size_t index); -// virtual size_t active_group_index(); - -// virtual const std::vector& get_groups(); - /** Scroll the editor-palette up one step if possible. */ void scroll_up(); - - bool can_scroll_down(); - bool can_scroll_up(); - /** Scroll the editor-palette down one step if possible. */ void scroll_down(); - void scroll_top(); + bool can_scroll_up(); + bool can_scroll_down(); + void scroll_top(); void scroll_bottom(); -// virtual void swap(); +//TODO +// void swap(); void adjust_size(); + handler_vector handler_members(); + virtual void handle_event(const SDL_Event& event); + /** * Draw the palette. * * If force is true everything will be redrawn, * even though it is not invalidated. */ - - virtual void handle_event(const SDL_Event& event); - void draw(bool force=false); - void draw() { draw(true); }; - - /** - * To be called when a mouse click occurs. - * - * Check if the coordinates is a terrain that may be chosen, - * and select the terrain if that is the case. - */ - void left_mouse_click(const int mousex, const int mousey); - void right_mouse_click(const int mousex, const int mousey); - - /** Return the number of the tile that is at coordinates (x, y) in the panel. */ - //TODO -// int tile_selected(const int x, const int y) const; - + void draw() { draw(false); }; public: common_palette& active_palette(); - //TODO { return (*mouse_action_)->get_palette(); }; - - //TODO -// terrain_palette* terrain_palette() { return terrain_palette_; }; -// unit_palette* unit_palette() { return unit_palette_; }; -// empty_palette* empty_palette() { return empty_palette_; }; private: editor_display& gui_; int palette_start_; - mouse_action** mouse_action_; public: + boost::scoped_ptr terrain_palette_; - boost::scoped_ptr unit_palette_; - boost::scoped_ptr empty_palette_; + boost::scoped_ptr unit_palette_; + boost::scoped_ptr empty_palette_; }; diff --git a/src/editor/palette/terrain_palettes.cpp b/src/editor/palette/terrain_palettes.cpp index 63d192141e6..2a5f99db1f7 100644 --- a/src/editor/palette/terrain_palettes.cpp +++ b/src/editor/palette/terrain_palettes.cpp @@ -166,11 +166,11 @@ void terrain_palette::setup(const config& cfg) // update_report(); } -void terrain_palette::draw_item(SDL_Rect& dstrect, const t_translation::t_terrain& terrain, std::stringstream& tooltip_text) { +void terrain_palette::draw_item(const t_translation::t_terrain& terrain, + surface& image, std::stringstream& tooltip_text) { - const t_translation::t_terrain base_terrain = map().get_terrain_info(terrain).default_base(); - - surface screen = gui_.video().getSurface(); + const t_translation::t_terrain base_terrain = + map().get_terrain_info(terrain).default_base(); //Draw default base for overlay terrains if(base_terrain != t_translation::NONE_TERRAIN) { @@ -191,12 +191,10 @@ void terrain_palette::draw_item(SDL_Rect& dstrect, const t_translation::t_terrai base_image.assign(scale_surface(base_image, item_size_, item_size_)); } - - sdl_blit(base_image, NULL, screen, &dstrect); } const std::string filename = "terrain/" + map().get_terrain_info(terrain).editor_image() + ".png"; - surface image(image::get_image(filename)); + image = surface(image::get_image(filename)); if(image == NULL) { tooltip_text << "IMAGE NOT FOUND\n"; ERR_ED << "image for terrain: '" << filename << "' not found\n"; @@ -212,8 +210,6 @@ void terrain_palette::draw_item(SDL_Rect& dstrect, const t_translation::t_terrai item_size_, item_size_)); } - sdl_blit(image, NULL, screen, &dstrect); - tooltip_text << map().get_terrain_editor_string(terrain); if (gui_.get_draw_terrain_codes()) { tooltip_text << " " + utils::unicode_em_dash + " " << terrain; diff --git a/src/editor/palette/terrain_palettes.hpp b/src/editor/palette/terrain_palettes.hpp index e99ea4540b3..09ac8fa3727 100644 --- a/src/editor/palette/terrain_palettes.hpp +++ b/src/editor/palette/terrain_palettes.hpp @@ -52,7 +52,7 @@ private: virtual const std::string& get_id(const t_translation::t_terrain& terrain); - virtual void draw_item(SDL_Rect& dstrect, const t_translation::t_terrain& terrain, std::stringstream& tooltip_text); + virtual void draw_item(const t_translation::t_terrain& terrain, surface& item_image, std::stringstream& tooltip_text); virtual void update_report(); }; diff --git a/src/editor/palette/tristate_button.cpp b/src/editor/palette/tristate_button.cpp new file mode 100644 index 00000000000..75c08097ad6 --- /dev/null +++ b/src/editor/palette/tristate_button.cpp @@ -0,0 +1,519 @@ +/* + Copyright (C) 2003 - 2013 by David White + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#include "global.hpp" + +#include "tristate_button.hpp" + +#include "font.hpp" +#include "game_config.hpp" +#include "image.hpp" +#include "log.hpp" +#include "marked-up_text.hpp" +#include "serialization/string_utils.hpp" +#include "sound.hpp" +#include "video.hpp" +#include "wml_separators.hpp" + +static lg::log_domain log_display("display"); +#define ERR_DP LOG_STREAM(err, log_display) + +namespace gui { + +const int font_size = font::SIZE_SMALL; +const int horizontal_padding = font::SIZE_SMALL; +const int checkbox_horizontal_padding = font::SIZE_SMALL / 2; +const int vertical_padding = font::SIZE_SMALL / 2; + +tristate_button::tristate_button(CVideo& video, const std::string& label, + editor::common_palette* palette, + std::string button_image_name, SPACE_CONSUMPTION spacing, + const bool auto_join) : + widget(video, auto_join) + , label_(label), + + baseImage_(NULL), touchedBaseImage_(NULL), activeBaseImage_(NULL), + + itemImage_(NULL), + +// normalImage_(NULL), activeImage_(NULL), + pressedDownImage_(NULL), pressedUpImage_(NULL), pressedBothImage_(NULL), + pressedBothActiveImage_(NULL), pressedDownActiveImage_(NULL), pressedUpActiveImage_(NULL), + touchedDownImage_(NULL), touchedUpImage_(NULL), touchedBothImage_(NULL), +// disabledImage_(NULL), pressedDownDisabledImage_(NULL), +// pressedUpDisabledImage_(NULL), pressedBothDisabledImage_(NULL), + + state_(NORMAL), pressed_(false), + spacing_(spacing), base_height_(0), base_width_(0) + , palette_(palette), item_id_() +{ + + if (button_image_name.empty()) { + button_image_name = "buttons/editor/palette/"; + } + + baseImage_.assign( + image::get_image(button_image_name + "base.png")); + activeBaseImage_.assign( + image::get_image(button_image_name + "base-active.png")); + touchedBaseImage_.assign( + image::get_image(button_image_name + "base-touched.png")); + + touchedBothImage_.assign( + image::get_image(button_image_name + "touched-both.png")); + touchedUpImage_.assign( + image::get_image(button_image_name + "touched-up.png")); + touchedDownImage_.assign( + image::get_image(button_image_name + "touched-down.png")); + + pressedUpImage_.assign( + image::get_image(button_image_name + "pressed-up.png")); + pressedDownImage_.assign( + image::get_image(button_image_name + "pressed-down.png")); + pressedBothImage_.assign( + image::get_image(button_image_name + "pressed-both.png")); + + pressedUpActiveImage_.assign( + image::get_image(button_image_name + "active-pressed-up.png")); + pressedDownActiveImage_.assign( + image::get_image(button_image_name + "active-pressed-down.png")); + pressedBothActiveImage_.assign( + image::get_image(button_image_name + "active-pressed-both.png")); + +// if (button_image.null()) { +// ERR_DP<< "error initializing button!\n"; +// throw error(); +// } + + base_height_ = baseImage_->h; + base_width_ = baseImage_->w; + +// calculate_size(); + +} + +tristate_button::~tristate_button() { +} + +void tristate_button::calculate_size() { + +// TODO +// if (type_ == TYPE_IMAGE){ +// SDL_Rect loc_image = location(); +// loc_image.h = normalImage_->h; +// loc_image.w = normalImage_->w; +// set_location(loc_image); +// return; +// } + + SDL_Rect const &loc = location(); + bool change_size = loc.h == 0 || loc.w == 0; + + if (!change_size) { + unsigned w = loc.w - (checkbox_horizontal_padding + base_width_); + + int fs = font_size; + int style = TTF_STYLE_NORMAL; + std::string::const_iterator i_beg = label_.begin(), i_end = + label_.end(), i = font::parse_markup(i_beg, i_end, &fs, NULL, + &style); + if (i != i_end) { + std::string tmp(i, i_end); + label_.erase(i - i_beg, i_end - i_beg); + label_ += font::make_text_ellipsis(tmp, fs, w, style); + } + } + + textRect_ = font::draw_text(NULL, screen_area(), font_size, + font::BUTTON_COLOR, label_, 0, 0); + + if (!change_size) + return; + + set_height(std::max(textRect_.h + vertical_padding, base_height_)); + + if (label_.empty()) { + set_width(base_width_); + } else { + set_width(checkbox_horizontal_padding + textRect_.w + base_width_); + } + +} + +void tristate_button::set_pressed(PRESSED_STATE new_pressed_state) { + + STATE new_state; + + switch (new_pressed_state) { + case LEFT: + new_state = PRESSED_LEFT; + break; + case RIGHT: + new_state = PRESSED_RIGHT; + break; + case BOTH: + new_state = PRESSED_BOTH; + break; + case NONE: + new_state = NORMAL; + } + +// if (check) { +// new_state = +// (state_ == ACTIVE || state_ == PRESSED_ACTIVE) ? +// PRESSED_ACTIVE : PRESSED; +// } else { +// new_state = +// (state_ == ACTIVE || state_ == PRESSED_ACTIVE) ? +// ACTIVE : NORMAL; +// } + + if (state_ != new_state) { + state_ = new_state; + set_dirty(); + } +} + +//void tristate_button::set_active(bool active) { +// if ((state_ == NORMAL) && active) { +// state_ = ACTIVE; +// set_dirty(); +// } else if ((state_ == ACTIVE) && !active) { +// state_ = NORMAL; +// set_dirty(); +// } +//} +// +tristate_button::PRESSED_STATE tristate_button::pressed_state() const { + + switch (state_) { + case PRESSED_LEFT: + case PRESSED_ACTIVE_LEFT: + case TOUCHED_BOTH_LEFT: + return LEFT; + case PRESSED_RIGHT: + case PRESSED_ACTIVE_RIGHT: + case TOUCHED_BOTH_RIGHT: + return RIGHT; + case PRESSED_BOTH: + case PRESSED_ACTIVE_BOTH: + return BOTH; + default: + return NONE; + break; + } + return NONE; +} + +void tristate_button::enable(bool new_val) { + if (new_val != enabled()) { + pressed_ = false; + // check buttons should keep their state + state_ = NORMAL; + + widget::enable(new_val); + } +} + +void tristate_button::draw_contents() { + + surface image(NULL); + + surface overlay(NULL); + surface base = baseImage_; + + int offset = 0; + switch (state_) { + + case UNINIT: + return; + + case NORMAL: + break; + + case TOUCHED_LEFT: + overlay = touchedUpImage_; + base = touchedBaseImage_; + break; + case TOUCHED_RIGHT: + overlay = touchedDownImage_; + base = touchedBaseImage_; + break; + case TOUCHED_BOTH_LEFT: + case TOUCHED_BOTH_RIGHT: + overlay = touchedBothImage_; + base = touchedBaseImage_; + break; + case ACTIVE: + // overlay = activeImage_; + base = activeBaseImage_; + break; + case PRESSED_LEFT: + overlay = pressedUpImage_; + break; + case PRESSED_RIGHT: + overlay = pressedDownImage_; + break; + case PRESSED_BOTH: + overlay = pressedBothImage_; + break; + case PRESSED_ACTIVE_LEFT: + overlay = pressedUpActiveImage_; + base = activeBaseImage_; + break; + case PRESSED_ACTIVE_BOTH: + overlay = pressedBothActiveImage_; + base = activeBaseImage_; + break; + case PRESSED_ACTIVE_RIGHT: + overlay = pressedDownActiveImage_; + base = activeBaseImage_; + break; + } + + image = base; + + const int image_w = image->w; + SDL_Rect const &loc = location(); + SDL_Rect clipArea = loc; + const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset; + int textx; + + clipArea.w += image_w + checkbox_horizontal_padding; + textx = loc.x + image_w + checkbox_horizontal_padding / 2; + + SDL_Color button_color = font::BUTTON_COLOR; + + // blit_surface want neutral surfaces + surface nitem = make_neutral_surface(itemImage_); + surface nbase = make_neutral_surface(base); + + //TODO avoid magic numbers + SDL_Rect r = create_rect(1, 1, 0, 0); + blit_surface(nitem, NULL, nbase, &r); + + if (!overlay.null()) { + surface noverlay = make_neutral_surface(overlay); + blit_surface(noverlay, NULL, nbase, NULL); + } + +// TODO for later reference +// SDL_SetAlpha(nbase, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); +// SDL_SetAlpha(image, 0, 0); +// +// TODO might be needed. + bg_restore(); + + image = nbase; + video().blit_surface(loc.x, loc.y, image); + + clipArea.x += offset; + clipArea.y += offset; + clipArea.w -= 2 * offset; + clipArea.h -= 2 * offset; + font::draw_text(&video(), clipArea, font_size, button_color, label_, textx, + texty); + + update_rect(loc); +} + +//TODO move to widget +bool tristate_button::hit(int x, int y) const { + return point_in_rect(x, y, location()); +} + +static bool not_image(const std::string& str) { + return !str.empty() && str[0] != IMAGE_PREFIX; +} + +void tristate_button::set_label(const std::string& val) { + label_ = val; + + //if we have a list of items, use the first one that isn't an image + if (std::find(label_.begin(), label_.end(), COLUMN_SEPARATOR) + != label_.end()) { + const std::vector& items = utils::split(label_, + COLUMN_SEPARATOR); + const std::vector::const_iterator i = std::find_if( + items.begin(), items.end(), not_image); + if (i != items.end()) { + label_ = *i; + } + } + + calculate_size(); + set_dirty(true); +} + +void tristate_button::mouse_motion(SDL_MouseMotionEvent const &event) { + + if (hit(event.x, event.y)) + { // the cursor is over the widget + + switch (state_) { + + case UNINIT: + return; + + case NORMAL: + state_ = ACTIVE; + break; + case PRESSED_LEFT: + state_ = PRESSED_ACTIVE_LEFT; + break; + case PRESSED_RIGHT: + state_ = PRESSED_ACTIVE_RIGHT; + break; + case PRESSED_BOTH: + state_ = PRESSED_ACTIVE_BOTH; + break; + default: + //assert(false); + break; + } + + } else { // the cursor is not over the widget + + switch (state_) { + + case ACTIVE: + state_ = NORMAL; + break; + case TOUCHED_LEFT: + case TOUCHED_RIGHT: + state_ = ACTIVE; + break; + case PRESSED_ACTIVE_RIGHT: + case TOUCHED_BOTH_RIGHT: + state_ = PRESSED_RIGHT; + break; + case PRESSED_ACTIVE_BOTH: + state_ = PRESSED_BOTH; + break; + case PRESSED_ACTIVE_LEFT: + case TOUCHED_BOTH_LEFT: + state_ = PRESSED_LEFT; + break; + default: + break; + } + } +} + +void tristate_button::mouse_down(SDL_MouseButtonEvent const &event) { + + if (!hit(event.x, event.y)) + return; + + if (event.button == SDL_BUTTON_RIGHT) { + if (state_ == ACTIVE) + state_ = TOUCHED_RIGHT; + if (state_ == PRESSED_ACTIVE_LEFT) + state_ = TOUCHED_BOTH_LEFT; + } + + if (event.button == SDL_BUTTON_LEFT) { + if (state_ == ACTIVE) + state_ = TOUCHED_LEFT; + if (state_ == PRESSED_ACTIVE_RIGHT) + state_ = TOUCHED_BOTH_RIGHT; + } + +} + +void tristate_button::release() { + state_ = NORMAL; + draw_contents(); +} + +void tristate_button::mouse_up(SDL_MouseButtonEvent const &event) { + + if (!(hit(event.x, event.y))) + return; + + // the user has stopped pressing the mouse left button while on the widget + if (event.button == SDL_BUTTON_LEFT) { + + if (state_ == TOUCHED_LEFT) { + state_ = PRESSED_ACTIVE_LEFT; + palette_->select_fg_item(item_id_); + palette_->draw(true); + pressed_ = true; + } + if (state_ == TOUCHED_BOTH_RIGHT) { + state_ = PRESSED_ACTIVE_BOTH; + palette_->select_fg_item(item_id_); + palette_->select_bg_item(item_id_); + palette_->draw(true); + pressed_ = true; + } + } + + if (event.button == SDL_BUTTON_RIGHT) { + + if (state_ == TOUCHED_RIGHT) { + state_ = PRESSED_ACTIVE_RIGHT; + palette_->select_bg_item(item_id_); + palette_->draw(true); + pressed_ = true; + } + if (state_ == TOUCHED_BOTH_LEFT) { + state_ = PRESSED_ACTIVE_BOTH; + palette_->select_fg_item(item_id_); + palette_->select_bg_item(item_id_); + palette_->draw(true); + pressed_ = true; + } + } + + if (pressed_) + sound::play_UI_sound(game_config::sounds::checkbox_release); +} + +void tristate_button::handle_event(const SDL_Event& event) { + + if (hidden() || !enabled()) + return; + + STATE start_state = state_; + + if (!mouse_locked()) { + switch (event.type) { + case SDL_MOUSEBUTTONDOWN: + mouse_down(event.button); + break; + case SDL_MOUSEBUTTONUP: + mouse_up(event.button); + break; + case SDL_MOUSEMOTION: + mouse_motion(event.motion); + break; + default: + return; + } + } + + if (start_state != state_) + set_dirty(true); +} + +bool tristate_button::pressed() { + const bool res = pressed_; + pressed_ = false; + return res; +} + +} diff --git a/src/editor/palette/tristate_button.hpp b/src/editor/palette/tristate_button.hpp new file mode 100644 index 00000000000..84ced5f2961 --- /dev/null +++ b/src/editor/palette/tristate_button.hpp @@ -0,0 +1,121 @@ +/* + Copyright (C) 2003 - 2013 by David White + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ +#ifndef TRISTATE_BUTTON_H_INCLUDED +#define TRISTATE_BUTTON_H_INCLUDED + +#include "widgets/widget.hpp" + +#include "exceptions.hpp" +#include "editor/palette/common_palette.hpp" + +namespace gui { + +class tristate_button : public widget +{ + +public: + + struct error : public game::error { + error() + : game::error("GUI1 tristate button error") + {} + }; + + enum PRESSED_STATE { LEFT, RIGHT, BOTH, NONE }; + + enum SPACE_CONSUMPTION { DEFAULT_SPACE, MINIMUM_SPACE }; + + tristate_button(CVideo& video, const std::string& label, + editor::common_palette* palette, + std::string button_image="", + SPACE_CONSUMPTION spacing=DEFAULT_SPACE, + const bool auto_join=true); + + /** Default implementation, but defined out-of-line for efficiency reasons. */ + virtual ~tristate_button(); + + void set_pressed(PRESSED_STATE new_pressed_state); + + // void set_active(bool active); + + bool pressed(); + PRESSED_STATE pressed_state() const; + + void set_label(const std::string& val); + + bool hit(int x, int y) const; + virtual void enable(bool new_val=true); + void release(); + + void set_item_image( + const surface& image) + { + itemImage_ = image; + } + + void set_item_id(const std::string& id) { + item_id_ = id; + } + + +protected: + + virtual void handle_event(const SDL_Event& event); + virtual void mouse_motion(const SDL_MouseMotionEvent& event); + virtual void mouse_down(const SDL_MouseButtonEvent& event); + virtual void mouse_up(const SDL_MouseButtonEvent& event); + + virtual void draw_contents(); + +private: + + void calculate_size(); + + std::string label_; + + surface baseImage_, touchedBaseImage_, activeBaseImage_, + itemImage_, + // normalImage_, activeImage_, + pressedDownImage_, pressedUpImage_, pressedBothImage_, + pressedBothActiveImage_, pressedDownActiveImage_, pressedUpActiveImage_, + touchedDownImage_, touchedUpImage_, touchedBothImage_; + // disabledImage_, pressedDownDisabledImage_, pressedUpDisabledImage_, pressedBothDisabledImage_; + + SDL_Rect textRect_; + + enum STATE { UNINIT, + NORMAL, ACTIVE, + PRESSED_ACTIVE_LEFT, PRESSED_ACTIVE_RIGHT, PRESSED_ACTIVE_BOTH, + TOUCHED_RIGHT, TOUCHED_BOTH_RIGHT, TOUCHED_BOTH_LEFT, TOUCHED_LEFT, + PRESSED_LEFT, PRESSED_RIGHT, PRESSED_BOTH + }; + + + STATE state_; + + bool pressed_; + + SPACE_CONSUMPTION spacing_; + + int base_height_, base_width_; + + editor::common_palette* palette_; + + std::string item_id_; + +}; //end class button + +} + +#endif diff --git a/src/editor/palette/unit_palette.cpp b/src/editor/palette/unit_palette.cpp index 46c8537f84c..d550fd2dd5f 100644 --- a/src/editor/palette/unit_palette.cpp +++ b/src/editor/palette/unit_palette.cpp @@ -89,7 +89,7 @@ void unit_palette::setup(const config& /*cfg*/) // update_report(); } -void unit_palette::draw_item(SDL_Rect& dstrect, const unit_type& u, std::stringstream& tooltip_text) { +void unit_palette::draw_item(const unit_type& u, surface& image, std::stringstream& tooltip_text) { surface screen = gui_.video().getSurface(); @@ -97,7 +97,7 @@ void unit_palette::draw_item(SDL_Rect& dstrect, const unit_type& u, std::strings filename << u.image() << "~RC(" << u.flag_rgb() << '>' << team::get_side_color_index(gui_.viewing_side()) << ')'; - surface image(image::get_image(filename.str())); + image = surface(image::get_image(filename.str())); if(image == NULL) { tooltip_text << "IMAGE NOT FOUND\n"; ERR_ED << "image for unit type: '" << filename.str() << "' not found\n"; @@ -113,8 +113,6 @@ void unit_palette::draw_item(SDL_Rect& dstrect, const unit_type& u, std::strings item_size_, item_size_)); } - sdl_blit(image, NULL, screen, &dstrect); - tooltip_text << u.type_name(); } diff --git a/src/editor/palette/unit_palette.hpp b/src/editor/palette/unit_palette.hpp index af1c7b3f533..8dd1c869314 100644 --- a/src/editor/palette/unit_palette.hpp +++ b/src/editor/palette/unit_palette.hpp @@ -38,7 +38,7 @@ public: private: virtual const std::string& get_id(const unit_type& terrain); - virtual void draw_item(SDL_Rect& dstrect, const unit_type& terrain, std::stringstream& tooltip_text); + virtual void draw_item(const unit_type& terrain, surface& image, std::stringstream& tooltip_text); // virtual void update_report();