/* 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" const int 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(ui::MenuItem::from(MRU_items[0]), TRUE); ui::MenuItem::from(MRU_items[MRU_used - 1]).show(); } void MRU_Init() { if (MRU_used > MRU_MAX) { MRU_used = MRU_MAX; } } void MRU_AddWidget(ui::MenuItem 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(ui::MenuItem::from(MRU_items[0]), TRUE); ui::MenuItem::from(MRU_items[pos]).show(); } } } 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) { auto label = ui::Label::from(gtk_bin_get_child(GTK_BIN(MRU_items[0]))); label.text("Recent Files"); gtk_widget_set_sensitive(ui::MenuItem::from(MRU_items[0]), FALSE); } else { ui::MenuItem::from(MRU_items[MRU_used]).hide(); } } } 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(ui::Menu menu) { { auto item = create_menu_item_with_mnemonic(menu, "_1", LoadMRUCaller(g_load_mru1)); gtk_widget_set_sensitive(item, FALSE); MRU_AddWidget(item, 0); } { auto item = create_menu_item_with_mnemonic(menu, "_2", LoadMRUCaller(g_load_mru2)); item.hide(); MRU_AddWidget(item, 1); } { auto item = create_menu_item_with_mnemonic(menu, "_3", LoadMRUCaller(g_load_mru3)); item.hide(); MRU_AddWidget(item, 2); } { auto item = create_menu_item_with_mnemonic(menu, "_4", LoadMRUCaller(g_load_mru4)); item.hide(); MRU_AddWidget(item, 3); } } #include "preferencesystem.h" #include "stringio.h" void MRU_Construct() { GlobalPreferenceSystem().registerPreference("Count", make_property_string(MRU_used)); for (std::size_t i = 0; i != MRU_MAX; ++i) { GlobalPreferenceSystem().registerPreference(MRU_keys[i], make_property_string(MRU_filenames[i])); } MRU_Init(); } void MRU_Destroy() { }