1 //  Copyright (C) 2009, 2010, 2011, 2014, 2020 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 //  02110-1301, USA.
17 
18 #include <config.h>
19 
20 #include <gtkmm.h>
21 #include <sigc++/functors/mem_fun.h>
22 
23 #include "tileset-explosion-picture-editor-dialog.h"
24 
25 #include "ucompose.hpp"
26 #include "defs.h"
27 #include "File.h"
28 #include "ImageCache.h"
29 #include "tarhelper.h"
30 #include "tile-preview-scene.h"
31 #include "tileset-window.h"
32 #include "past-chooser.h"
33 #include "font-size.h"
34 #include "image-file-filter.h"
35 #include "timed-message-dialog.h"
36 
37 #define method(x) sigc::mem_fun(*this, &TilesetExplosionPictureEditorDialog::x)
38 
TilesetExplosionPictureEditorDialog(Gtk::Window & parent,Tileset * tileset)39 TilesetExplosionPictureEditorDialog::TilesetExplosionPictureEditorDialog(Gtk::Window &parent, Tileset *tileset)
40  : LwEditorDialog(parent, "tileset-explosion-picture-editor-dialog.ui")
41 {
42   d_changed = false;
43   d_tileset = tileset;
44 
45   xml->get_widget("explosion_imagebutton", explosion_imagebutton);
46   explosion_imagebutton->signal_clicked().connect
47     (method(on_explosion_imagebutton_clicked));
48 
49   xml->get_widget("large_explosion_radiobutton", large_explosion_radiobutton);
50   large_explosion_radiobutton->signal_toggled().connect (method(on_large_toggled));
51   xml->get_widget("small_explosion_radiobutton", small_explosion_radiobutton);
52   small_explosion_radiobutton->signal_toggled().connect (method(on_small_toggled));
53 
54   xml->get_widget("scene_image", scene_image);
55 
56   Glib::ustring imgname = d_tileset->getExplosionFilename();
57   if (imgname.empty() == false)
58     {
59       bool broken = false;
60       Glib::ustring f =
61         d_tileset->getFileFromConfigurationFile(imgname);
62       d_explosion = PixMask::create (f, broken);
63     }
64   else
65     d_explosion = NULL;
66   on_large_toggled();
67 }
68 
run()69 bool TilesetExplosionPictureEditorDialog::run()
70 {
71   dialog->show_all();
72   dialog->run();
73   dialog->hide ();
74   return d_changed;
75 }
76 
on_image_chosen(Gtk::FileChooserDialog * d)77 bool TilesetExplosionPictureEditorDialog::on_image_chosen(Gtk::FileChooserDialog *d)
78 {
79   bool broken = false;
80   d_explosion = PixMask::create (d->get_filename (), broken);
81   if (!broken)
82     {
83       Glib::ustring imgname = d_tileset->getExplosionFilename();
84       Glib::ustring newname = "";
85       bool success = false;
86       if (imgname.empty() == true)
87         success =
88           d_tileset->addFileInCfgFile(d->get_filename(), newname);
89       else
90         success =
91           d_tileset->replaceFileInCfgFile(imgname, d->get_filename(), newname);
92       if (success)
93         {
94           d_tileset->setExplosionFilename (newname);
95           d_tileset->instantiateExplosionImage();
96           d_changed = true;
97           update_panel ();
98         }
99       else
100         {
101           Glib::ustring errmsg = Glib::strerror(errno);
102           TimedMessageDialog
103             td(*d, String::ucompose(_("Couldn't add %1 to :\n%2\n%3"),
104                                     d->get_filename (),
105                                     d_tileset->getConfigurationFile(),
106                                     errmsg), 0);
107           td.run_and_hide ();
108           broken = true;
109         }
110     }
111   else
112     {
113       TimedMessageDialog
114         td(*d, String::ucompose(_("Couldn't make sense of the image:\n%1"),
115                                 d->get_filename ()), 0);
116       td.run_and_hide ();
117       broken = true;
118     }
119   return broken;
120 }
121 
on_large_toggled()122 void TilesetExplosionPictureEditorDialog::on_large_toggled()
123 {
124   update_panel();
125 }
126 
on_small_toggled()127 void TilesetExplosionPictureEditorDialog::on_small_toggled()
128 {
129   update_panel();
130 }
131 
update_panel()132 void TilesetExplosionPictureEditorDialog::update_panel()
133 {
134   Glib::ustring imgname = d_tileset->getExplosionFilename();
135   if (imgname.empty() == false)
136     {
137       explosion_imagebutton->set_label (imgname);
138       show_explosion_image();
139     }
140   else
141     {
142       explosion_imagebutton->set_label (_("no image set"));
143       scene_image->clear();
144     }
145 }
146 
show_explosion_image()147 void TilesetExplosionPictureEditorDialog::show_explosion_image()
148 {
149   guint32 size = FontSize::getInstance ()->get_height () *
150     EDITOR_DIALOG_TILE_PIC_FONTSIZE_MULTIPLE;
151   TilePreviewScene *s;
152   Glib::ustring scene;
153   guint32 idx = d_tileset->getIndex(Tile::GRASS);
154   Tile *grass = NULL;
155   if (d_tileset->size() > 0)
156     grass = (*d_tileset)[idx];
157   scene.clear();
158   if (large_explosion_radiobutton->get_active() == true)
159     {
160       scene += "aaaaaa";
161       scene += "aaaaaa";
162       scene += "aaaaaa";
163       scene += "aaaaaa";
164       scene += "aaaaaa";
165       scene += "aaaaaa";
166       s = new TilePreviewScene(grass, NULL, 6, 6, scene, size);
167       update_scene(s);
168     }
169   else if (small_explosion_radiobutton->get_active() == true)
170     {
171       scene += "aaaaaaa";
172       scene += "aaaaaaa";
173       scene += "aaaaaaa";
174       scene += "aaaaaaa";
175       scene += "aaaaaaa";
176       scene += "aaaaaaa";
177       scene += "aaaaaaa";
178       s = new TilePreviewScene(grass, NULL, 7, 7, scene, size);
179       update_scene(s);
180     }
181 }
182 
update_scene(TilePreviewScene * scene)183 void TilesetExplosionPictureEditorDialog::update_scene(TilePreviewScene *scene)
184 {
185   if (!d_explosion)
186     return;
187   if (!scene)
188     return;
189 
190   Glib::RefPtr<Gdk::Pixbuf> scene_pixbuf;
191   scene_pixbuf = scene->renderScene ();
192   //center the explosion image on the pixbuf
193   //but the large explosion is scaled first
194 
195   Glib::RefPtr<Gdk::Pixbuf> explosion;
196   if (small_explosion_radiobutton->get_active())
197     {
198       //explosion = d_explosion->to_pixbuf ();
199       PixMask *p = d_explosion->copy ();
200       double ratio = EDITOR_DIALOG_TILE_PIC_FONTSIZE_MULTIPLE;
201       double new_height = FontSize::getInstance()->get_height () * ratio;
202       int new_width =
203         ImageCache::calculate_width_from_adjusted_height (p, new_height);
204       PixMask::scale (p, new_width, new_height);
205       explosion = p->to_pixbuf ();
206       delete p;
207     }
208   else if (large_explosion_radiobutton->get_active())
209     {
210       PixMask *p = d_explosion->copy ();
211       double ratio = EDITOR_DIALOG_TILE_PIC_FONTSIZE_MULTIPLE;
212       double new_height = FontSize::getInstance()->get_height () * ratio * 2.0;
213       int new_width =
214         ImageCache::calculate_width_from_adjusted_height (p, new_height);
215       PixMask::scale (p, new_width, new_height);
216       explosion = p->to_pixbuf ();
217       //guint32 ts = d_tileset->getTileSize ();
218       //PixMask::scale (p, ts * 2, ts * 2);
219       //explosion = p->to_pixbuf ();
220       delete p;
221     }
222 
223   int i = (scene_pixbuf->get_width() - explosion->get_width()) / 2;
224   int j = (scene_pixbuf->get_height() - explosion->get_height()) / 2;
225   explosion->composite (scene_pixbuf, i, j, explosion->get_width(), explosion->get_height(), i, j, 1, 1, Gdk::INTERP_NEAREST, 255);
226   scene_image->property_pixbuf() = scene_pixbuf;
227   scene_image->queue_draw();
228 }
229 
image_filechooser(bool clear)230 Gtk::FileChooserDialog* TilesetExplosionPictureEditorDialog::image_filechooser(bool clear)
231 {
232   Glib::ustring filename = "";
233   Glib::ustring title = _("Choose an explosion image");
234   Gtk::FileChooserDialog *d = new Gtk::FileChooserDialog(*dialog, title);
235   ImageFileFilter::getInstance ()->add (d);
236   d->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
237   d->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
238   if (clear)
239     d->add_button(Gtk::Stock::CLEAR, Gtk::RESPONSE_REJECT);
240   d->set_default_response(Gtk::RESPONSE_ACCEPT);
241   d->set_current_folder(PastChooser::getInstance()->get_dir(d));
242   return d;
243 }
244 
on_explosion_imagebutton_clicked()245 void TilesetExplosionPictureEditorDialog::on_explosion_imagebutton_clicked ()
246 {
247   Glib::ustring f = d_tileset->getExplosionFilename ();
248   Glib::ustring filename = "";
249   Gtk::FileChooserDialog *d = image_filechooser(f != "");
250   if (f != "")
251     filename = d_tileset->getFileFromConfigurationFile(f);
252   int response = d->run();
253   if (filename != "")
254     File::erase(filename);
255   if (response == Gtk::RESPONSE_ACCEPT && d->get_filename() != "")
256     {
257       if (ImageFileFilter::getInstance ()->hasInvalidExt (d->get_filename ()))
258         ImageFileFilter::getInstance()->showErrorDialog (d);
259       else
260         {
261           if (d->get_filename() != filename)
262             {
263               PastChooser::getInstance()->set_dir(d);
264               on_image_chosen (d);
265             }
266         }
267     }
268   else if (response == Gtk::RESPONSE_REJECT && f != "")
269     {
270       if (d_tileset->removeFileInCfgFile(f))
271         {
272           d_changed = true;
273           d_tileset->uninstantiateSameNamedImages (f);
274           if (d_explosion)
275             {
276               delete d_explosion;
277               d_explosion = NULL;
278             }
279           update_panel ();
280         }
281       else
282         {
283           Glib::ustring errmsg = Glib::strerror(errno);
284           TimedMessageDialog
285             td(*d, String::ucompose(_("Couldn't remove %1 from:\n%2\n%3"),
286                                     f, d_tileset->getConfigurationFile(),
287                                     errmsg), 0);
288           td.run_and_hide ();
289         }
290     }
291   d->hide();
292   delete d;
293 }
294 
~TilesetExplosionPictureEditorDialog()295 TilesetExplosionPictureEditorDialog::~TilesetExplosionPictureEditorDialog ()
296 {
297   if (d_explosion)
298     delete d_explosion;
299 }
300