// actionwin.cpp -- the undo/redo popup window // // Written by Frederic Bouvier, started June 2002. // // Copyright (C) 2002 Frederic Bouvier - fredb@users.sourceforge.net // // 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; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // $Id: actionwin.cpp,v 1.13 2005/06/10 21:39:14 fredb2 Exp $ #ifdef _MSC_VER #pragma warning ( disable : 4786 4503 ) #endif #include #include #include #include #include "actionwin.hpp" #include "mainwin.hpp" FGSD_ActionWindow::FGSD_ActionWindow( FGSD_MainWindow * __mainWindow, int x, int y, int w, int h, bool undo ) : Fl_Window( x, y, w, h ) , _mainWindow( __mainWindow ) , _x( x ) , _y( y ) , _width( w ) , _height( h ) , _undo( undo ) , _exit( false ) { box( FL_UP_BOX ); begin(); set_override(); _output = new Fl_Box( 5, h - 35, w - 10, 30 ); _output->box( FL_DOWN_BOX ); _output->align( FL_ALIGN_INSIDE ); _list = new FGSD_ActionBrowser( 5, 5, w - 10, h - 45, _undo, _output ); _list->when( FL_WHEN_RELEASE | FL_WHEN_NOT_CHANGED ); _list->callback( &FGSD_ActionWindow::list_cb, this ); end(); } FGSD_ActionWindow::~FGSD_ActionWindow() { } int FGSD_ActionWindow::handle( int event ) { switch ( event ) { case FL_PUSH: { int x = Fl::event_x(); int y = Fl::event_y(); if ( x < 0 || x >= _width || y < 0 || y >= _height ) { _exit = true; return 0; } } return Fl_Window::handle( event ); default: if ( event != FL_RELEASE ) _list->handle( event ); return Fl_Window::handle( event ); } } void FGSD_ActionWindow::show() { resize( _mainWindow->_window->x() + _x, _mainWindow->_window->y() + _y, _width, _height ); if ( _undo ) { _list->clear(); std::vector descs = _mainWindow->_actionMgr.getUndoDesc(); size_t nb = descs.size(); for ( size_t i = 0; i < nb; i++ ) { _list->add( descs[ i ].c_str() ); } } else { _list->clear(); std::vector descs = _mainWindow->_actionMgr.getRedoDesc(); size_t nb = descs.size(); for ( size_t i = 0; i < nb; i++ ) { _list->add( descs[ i ].c_str() ); } } Fl_Window* saved_modal = Fl::modal(); Fl::grab( this ); set_modal(); Fl_Window::show(); for (; !_exit; Fl::wait()); if ( saved_modal ) saved_modal->set_modal(); Fl::grab( 0 ); Fl_Window::hide(); } void FGSD_ActionWindow::list_cb( Fl_Widget *o, void *v ) { ((FGSD_ActionWindow *)v)->list_cb( o ); } void FGSD_ActionWindow::list_cb( Fl_Widget *o ) { if ( !_list->leave ) { size_t n = _list->value() - 1; bool ret = true; size_t i = 0; for ( i = 0; i <= n; i++ ) { if ( _undo ) ret = _mainWindow->_actionMgr.undo(); else ret = _mainWindow->_actionMgr.redo(); if ( !ret ) break; } if ( i > 0 ) { _mainWindow->updateUndoMenu(); double lon, lat; bool change = _mainWindow->_actionMgr.getPosition( _undo, lon, lat ); if ( change ) { double xcent = _mainWindow->_posx + _mainWindow->_visw / 2; if ( xcent < _mainWindow->_minx ) xcent = _mainWindow->_minx; if ( xcent > _mainWindow->_maxx ) xcent = _mainWindow->_maxx; double ycent = _mainWindow->_posy + _mainWindow->_vish / 2; if ( ycent < _mainWindow->_miny ) ycent = _mainWindow->_miny; if ( ycent > _mainWindow->_maxy ) ycent = _mainWindow->_maxy; if ( lon < xcent - _mainWindow->_visw / 2 || lon > xcent + _mainWindow->_visw / 2 || lat < ycent - _mainWindow->_vish / 2 || lat > ycent + _mainWindow->_vish / 2 ) _mainWindow->centerPosition( lon, lat ); } } } _exit = true; } FGSD_ActionBrowser::FGSD_ActionBrowser( int x, int y, int w, int h, bool u, Fl_Box *o ) : Fl_Multi_Browser(x,y,w,h) , leave( false ) , current( 0 ) , ind( -1 ) , output( o ) , undo( u ) { } int FGSD_ActionBrowser::handle( int e ) { if ( e == FL_MOVE || e == FL_PUSH || e == FL_DRAG ) { leave = false; int X = 0, Y = 0, W = w(), H = h(); Fl_Boxtype bt = this->box(); X += Fl::box_dx(bt); Y += Fl::box_dy(bt); W -= Fl::box_dw(bt); H -= Fl::box_dh(bt); int real_y = Fl::event_y() /*- Y + scrollbar.value()*/; if ( Fl::event_x() < X || Fl::event_x() >= X + W ) leave = true; else { void *p = find_item( real_y ); if ( p ) { if ( e == FL_PUSH || p != current ) { void *l = p; if ( item_selected( l ) ) { // decrease selection while ( ( l = item_next( l ) ) != 0 ) { Fl_Browser_::select( l, 0 ); if ( l == current ) break; } } else { // increase selection do { Fl_Browser_::select( l, 1 ); l = item_prev( l ); } while ( l != current && l != 0 ); } l = p; size_t nb = 0; while ( l != 0 ) { nb += 1; l = item_prev( l ); } static std::ostringstream str; str.str(""); str << ( undo ? "undo " : "redo " ) << nb << " action" << ( nb ? "s" : "" ) << std::ends; label = str.str(); output->label( label.c_str() ); //damage(FL_DAMAGE_ALL); current = p; } } } } else if ( e == FL_LEAVE ) leave = true; if ( leave ) { output->label( "cancel" ); void *l = current; while ( l != 0 ) { Fl_Browser_::select( l, 0 ); l = item_prev( l ); } current = 0; } int ret = Fl_Multi_Browser::handle( e ); if ( e == FL_PUSH ) { void *l = current; while ( l != 0 ) { Fl_Browser_::select( l, 1 ); l = item_prev( l ); } if ( current ) { // to have value() return the last selected Fl_Browser_::select( current, 0 ); Fl_Browser_::select( current, 1 ); } } return ret; }