mouse_handler_base.cpp

Go to the documentation of this file.
00001 /* $Id: mouse_handler_base.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2006 - 2012 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
00004    wesnoth playturn Copyright (C) 2003 by David White <dave@whitevine.net>
00005    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY.
00013 
00014    See the COPYING file for more details.
00015 */
00016 
00017 #include "mouse_handler_base.hpp"
00018 
00019 #include "cursor.hpp"
00020 #include "display.hpp"
00021 #include "log.hpp"
00022 #include "preferences.hpp"
00023 #include "tooltips.hpp"
00024 
00025 static lg::log_domain log_display("display");
00026 #define WRN_DP LOG_STREAM(warn, log_display)
00027 
00028 namespace events {
00029 
00030 command_disabler::command_disabler()
00031 {
00032     ++commands_disabled;
00033 }
00034 
00035 command_disabler::~command_disabler()
00036 {
00037     --commands_disabled;
00038 }
00039 
00040 int commands_disabled= 0;
00041 
00042 static bool command_active()
00043 {
00044 #ifdef __APPLE__
00045     return (SDL_GetModState()&KMOD_META) != 0;
00046 #else
00047     return false;
00048 #endif
00049 }
00050 
00051 mouse_handler_base::mouse_handler_base() :
00052     simple_warp_(false),
00053     minimap_scrolling_(false),
00054     dragging_left_(false),
00055     dragging_started_(false),
00056     dragging_right_(false),
00057     drag_from_x_(0),
00058     drag_from_y_(0),
00059     drag_from_hex_(),
00060     last_hex_(),
00061     show_menu_(false)
00062 {
00063 }
00064 
00065 bool mouse_handler_base::is_dragging() const
00066 {
00067     return dragging_left_ || dragging_right_;
00068 }
00069 
00070 void mouse_handler_base::mouse_motion_event(const SDL_MouseMotionEvent& event, const bool browse)
00071 {
00072     mouse_motion(event.x,event.y, browse);
00073 }
00074 
00075 void mouse_handler_base::mouse_update(const bool browse, map_location loc)
00076 {
00077     int x, y;
00078     SDL_GetMouseState(&x,&y);
00079     mouse_motion(x, y, browse, true, loc);
00080 }
00081 
00082 bool mouse_handler_base::mouse_motion_default(int x, int y, bool /*update*/)
00083 {
00084     tooltips::process(x, y);
00085 
00086     if(simple_warp_) {
00087         return true;
00088     }
00089 
00090     if(minimap_scrolling_) {
00091         //if the game is run in a window, we could miss a LMB/MMB up event
00092         // if it occurs outside our window.
00093         // thus, we need to check if the LMB/MMB is still down
00094         minimap_scrolling_ = ((SDL_GetMouseState(NULL,NULL) & (SDL_BUTTON(1) | SDL_BUTTON(2))) != 0);
00095         if(minimap_scrolling_) {
00096             const map_location& loc = gui().minimap_location_on(x,y);
00097             if(loc.valid()) {
00098                 if(loc != last_hex_) {
00099                     last_hex_ = loc;
00100                     gui().scroll_to_tile(loc,display::WARP,false);
00101                 }
00102             } else {
00103                 // clicking outside of the minimap will end minimap scrolling
00104                 minimap_scrolling_ = false;
00105             }
00106         }
00107         if(minimap_scrolling_) return true;
00108     }
00109 
00110     // Fire the drag & drop only after minimal drag distance
00111     // While we check the mouse buttons state, we also grab fresh position data.
00112     int mx = drag_from_x_; // some default value to prevent unlikely SDL bug
00113     int my = drag_from_y_;
00114     if (is_dragging() && !dragging_started_) {
00115         if ((dragging_left_ && (SDL_GetMouseState(&mx,&my) & SDL_BUTTON_LEFT) != 0)
00116         || (dragging_right_ && (SDL_GetMouseState(&mx,&my) & SDL_BUTTON_RIGHT) != 0)) {
00117             const double drag_distance = std::pow(static_cast<double>(drag_from_x_- mx), 2)
00118                     + std::pow(static_cast<double>(drag_from_y_- my), 2);
00119             if (drag_distance > drag_threshold()*drag_threshold()) {
00120                 dragging_started_ = true;
00121                 cursor::set_dragging(true);
00122             }
00123         }
00124     }
00125     return false;
00126 }
00127 
00128 void mouse_handler_base::mouse_press(const SDL_MouseButtonEvent& event, const bool browse)
00129 {
00130     if(is_middle_click(event) && !preferences::middle_click_scrolls()) {
00131         simple_warp_ = true;
00132     }
00133     show_menu_ = false;
00134     map_location loc = gui().hex_clicked_on(event.x,event.y);
00135     mouse_update(browse, loc);
00136     int scrollx = 0;
00137     int scrolly = 0;
00138 
00139     if (is_left_click(event)) {
00140         if (event.state == SDL_PRESSED) {
00141             cancel_dragging();
00142             init_dragging(dragging_left_);
00143             left_click(event.x, event.y, browse);
00144         } else if (event.state == SDL_RELEASED) {
00145             minimap_scrolling_ = false;
00146             clear_dragging(event, browse);
00147             left_mouse_up(event.x, event.y, browse);
00148         }
00149     } else if (is_right_click(event)) {
00150         if (event.state == SDL_PRESSED) {
00151             cancel_dragging();
00152             init_dragging(dragging_right_);
00153             right_click(event.x, event.y, browse);
00154         } else if (event.state == SDL_RELEASED) {
00155             minimap_scrolling_ = false;
00156             clear_dragging(event, browse);
00157             right_mouse_up(event.x, event.y, browse);
00158         }
00159     } else if (is_middle_click(event)) {
00160         if (event.state == SDL_PRESSED) {
00161             map_location loc = gui().minimap_location_on(event.x,event.y);
00162             minimap_scrolling_ = false;
00163             if(loc.valid()) {
00164                 simple_warp_ = false;
00165                 minimap_scrolling_ = true;
00166                 last_hex_ = loc;
00167                 gui().scroll_to_tile(loc,display::WARP,false);
00168             } else if(simple_warp_) {
00169                 // middle click not on minimap, check gamemap instead
00170                 loc = gui().hex_clicked_on(event.x,event.y);
00171                 if(loc.valid()) {
00172                     last_hex_ = loc;
00173                     gui().scroll_to_tile(loc,display::WARP,false);
00174                 }
00175             }
00176         } else if (event.state == SDL_RELEASED) {
00177             minimap_scrolling_ = false;
00178             simple_warp_ = false;
00179         }
00180     } else if (allow_mouse_wheel_scroll(event.x, event.y)) {
00181         if (event.button == SDL_BUTTON_WHEELUP) {
00182             scrolly = - preferences::scroll_speed();
00183         } else if (event.button == SDL_BUTTON_WHEELDOWN) {
00184             scrolly = preferences::scroll_speed();
00185         } else if (event.button == SDL_BUTTON_WHEELLEFT) {
00186             scrollx = - preferences::scroll_speed();
00187         } else if (event.button == SDL_BUTTON_WHEELRIGHT) {
00188             scrollx = preferences::scroll_speed();
00189         }
00190     }
00191 
00192     if (scrollx != 0 || scrolly != 0) {
00193         CKey pressed;
00194         // Alt + mousewheel do an 90° rotation on the scroll direction
00195         if (pressed[SDLK_LALT] || pressed[SDLK_RALT])
00196             gui().scroll(scrolly,scrollx);
00197         else
00198             gui().scroll(scrollx,scrolly);
00199     }
00200     if (!dragging_left_ && !dragging_right_ && dragging_started_) {
00201         dragging_started_ = false;
00202         cursor::set_dragging(false);
00203     }
00204     mouse_update(browse, loc);
00205 }
00206 
00207 bool mouse_handler_base::is_left_click(
00208         const SDL_MouseButtonEvent& event) const
00209 {
00210     return event.button == SDL_BUTTON_LEFT && !command_active();
00211 }
00212 
00213 bool mouse_handler_base::is_middle_click(
00214         const SDL_MouseButtonEvent& event) const
00215 {
00216     return event.button == SDL_BUTTON_MIDDLE;
00217 }
00218 
00219 bool mouse_handler_base::is_right_click(
00220         const SDL_MouseButtonEvent& event) const
00221 {
00222     return event.button == SDL_BUTTON_RIGHT
00223             || (event.button == SDL_BUTTON_LEFT && command_active());
00224 }
00225 
00226 bool mouse_handler_base::allow_mouse_wheel_scroll(int /*x*/, int /*y*/)
00227 {
00228     return true;
00229 }
00230 
00231 bool mouse_handler_base::right_click_show_menu(int /*x*/, int /*y*/, const bool /*browse*/)
00232 {
00233     return true;
00234 }
00235 
00236 bool mouse_handler_base::left_click(int x, int y, const bool /*browse*/)
00237 {
00238     if(tooltips::click(x,y))
00239         return true;
00240 
00241     // clicked on a hex on the minimap? then initiate minimap scrolling
00242     const map_location& loc = gui().minimap_location_on(x, y);
00243     minimap_scrolling_ = false;
00244     if(loc.valid()) {
00245         minimap_scrolling_ = true;
00246         last_hex_ = loc;
00247         gui().scroll_to_tile(loc,display::WARP, false);
00248         return true;
00249     }
00250     return false;
00251 }
00252 
00253 void mouse_handler_base::left_drag_end(int x, int y, const bool browse)
00254 {
00255     left_click(x, y, browse);
00256 }
00257 
00258 void mouse_handler_base::left_mouse_up(int /*x*/, int /*y*/, const bool /*browse*/)
00259 {
00260 }
00261 
00262 bool mouse_handler_base::right_click(int x, int y, const bool browse)
00263 {
00264     if (right_click_show_menu(x, y, browse)) {
00265         gui().draw(); // redraw highlight (and maybe some more)
00266         const theme::menu* const m = gui().get_theme().context_menu();
00267         if (m != NULL) {
00268             show_menu_ = true;
00269         } else {
00270             WRN_DP << "no context menu found...\n";
00271         }
00272         return true;
00273     }
00274     return false;
00275 }
00276 
00277 void mouse_handler_base::right_drag_end(int /*x*/, int /*y*/, const bool /*browse*/)
00278 {
00279     //FIXME: This is called when we select an option in context-menu,
00280     //       which is bad because that was not a real dragging
00281 }
00282 
00283 void mouse_handler_base::right_mouse_up(int /*x*/, int /*y*/, const bool /*browse*/)
00284 {
00285 }
00286 
00287 void mouse_handler_base::init_dragging(bool& dragging_flag)
00288 {
00289     dragging_flag = true;
00290     SDL_GetMouseState(&drag_from_x_, &drag_from_y_);
00291     drag_from_hex_ = gui().hex_clicked_on(drag_from_x_, drag_from_y_);
00292 }
00293 
00294 void mouse_handler_base::cancel_dragging()
00295 {
00296     dragging_started_ = false;
00297     dragging_left_ = false;
00298     dragging_right_ = false;
00299     cursor::set_dragging(false);
00300 }
00301 
00302 void mouse_handler_base::clear_dragging(const SDL_MouseButtonEvent& event, bool browse)
00303 {
00304     // we reset dragging info before calling functions
00305     // because they may take time to return, and we
00306     // could have started other drag&drop before that
00307     cursor::set_dragging(false);
00308     if (dragging_started_) {
00309         dragging_started_ = false;
00310         if (dragging_left_) {
00311             dragging_left_ = false;
00312             left_drag_end(event.x, event.y, browse);
00313         }
00314         if (dragging_right_) {
00315             dragging_right_ = false;
00316             right_drag_end(event.x, event.y, browse);
00317         }
00318     } else {
00319         dragging_left_ = false;
00320         dragging_right_ = false;
00321     }
00322 }
00323 
00324 
00325 } //end namespace events
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:05 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs