Fix a crash when running single-threaded and dragging the time slider.
[synfig.git] / synfig-studio / trunk / src / gtkmm / about.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file about.cpp
3 **      \brief writeme
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 **
22 ** === N O T E S ===========================================================
23 **
24 ** ========================================================================= */
25
26 /* === H E A D E R S ======================================================= */
27
28 #ifdef USING_PCH
29 #       include "pch.h"
30 #else
31 #ifdef HAVE_CONFIG_H
32 #       include <config.h>
33 #endif
34
35 #include <iostream>
36 #include <string>
37
38 #include <ETL/stringf>
39
40 #include <gtkmm/image.h>
41 #include <gdkmm/pixbufloader.h>
42 #include <gtkmm/button.h>
43 #include <gtkmm/label.h>
44 #include <gtkmm/fixed.h>
45
46 #include <synfig/general.h>
47
48 #include "about.h"
49 #include "app.h"
50
51 #endif
52
53 using namespace std;
54 using namespace etl;
55 using namespace studio;
56
57 /* === M A C R O S ========================================================= */
58
59 #ifndef VERSION
60 #define VERSION "unknown"
61 #define PACKAGE "synfigstudio"
62 #endif
63
64 #ifdef WIN32
65 #       ifdef IMAGE_DIR
66 #               undef IMAGE_DIR
67 #               define IMAGE_DIR "share\\pixmaps"
68 #       endif
69 #endif
70
71 #ifndef IMAGE_DIR
72 #       define IMAGE_DIR "/usr/local/share/pixmaps"
73 #endif
74
75 #ifndef IMAGE_EXT
76 #       define IMAGE_EXT        "png"
77 #endif
78
79 /* === G L O B A L S ======================================================= */
80 extern      const guint gtk_major_version;
81 extern      const guint gtk_minor_version;
82 extern      const guint gtk_micro_version;
83 extern      const guint gtk_binary_age;
84 extern      const guint gtk_interface_age;
85
86 /* === P R O C E D U R E S ================================================= */
87
88 class studio::AboutProgress : public synfig::ProgressCallback
89 {
90         About &about;
91
92 public:
93
94         AboutProgress(About &about):about(about) { }
95
96         virtual bool task(const std::string &task)
97         {
98                 if(about.tasklabel)
99                 {
100                         about.tasklabel->set_label(task);
101                         about.tasklabel->show();
102                 }
103                 else
104                 {
105                         cerr<<task<<endl;
106                 }
107
108                 while(studio::App::events_pending())studio::App::iteration(false);
109                 return true;
110         }
111
112         virtual bool error(const std::string &task)
113         {
114                 if(about.tasklabel)
115                 {
116                         about.tasklabel->set_label(_("ERROR:")+task);
117                         about.tasklabel->show();
118                 }
119                 else
120                 {
121                         cerr<<task<<endl;
122                 }
123
124                 while(studio::App::events_pending())studio::App::iteration(false);
125                 return true;
126         }
127
128         virtual bool warning(const std::string &task)
129         {
130                 if(about.tasklabel)
131                 {
132                         about.tasklabel->set_label(_("WARNING:")+task);
133                         about.tasklabel->show();
134                 }
135                 else
136                 {
137                         cerr<<task<<endl;
138                 }
139
140                 while(studio::App::events_pending())studio::App::iteration(false);
141                 return true;
142         }
143
144         virtual bool amount_complete(int current, int total)
145         {
146                 if(about.progressbar)
147                 {
148                         about.progressbar->set_fraction((float)current/(float)total);
149                         about.progressbar->show();
150                 }
151                 else
152                         cerr<<current<<'/'<<total<<endl;
153
154                 while(studio::App::events_pending())studio::App::iteration(false);
155                 return true;
156         }
157 }; // END of class AboutProgress
158
159 /* === M E T H O D S ======================================================= */
160
161 About::About():
162         Gtk::Window(getenv("SYNFIG_DISABLE_POPUP_WINDOWS") ? Gtk::WINDOW_TOPLEVEL : Gtk::WINDOW_POPUP),
163         can_self_destruct(true)
164 {
165         int image_w=300,image_h=350;
166
167         std::string imagepath;
168 #ifdef WIN32
169         imagepath=App::get_base_path()+ETL_DIRECTORY_SEPARATOR+IMAGE_DIR;
170 #else
171         imagepath=IMAGE_DIR;
172 #endif
173         char* synfig_root=getenv("SYNFIG_ROOT");
174         if(synfig_root) {
175                 imagepath=synfig_root;
176                 imagepath+=ETL_DIRECTORY_SEPARATOR;
177
178                 imagepath+="share/pixmaps";
179         }
180         imagepath+=ETL_DIRECTORY_SEPARATOR;
181
182
183         // Create the Logo
184         Gtk::Image *Logo = manage(new class Gtk::Image());
185         Logo->set(imagepath+"about_dialog."IMAGE_EXT);
186         Logo->set_size_request(image_w,image_h);
187         Logo->set_alignment(0.5,0.5);
188         Logo->set_padding(0,0);
189
190         // Create the Copyright Label
191         Gtk::Label *CopyrightLabel = manage(new class Gtk::Label(SYNFIG_COPYRIGHT));
192         CopyrightLabel->set_size_request(image_w,24);
193         CopyrightLabel->set_alignment(0.5,0.5);
194         CopyrightLabel->set_padding(0,0);
195         CopyrightLabel->set_justify(Gtk::JUSTIFY_CENTER);
196         CopyrightLabel->set_line_wrap(false);
197         CopyrightLabel->modify_fg(Gtk::STATE_NORMAL,Gdk::Color("black"));
198
199         /* Scale the text to fit */
200         int width = 0;
201         int height = 0;
202         float size=11;
203         Glib::RefPtr<Pango::Layout> l = CopyrightLabel->get_layout();
204         Pango::FontDescription fd = Pango::FontDescription("Sans, 11");
205         l->set_font_description(fd);
206         l->set_justify(Pango::ALIGN_CENTER);
207         fd.set_size(int(size*Pango::SCALE));
208         l->set_font_description(fd);
209         l->get_pixel_size(width,height);
210         while( width >= image_w-6 ){
211                 size-=0.5;
212                 fd.set_size((int)(size*Pango::SCALE));
213                 l->set_font_description(fd);
214                 l->get_pixel_size(width,height);
215         }
216         CopyrightLabel->modify_font(fd);
217
218         // Create the Version information label
219         Gtk::Label *VersionLabel = manage(new class Gtk::Label("Version"));
220         VersionLabel->set_size_request(image_w,80);
221         VersionLabel->set_flags(Gtk::CAN_FOCUS);
222         VersionLabel->set_alignment(0.5,0.5);
223         VersionLabel->set_padding(0,0);
224         VersionLabel->set_justify(Gtk::JUSTIFY_CENTER);
225         VersionLabel->set_line_wrap(false);
226         VersionLabel->modify_fg(Gtk::STATE_NORMAL,Gdk::Color("black"));
227
228         // Set the version label to contain the correct information
229         string ver;
230         ver+="Version "VERSION" ("__DATE__" "__TIME__")\n";
231         ver+="Using Synfig ";
232         ver+=synfig::get_version();
233         #ifdef __GNUC__
234                 ver+=strprintf(" and GNU G++ %d.%d.%d",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);
235         #endif
236
237         ver+=strprintf("\nGtk+ %d.%d.%d",gtk_major_version,gtk_minor_version,gtk_micro_version);
238
239         #ifdef _DEBUG
240                 ver+="\nDEBUG BUILD";
241         #endif
242         VersionLabel->set_text(ver);
243
244         /* Scale the text to fit */
245         width = 0;
246         height = 0;
247         size=11;
248         l = VersionLabel->get_layout();
249         fd = Pango::FontDescription("Sans, 11");
250         l->set_font_description(fd);
251         l->set_justify(Pango::ALIGN_CENTER);
252         fd.set_size(int(size*Pango::SCALE));
253         l->set_font_description(fd);
254         l->get_pixel_size(width,height);
255         while( width >= image_w-6 ){
256                 size-=0.5;
257                 fd.set_size((int)(size*Pango::SCALE));
258                 l->set_font_description(fd);
259                 l->get_pixel_size(width,height);
260         }
261         VersionLabel->modify_font(fd);
262
263         // Create the image that will be used on the close button
264         Gtk::Image *image2 = manage(new class Gtk::Image(Gtk::StockID("gtk-close"), Gtk::IconSize(4)));
265         image2->set_alignment(0.5,0.5);
266         image2->set_padding(0,0);
267
268         // Create the close button, and attach the image to it
269         CloseButton = manage(new class Gtk::Button());
270         CloseButton->set_size_request(24,24);
271         CloseButton->set_flags(Gtk::CAN_FOCUS);
272         _tooltips.set_tip(*CloseButton, "Close", "");
273         CloseButton->set_relief(Gtk::RELIEF_NONE);
274         CloseButton->add(*image2);
275
276         // Create the progress bar
277         progressbar = manage(new class Gtk::ProgressBar());
278         progressbar->set_size_request(image_w,24);
279
280         // Create the current task label
281         tasklabel = manage(new class Gtk::Label());
282         tasklabel->set_size_request(image_w,24);
283         tasklabel->set_use_underline(false);
284
285         // Create the Gtk::Fixed container and put all of the widgets into it
286         Gtk::Fixed *fixed1 = manage(new class Gtk::Fixed());
287         fixed1->put(*Logo, 0, 0);
288         fixed1->put(*CopyrightLabel, 0, image_h-25);
289         fixed1->put(*CloseButton, image_w-24, 0);
290         fixed1->put(*VersionLabel, 0, image_h-90);
291         fixed1->put(*progressbar, 0, image_h+24);
292         fixed1->put(*tasklabel, 0, image_h);
293
294         // Set up the parameters for this pop-up window
295         set_title("Synfig Studio "VERSION);
296         set_modal(false);
297         property_window_position().set_value(Gtk::WIN_POS_CENTER);
298         set_resizable(false);
299         add(*fixed1);
300
301         // show everything off
302         Logo->show();
303         CopyrightLabel->show();
304         image2->show();
305         CloseButton->show();
306         VersionLabel->show();
307         fixed1->show();
308
309         // Connect relevant signals
310         CloseButton->signal_clicked().connect(sigc::mem_fun(*this, &About::close));
311
312         cb=new AboutProgress(*this);
313 }
314
315 About::~About()
316 {
317         delete cb;
318 }
319
320 void About::close()
321 {
322         hide();
323         if(can_self_destruct)
324                 delete this;
325 }
326
327 void
328 About::set_can_self_destruct(bool x)
329 {
330         can_self_destruct=x;
331         if(x==true)
332                 CloseButton->show();
333         else
334                 CloseButton->hide();
335 }
336
337 synfig::ProgressCallback *
338 About::get_callback()
339 {
340         return cb;
341 }