/* Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant 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. GtkRadiant 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 GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mru.h" #include #include #include #include "os/file.h" #include "generic/callback.h" #include "stream/stringstream.h" #include "convert.h" #include "gtkutil/menu.h" #include "map.h" #include "qe3.h" #define MRU_MAX 4 namespace { GtkMenuItem *MRU_items[MRU_MAX]; std::size_t MRU_used; typedef CopiedString MRU_filename_t; MRU_filename_t MRU_filenames[MRU_MAX]; typedef const char* MRU_key_t; MRU_key_t MRU_keys[MRU_MAX] = { "File0", "File1", "File2", "File3" }; } inline const char* MRU_GetText( std::size_t index ){ return MRU_filenames[index].c_str(); } class EscapedMnemonic { StringBuffer m_buffer; public: EscapedMnemonic( std::size_t capacity ) : m_buffer( capacity ){ m_buffer.push_back( '_' ); } const char* c_str() const { return m_buffer.c_str(); } void push_back( char c ){ // not escaped m_buffer.push_back( c ); } std::size_t write( const char* buffer, std::size_t length ){ for ( const char* end = buffer + length; buffer != end; ++buffer ) { if ( *buffer == '_' ) { m_buffer.push_back( '_' ); } m_buffer.push_back( *buffer ); } return length; } }; template inline EscapedMnemonic& operator<<( EscapedMnemonic& ostream, const T& t ){ return ostream_write( ostream, t ); } void MRU_updateWidget( std::size_t index, const char *filename ){ EscapedMnemonic mnemonic( 64 ); mnemonic << Unsigned( index + 1 ) << "- " << filename; gtk_label_set_text_with_mnemonic( GTK_LABEL( gtk_bin_get_child( GTK_BIN( MRU_items[index] ) ) ), mnemonic.c_str() ); } void MRU_SetText( std::size_t index, const char *filename ){ MRU_filenames[index] = filename; MRU_updateWidget( index, filename ); } void MRU_AddFile( const char *str ){ std::size_t i; const char* text; // check if file is already in our list for ( i = 0; i < MRU_used; i++ ) { text = MRU_GetText( i ); if ( strcmp( text, str ) == 0 ) { // reorder menu for (; i > 0; i-- ) MRU_SetText( i, MRU_GetText( i - 1 ) ); MRU_SetText( 0, str ); return; } } if ( MRU_used < MRU_MAX ) { MRU_used++; } // move items down for ( i = MRU_used - 1; i > 0; i-- ) MRU_SetText( i, MRU_GetText( i - 1 ) ); MRU_SetText( 0, str ); gtk_widget_set_sensitive( GTK_WIDGET( MRU_items[0] ), TRUE ); gtk_widget_show( GTK_WIDGET( MRU_items[MRU_used - 1] ) ); } void MRU_Init(){ if ( MRU_used > MRU_MAX ) { MRU_used = MRU_MAX; } } void MRU_AddWidget( GtkMenuItem *widget, std::size_t pos ){ if ( pos < MRU_MAX ) { MRU_items[pos] = widget; if ( pos < MRU_used ) { MRU_updateWidget( pos, MRU_GetText( pos ) ); gtk_widget_set_sensitive( GTK_WIDGET( MRU_items[0] ), TRUE ); gtk_widget_show( GTK_WIDGET( MRU_items[pos] ) ); } } } void MRU_Activate( std::size_t index ){ char text[1024]; strcpy( text, MRU_GetText( index ) ); if ( file_readable( text ) ) { //\todo Test 'map load succeeds' instead of 'file is readable'. MRU_AddFile( text ); Map_RegionOff(); Map_Free(); Map_LoadFile( text ); } else { MRU_used--; for ( std::size_t i = index; i < MRU_used; i++ ) MRU_SetText( i, MRU_GetText( i + 1 ) ); if ( MRU_used == 0 ) { gtk_label_set_text( GTK_LABEL( GTK_BIN( MRU_items[0] )->child ), "Recent Files" ); gtk_widget_set_sensitive( GTK_WIDGET( MRU_items[0] ), FALSE ); } else { gtk_widget_hide( GTK_WIDGET( MRU_items[MRU_used] ) ); } } } class LoadMRU { std::size_t m_number; public: LoadMRU( std::size_t number ) : m_number( number ){ } void load(){ if ( ConfirmModified( "Open Map" ) ) { MRU_Activate( m_number - 1 ); } } }; typedef MemberCaller LoadMRUCaller; LoadMRU g_load_mru1( 1 ); LoadMRU g_load_mru2( 2 ); LoadMRU g_load_mru3( 3 ); LoadMRU g_load_mru4( 4 ); void MRU_constructMenu( GtkMenu* menu ){ { GtkMenuItem* item = create_menu_item_with_mnemonic( menu, "_1", LoadMRUCaller( g_load_mru1 ) ); gtk_widget_set_sensitive( GTK_WIDGET( item ), FALSE ); MRU_AddWidget( item, 0 ); } { GtkMenuItem* item = create_menu_item_with_mnemonic( menu, "_2", LoadMRUCaller( g_load_mru2 ) ); gtk_widget_hide( GTK_WIDGET( item ) ); MRU_AddWidget( item, 1 ); } { GtkMenuItem* item = create_menu_item_with_mnemonic( menu, "_3", LoadMRUCaller( g_load_mru3 ) ); gtk_widget_hide( GTK_WIDGET( item ) ); MRU_AddWidget( item, 2 ); } { GtkMenuItem* item = create_menu_item_with_mnemonic( menu, "_4", LoadMRUCaller( g_load_mru4 ) ); gtk_widget_hide( GTK_WIDGET( item ) ); MRU_AddWidget( item, 3 ); } } #include "preferencesystem.h" #include "stringio.h" void MRU_Construct(){ GlobalPreferenceSystem().registerPreference( "Count", SizeImportStringCaller( MRU_used ), SizeExportStringCaller( MRU_used ) ); for ( std::size_t i = 0; i != MRU_MAX; ++i ) { GlobalPreferenceSystem().registerPreference( MRU_keys[i], CopiedStringImportStringCaller( MRU_filenames[i] ), CopiedStringExportStringCaller( MRU_filenames[i] ) ); } MRU_Init(); } void MRU_Destroy(){ }