initial commit, lordsawar source, slightly modified
[lordsawar] / src / editor / cityset-window.cpp
diff --git a/src/editor/cityset-window.cpp b/src/editor/cityset-window.cpp
new file mode 100644 (file)
index 0000000..3fbe9ff
--- /dev/null
@@ -0,0 +1,628 @@
+//  Copyright (C) 2009 Ben Asselstine
+//
+//  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 3 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#include <config.h>
+
+#include <iostream>
+#include <iomanip>
+#include <assert.h>
+#include <string.h>
+
+#include <sigc++/functors/mem_fun.h>
+#include <sigc++/functors/ptr_fun.h>
+
+#include <gtkmm.h>
+#include "cityset-window.h"
+#include "cityset-info-dialog.h"
+#include "masked-image-editor-dialog.h"
+
+#include "image-helpers.h"
+#include "input-helpers.h"
+#include "error-utils.h"
+
+#include "defs.h"
+#include "File.h"
+
+#include "ucompose.hpp"
+
+#include "glade-helpers.h"
+#include "image-editor-dialog.h"
+#include "GraphicsCache.h"
+#include "citysetlist.h"
+
+
+CitySetWindow::CitySetWindow(std::string load_filename)
+{
+  needs_saving = false;
+  d_cityset = NULL;
+    Glib::RefPtr<Gtk::Builder> xml
+       = Gtk::Builder::create_from_file(get_glade_path() + "/cityset-window.ui");
+
+    xml->get_widget("window", window);
+    window->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
+    window->signal_delete_event().connect
+      (sigc::mem_fun(*this, &CitySetWindow::on_window_closed));
+
+    xml->get_widget("cityset_frame", cityset_frame);
+    xml->get_widget("new_cityset_menuitem", new_cityset_menuitem);
+    new_cityset_menuitem->signal_activate().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_new_cityset_activated));
+    xml->get_widget("load_cityset_menuitem", load_cityset_menuitem);
+    load_cityset_menuitem->signal_activate().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_load_cityset_activated));
+    xml->get_widget("save_cityset_menuitem", save_cityset_menuitem);
+    save_cityset_menuitem->signal_activate().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_save_cityset_activated));
+    xml->get_widget("validate_cityset_menuitem", validate_cityset_menuitem);
+    validate_cityset_menuitem->signal_activate().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_validate_cityset_activated));
+    xml->get_widget("quit_menuitem", quit_menuitem);
+    quit_menuitem->signal_activate().connect
+       (sigc::mem_fun(this, &CitySetWindow::on_quit_activated));
+    xml->get_widget("edit_cityset_info_menuitem", edit_cityset_info_menuitem);
+    edit_cityset_info_menuitem->signal_activate().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_edit_cityset_info_activated));
+    xml->get_widget ("help_about_menuitem", help_about_menuitem);
+    help_about_menuitem->signal_activate().connect
+       (sigc::mem_fun(this, &CitySetWindow::on_help_about_activated));
+    xml->get_widget("city_tile_width_spinbutton", city_tile_width_spinbutton);
+    city_tile_width_spinbutton->set_range (1, 4);
+    city_tile_width_spinbutton->signal_changed().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_city_tile_width_changed));
+    city_tile_width_spinbutton->signal_insert_text().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_city_tile_width_text_changed));
+    xml->get_widget("ruin_tile_width_spinbutton", ruin_tile_width_spinbutton);
+    ruin_tile_width_spinbutton->set_range (1, 4);
+    ruin_tile_width_spinbutton->signal_changed().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_ruin_tile_width_changed));
+    ruin_tile_width_spinbutton->signal_insert_text().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_ruin_tile_width_text_changed));
+    xml->get_widget("temple_tile_width_spinbutton", 
+                   temple_tile_width_spinbutton);
+    temple_tile_width_spinbutton->set_range (1, 4);
+    temple_tile_width_spinbutton->signal_changed().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_temple_tile_width_changed));
+    temple_tile_width_spinbutton->signal_insert_text().connect
+      (sigc::mem_fun(this, &CitySetWindow::on_temple_tile_width_text_changed));
+
+    window->signal_delete_event().connect
+      (sigc::mem_fun(*this, &CitySetWindow::on_delete_event));
+    xml->get_widget("change_citypics_button", change_citypics_button);
+    change_citypics_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_citypics_clicked));
+    xml->get_widget("change_razedcitypics_button", change_razedcitypics_button);
+    change_razedcitypics_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_razedcitypics_clicked));
+    xml->get_widget("change_portpic_button", change_portpic_button);
+    change_portpic_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_portpic_clicked));
+    xml->get_widget("change_signpostpic_button", change_signpostpic_button);
+    change_signpostpic_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_signpostpic_clicked));
+    xml->get_widget("change_ruinpics_button", change_ruinpics_button);
+    change_ruinpics_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_ruinpics_clicked));
+    xml->get_widget("change_templepic_button", change_templepic_button);
+    change_templepic_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_templepic_clicked));
+    xml->get_widget("change_towerpics_button", change_towerpics_button);
+    change_towerpics_button->signal_clicked().connect(
+       sigc::mem_fun(this, &CitySetWindow::on_change_towerpics_clicked));
+
+    update_cityset_panel();
+
+    if (load_filename.empty() == false)
+      {
+       load_cityset (load_filename);
+       update_cityset_panel();
+      }
+    update_cityset_menuitems();
+}
+
+void
+CitySetWindow::update_cityset_menuitems()
+{
+  if (d_cityset == NULL)
+    {
+      save_cityset_menuitem->set_sensitive(false);
+      validate_cityset_menuitem->set_sensitive(false);
+      edit_cityset_info_menuitem->set_sensitive(false);
+    }
+  else
+    {
+      std::string file = d_cityset->getConfigurationFile();
+      if (File::exists(file) == false)
+       save_cityset_menuitem->set_sensitive(true);
+      else if (File::is_writable(file) == false)
+       save_cityset_menuitem->set_sensitive(false);
+      else
+       save_cityset_menuitem->set_sensitive(true);
+      edit_cityset_info_menuitem->set_sensitive(true);
+      validate_cityset_menuitem->set_sensitive(true);
+    }
+}
+
+void
+CitySetWindow::update_cityset_panel()
+{
+  cityset_frame->set_sensitive(d_cityset != NULL);
+  std::string no_image = _("no image set");
+  std::string s;
+  if (d_cityset && d_cityset->getCitiesFilename().empty() == false)
+    s = d_cityset->getCitiesFilename() + ".png";
+  else
+    s = no_image;
+  change_citypics_button->set_label(s);
+  if (d_cityset && d_cityset->getRazedCitiesFilename().empty() == false)
+    s = d_cityset->getRazedCitiesFilename() + ".png";
+  else
+    s = no_image;
+  change_razedcitypics_button->set_label(s);
+  if (d_cityset && d_cityset->getPortFilename().empty() == false)
+    s = d_cityset->getPortFilename() + ".png";
+  else
+    s = no_image;
+  change_portpic_button->set_label(s);
+  if (d_cityset && d_cityset->getSignpostFilename().empty() == false)
+    s = d_cityset->getSignpostFilename() + ".png";
+  else
+    s = no_image;
+  change_signpostpic_button->set_label(s);
+  if (d_cityset && d_cityset->getRuinsFilename().empty() == false)
+    s = d_cityset->getRuinsFilename() + ".png";
+  else
+    s = no_image;
+  change_ruinpics_button->set_label(s);
+  if (d_cityset && d_cityset->getTemplesFilename().empty() == false)
+    s = d_cityset->getTemplesFilename() + ".png";
+  else
+    s = no_image;
+  change_templepic_button->set_label(s);
+  if (d_cityset && d_cityset->getTowersFilename().empty() == false)
+    s = d_cityset->getTowersFilename() + ".png";
+  else
+    s = no_image;
+  change_towerpics_button->set_label(s);
+  if (d_cityset)
+    city_tile_width_spinbutton->set_value(d_cityset->getCityTileWidth());
+  else
+    city_tile_width_spinbutton->set_value(2);
+  if (d_cityset)
+    ruin_tile_width_spinbutton->set_value(d_cityset->getRuinTileWidth());
+  else
+    ruin_tile_width_spinbutton->set_value(1);
+  if (d_cityset)
+    temple_tile_width_spinbutton->set_value(d_cityset->getTempleTileWidth());
+  else
+    temple_tile_width_spinbutton->set_value(1);
+}
+
+CitySetWindow::~CitySetWindow()
+{
+  delete window;
+}
+
+void CitySetWindow::show()
+{
+  window->show();
+}
+
+void CitySetWindow::hide()
+{
+  window->hide();
+}
+
+bool CitySetWindow::on_delete_event(GdkEventAny *e)
+{
+  hide();
+
+  return true;
+}
+
+void CitySetWindow::on_new_cityset_activated()
+{
+  std::string name = "";
+  int id = Citysetlist::getNextAvailableId();
+  Cityset *cityset = new Cityset(id, name);
+  CitySetInfoDialog d(cityset, false);
+  d.set_parent_window(*window);
+  int response = d.run();
+  if (response != Gtk::RESPONSE_ACCEPT)
+    {
+      delete cityset;
+      return;
+    }
+  if (d_cityset)
+    delete d_cityset;
+  d_cityset = cityset;
+  std::string dir = File::getUserCitysetDir() + "/" + d_cityset->getSubDir();
+  d_cityset->setDirectory(dir);
+  File::create_dir(dir);
+  current_save_filename = d_cityset->getConfigurationFile();
+
+  update_cityset_panel();
+  update_cityset_menuitems();
+
+  XML_Helper helper(current_save_filename, std::ios::out, false);
+  d_cityset->save(&helper);
+  helper.close();
+  needs_saving = true;
+}
+
+void CitySetWindow::on_load_cityset_activated()
+{
+  Gtk::FileChooserDialog chooser(*window, 
+                                _("Choose a Cityset to Load"));
+  Gtk::FileFilter sav_filter;
+  sav_filter.add_pattern("*" + CITYSET_EXT);
+  chooser.set_filter(sav_filter);
+  chooser.set_current_folder(File::getUserCitysetDir());
+
+  chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+  chooser.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
+  chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
+
+  chooser.show_all();
+  int res = chooser.run();
+
+  if (res == Gtk::RESPONSE_ACCEPT)
+    {
+      load_cityset(chooser.get_filename());
+      chooser.hide();
+    }
+
+  update_cityset_menuitems();
+  update_cityset_panel();
+}
+
+void CitySetWindow::on_validate_cityset_activated()
+{
+  std::list<std::string> msgs;
+  if (d_cityset == NULL)
+    return;
+  if (d_cityset->validateCitiesFilename() == false)
+    msgs.push_back(_("The cities picture is not set."));
+  if (d_cityset->validateRazedCitiesFilename() == false)
+    msgs.push_back(_("The razed cities picture is not set."));
+  if (d_cityset->validatePortFilename() == false)
+    msgs.push_back(_("The port picture is not set."));
+  if (d_cityset->validateSignpostFilename() == false)
+    msgs.push_back(_("The signpost picture is not set."));
+  if (d_cityset->validateRuinsFilename() == false)
+    msgs.push_back(_("The ruins picture is not set."));
+  if (d_cityset->validateTemplesFilename() == false)
+    msgs.push_back(_("The temple picture is not set."));
+  if (d_cityset->validateTowersFilename() == false)
+    msgs.push_back(_("The towers picture is not set."));
+  if (d_cityset->validateCityTileWidth() == false)
+    msgs.push_back(_("The tile width for temples must be over zero."));
+  if (d_cityset->validateRuinTileWidth() == false)
+    msgs.push_back(_("The tile width for ruins must be over zero."));
+  if (d_cityset->validateTempleTileWidth() == false)
+    msgs.push_back(_("The tile width for temples must be over zero."));
+
+  std::string msg = "";
+  for (std::list<std::string>::iterator it = msgs.begin(); it != msgs.end();
+       it++)
+    msg += (*it) + "\n";
+
+  if (msg != "")
+    {
+      Gtk::MessageDialog dialog(*window, msg);
+      dialog.run();
+      dialog.hide();
+    }
+
+  return;
+}
+
+void CitySetWindow::on_save_cityset_activated()
+{
+  if (current_save_filename.empty())
+    current_save_filename = d_cityset->getConfigurationFile();
+
+  XML_Helper helper(current_save_filename, std::ios::out, false);
+  d_cityset->save(&helper);
+  helper.close();
+  needs_saving = false;
+}
+
+void CitySetWindow::on_edit_cityset_info_activated()
+{
+  CitySetInfoDialog d(d_cityset, true);
+  d.set_parent_window(*window);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    needs_saving = true;
+}
+
+void CitySetWindow::on_help_about_activated()
+{
+  Gtk::AboutDialog* dialog;
+
+  Glib::RefPtr<Gtk::Builder> xml
+    = Gtk::Builder::create_from_file(get_glade_path() + "/../about-dialog.ui");
+
+  xml->get_widget("dialog", dialog);
+  dialog->set_transient_for(*window);
+  dialog->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
+
+  dialog->set_version(PACKAGE_VERSION);
+  dialog->set_logo(GraphicsCache::getMiscPicture("castle_icon.png")->to_pixbuf());
+  dialog->show_all();
+  dialog->run();
+  delete dialog;
+
+  return;
+}
+
+void CitySetWindow::load_cityset(std::string filename)
+{
+  current_save_filename = filename;
+
+  std::string name = File::get_basename(filename);
+
+  Cityset *cityset = Cityset::create(filename);
+  if (cityset == NULL)
+    {
+      std::string msg;
+      msg = "Error!  Cityset could not be loaded.";
+      Gtk::MessageDialog dialog(*window, msg);
+      dialog.run();
+      dialog.hide();
+      return;
+    }
+  if (d_cityset)
+    delete d_cityset;
+  d_cityset = cityset;
+
+  d_cityset->setSubDir(name);
+  d_cityset->instantiateImages();
+}
+
+bool CitySetWindow::quit()
+{
+  if (needs_saving == true)
+    {
+      Gtk::Dialog* dialog;
+      Glib::RefPtr<Gtk::Builder> xml
+       = Gtk::Builder::create_from_file(get_glade_path() + 
+                                        "/editor-quit-dialog.ui");
+      xml->get_widget("dialog", dialog);
+      dialog->set_transient_for(*window);
+      int response = dialog->run();
+      dialog->hide();
+      delete dialog;
+
+      if (response == Gtk::RESPONSE_CANCEL) //we don't want to quit
+       return false;
+
+      else if (response == Gtk::RESPONSE_ACCEPT) // save and quit
+       on_save_cityset_activated();
+      //else if (Response == Gtk::CLOSE) // don't save just quit
+      window->hide();
+    }
+  else
+    window->hide();
+  return true;
+}
+
+bool CitySetWindow::on_window_closed(GdkEventAny*)
+{
+  return !quit();
+}
+
+void CitySetWindow::on_quit_activated()
+{
+  quit();
+}
+
+void CitySetWindow::on_city_tile_width_text_changed(const Glib::ustring &s, int* p)
+{
+  city_tile_width_spinbutton->set_value(atoi(city_tile_width_spinbutton->get_text().c_str()));
+  on_city_tile_width_changed();
+}
+
+void CitySetWindow::on_city_tile_width_changed()
+{
+  if (!d_cityset)
+    return;
+  d_cityset->setCityTileWidth(city_tile_width_spinbutton->get_value());
+  needs_saving = true;
+}
+
+void CitySetWindow::on_ruin_tile_width_text_changed(const Glib::ustring &s, int* p)
+{
+  ruin_tile_width_spinbutton->set_value(atoi(ruin_tile_width_spinbutton->get_text().c_str()));
+  on_ruin_tile_width_changed();
+}
+
+void CitySetWindow::on_ruin_tile_width_changed()
+{
+  if (!d_cityset)
+    return;
+  d_cityset->setRuinTileWidth(ruin_tile_width_spinbutton->get_value());
+  needs_saving = true;
+}
+
+void CitySetWindow::on_temple_tile_width_text_changed(const Glib::ustring &s, int* p)
+{
+  temple_tile_width_spinbutton->set_value(atoi(temple_tile_width_spinbutton->get_text().c_str()));
+  on_temple_tile_width_changed();
+}
+
+void CitySetWindow::on_temple_tile_width_changed()
+{
+  if (!d_cityset)
+    return;
+  d_cityset->setTempleTileWidth(temple_tile_width_spinbutton->get_value());
+  needs_saving = true;
+}
+
+void CitySetWindow::on_change_citypics_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getCitiesFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getCitiesFilename());
+  ImageEditorDialog d(filename, MAX_PLAYERS + 1);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getCitiesFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getCitiesFilename()));
+       }
+
+      d_cityset->setCitiesFilename
+       (File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}
+void CitySetWindow::on_change_razedcitypics_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getRazedCitiesFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getRazedCitiesFilename());
+  ImageEditorDialog d(filename, MAX_PLAYERS);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getRazedCitiesFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getRazedCitiesFilename()));
+       }
+
+      d_cityset->setRazedCitiesFilename
+       (File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}
+void CitySetWindow::on_change_portpic_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getPortFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getPortFilename());
+  ImageEditorDialog d(filename, 1);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getPortFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getPortFilename()));
+       }
+
+      d_cityset->setPortFilename(File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}
+void CitySetWindow::on_change_signpostpic_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getSignpostFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getSignpostFilename());
+  ImageEditorDialog d(filename, 1);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getSignpostFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getSignpostFilename()));
+       }
+
+      d_cityset->setSignpostFilename
+       (File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}
+void CitySetWindow::on_change_ruinpics_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getRuinsFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getRuinsFilename());
+  ImageEditorDialog d(filename, RUIN_TYPES);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getRuinsFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getRuinsFilename()));
+       }
+
+      d_cityset->setRuinsFilename
+       (File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}
+void CitySetWindow::on_change_templepic_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getTemplesFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getTemplesFilename());
+  ImageEditorDialog d(filename, TEMPLE_TYPES);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getTemplesFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getTemplesFilename()));
+       }
+
+      d_cityset->setTemplesFilename
+       (File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}
+void CitySetWindow::on_change_towerpics_clicked()
+{
+  std::string filename = "";
+  if (d_cityset->getTowersFilename().empty() == false)
+    filename = d_cityset->getFile(d_cityset->getTowersFilename());
+  ImageEditorDialog d(filename, MAX_PLAYERS);
+  int response = d.run();
+  if (response == Gtk::RESPONSE_ACCEPT)
+    {
+      if (d_cityset->getFile(d_cityset->getTowersFilename()) != 
+         d.get_selected_filename())
+       {
+         File::copy(d.get_selected_filename(), 
+                    d_cityset->getFile(d_cityset->getTowersFilename()));
+       }
+
+      d_cityset->setTowersFilename
+       (File::get_basename(d.get_selected_filename()));
+      needs_saving = true;
+      update_cityset_panel();
+    }
+}