1 /* === S Y N F I G ========================================================= */
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
36 #ifdef HAVE_SYS_ERRNO_H
37 #include <sys/errno.h>
39 #include <gtkmm/fileselection.h>
40 #include <gtkmm/dialog.h>
41 #include <gtkmm/messagedialog.h>
42 #include <gtkmm/label.h>
43 #include <gtkmm/stock.h>
44 #include <gtkmm/stockitem.h>
45 #include <gtkmm/iconsource.h>
46 #include <gtkmm/inputdialog.h>
47 #include <gtkmm/accelmap.h>
48 #include <gtkmm/uimanager.h>
52 #include <synfig/loadcanvas.h>
57 #include "canvasview.h"
58 #include "dialog_setup.h"
59 #include "dialog_gradient.h"
60 #include "dialog_color.h"
63 #include "onemoment.h"
65 #include "dockmanager.h"
67 #include "state_eyedrop.h"
68 #include "state_normal.h"
69 #include "state_draw.h"
70 #include "state_fill.h"
71 #include "state_bline.h"
72 #include "state_polygon.h"
73 #include "state_sketch.h"
74 #include "state_gradient.h"
75 #include "state_circle.h"
76 #include "state_rectangle.h"
77 #include "state_smoothmove.h"
78 #include "state_scale.h"
79 #include "state_width.h"
80 #include "state_rotate.h"
81 #include "state_zoom.h"
83 #include "devicetracker.h"
84 #include "dialog_tooloptions.h"
86 #include "autorecover.h"
88 #include <synfigapp/settings.h>
89 #include "dock_history.h"
90 #include "dock_canvases.h"
91 #include "dock_keyframes.h"
92 #include "dock_layers.h"
93 #include "dock_params.h"
94 #include "dock_metadata.h"
95 #include "dock_children.h"
96 #include "dock_info.h"
97 #include "dock_navigator.h"
98 #include "dock_layergroups.h"
99 #include "dock_timetrack.h"
100 #include "dock_curves.h"
102 #include "mod_palette/mod_palette.h"
103 #include "mod_mirror/mod_mirror.h"
105 #include <sys/stat.h>
111 #include "statemanager.h"
118 #define _WIN32_WINNT 0x0500
121 #include <gtkmm/accelmap.h>
122 #include <gtkmm/filechooser.h>
123 #include <gtkmm/filechooserdialog.h>
127 /* === U S I N G =========================================================== */
131 using namespace synfig;
132 using namespace studio;
134 /* === M A C R O S ========================================================= */
136 #ifndef SYNFIG_USER_APP_DIR
138 #define SYNFIG_USER_APP_DIR "Library/Synfig"
139 #elif defined(_WIN32)
140 #define SYNFIG_USER_APP_DIR "Synfig"
142 #define SYNFIG_USER_APP_DIR ".synfig"
147 #define DPM2DPI(x) (float(x)/39.3700787402f)
148 #define DPI2DPM(x) (float(x)*39.3700787402f)
154 # define IMAGE_DIR "share\\pixmaps"
159 # define IMAGE_DIR "/usr/local/share/pixmaps"
163 # define IMAGE_EXT "tif"
166 #include <synfigapp/main.h>
168 /* === S I G N A L S ======================================================= */
170 static sigc::signal<void> signal_present_all_;
172 App::signal_present_all() { return signal_present_all_; }
174 static sigc::signal<void> signal_recent_files_changed_;
176 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
178 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
179 sigc::signal<void,etl::loose_handle<CanvasView> >&
180 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
182 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
183 sigc::signal<void,etl::handle<Instance> >&
184 App::signal_instance_selected() { return signal_instance_selected_; }
186 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
187 sigc::signal<void,etl::handle<Instance> >&
188 App::signal_instance_created() { return signal_instance_created_; }
190 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
191 sigc::signal<void,etl::handle<Instance> >&
192 App::signal_instance_deleted() { return signal_instance_deleted_; }
194 /* === G L O B A L S ======================================================= */
196 static std::list<std::string> recent_files;
197 const std::list<std::string>& App::get_recent_files() { return recent_files; }
199 int App::Busy::count;
200 bool App::shutdown_in_progress;
202 synfig::Gamma App::gamma;
204 Glib::RefPtr<studio::UIManager> App::ui_manager_;
206 synfig::Distance::System App::distance_system;
208 studio::Dialog_Setup* App::dialog_setup;
210 etl::handle< studio::ModPalette > mod_palette_;
211 //studio::Dialog_Palette* App::dialog_palette;
213 std::list<etl::handle<Instance> > App::instance_list;
215 static etl::handle<synfigapp::UIInterface> ui_interface_;
216 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
218 etl::handle<Instance> App::selected_instance;
219 etl::handle<CanvasView> App::selected_canvas_view;
221 studio::Toolbox *studio::App::toolbox=NULL;
223 studio::AutoRecover *studio::App::auto_recover=NULL;
225 studio::IPC *ipc=NULL;
227 studio::DockManager* studio::App::dock_manager=0;
229 studio::DeviceTracker* studio::App::device_tracker=0;
231 studio::Dialog_Gradient* studio::App::dialog_gradient;
233 studio::Dialog_Color* studio::App::dialog_color;
235 Gtk::InputDialog* studio::App::dialog_input;
237 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
239 studio::Dock_History* dock_history;
240 studio::Dock_Canvases* dock_canvases;
241 studio::Dock_Keyframes* dock_keyframes;
242 studio::Dock_Layers* dock_layers;
243 studio::Dock_Params* dock_params;
244 studio::Dock_MetaData* dock_meta_data;
245 studio::Dock_Children* dock_children;
246 studio::Dock_Info* dock_info;
247 studio::Dock_LayerGroups* dock_layer_groups;
248 studio::Dock_Navigator* dock_navigator;
249 studio::Dock_Timetrack* dock_timetrack;
250 studio::Dock_Curves* dock_curves;
252 std::list< etl::handle< studio::Module > > module_list_;
254 bool studio::App::use_colorspace_gamma=true;
256 static int max_recent_files_=25;
257 int studio::App::get_max_recent_files() { return max_recent_files_; }
258 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
260 static synfig::String app_base_path_;
263 }; // END of namespace studio
264 studio::StateManager* state_manager;
269 class GlobalUIInterface : public synfigapp::UIInterface
273 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
278 true // use_separator
280 Gtk::Label label(message);
283 dialog.get_vbox()->pack_start(label);
284 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
285 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
287 dialog.set_default_response(dflt);
289 return (Response)dialog.run();
291 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
296 true // use_separator
298 Gtk::Label label(message);
301 dialog.get_vbox()->pack_start(label);
302 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
303 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
304 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
306 dialog.set_default_response(dflt);
308 return (Response)dialog.run();
310 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
315 true // use_separator
317 Gtk::Label label(message);
320 dialog.get_vbox()->pack_start(label);
321 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
322 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
324 dialog.set_default_response(dflt);
326 return (Response)dialog.run();
330 task(const std::string &task)
332 std::cerr<<task<<std::endl;
333 while(studio::App::events_pending())studio::App::iteration(false);
338 error(const std::string &err)
340 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
347 warning(const std::string &err)
349 std::cerr<<"warning: "<<err<<std::endl;
350 while(studio::App::events_pending())studio::App::iteration(false);
355 amount_complete(int current, int total)
357 while(studio::App::events_pending())studio::App::iteration(false);
362 /* === P R O C E D U R E S ================================================= */
364 typedef unsigned char U8;
365 typedef unsigned short U16;
366 typedef unsigned long U32;
376 static inline U32 hash_U32(U32 i)
378 i=i*1664525+1013904223;
379 i=i*1664525+1013904223;
380 i=i*1664525+1013904223;
385 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
386 #define endian_fix(x) (endian_fix_table[x])
388 #define endian_fix(x) (x)
391 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
394 unwound->element.serial=0;
395 unwound->element.checksum=0;
403 case '0': data=0; break;
404 case '1': data=1; break;
405 case '2': data=2; break;
406 case '3': data=3; break;
407 case '4': data=4; break;
408 case '5': data=5; break;
409 case '6': data=6; break;
410 case '7': data=7; break;
411 case '8': data=8; break;
412 case '9': data=9; break;
413 case 'a': case 'A': data=10; break;
414 case 'b': case 'B': data=11; break;
415 case 'c': case 'C': data=12; break;
416 case 'd': case 'D': data=13; break;
417 case 'e': case 'E': data=14; break;
418 case 'f': case 'F': data=15; break;
419 default: return 0; break;
422 unwound->element.checksum|=(((U32)data&3)<<bit);
423 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
428 int v_key_check(const char* key, U32* serial, U32 appid)
430 V_KeyUnwound unwound_key;
431 U32 appid_mask_a=hash_U32(appid);
432 U32 appid_mask_b=hash_U32(appid_mask_a);
434 if(!v_unwind_key(&unwound_key, key))
436 // Invalid characters in key
441 // Undo obfuscation pass
443 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
448 unwound_key.raw[endian_fix(i)]^=(next>>24);
452 unwound_key.element.serial^=appid_mask_a;
453 unwound_key.element.checksum^=appid_mask_b;
455 *serial=unwound_key.element.serial;
457 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
461 int check_license(String basedir)
463 #ifdef LICENSE_KEY_REQUIRED
468 license_file="/usr/local/etc/.synfiglicense";
470 license_file=basedir+"\\etc\\.synfiglicense";
474 key=Glib::file_get_contents(license_file);
475 } catch (Glib::FileError) { }
477 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
479 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
483 if(!App::dialog_entry(
484 _("Synfig Studio Authentication"),
485 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
488 throw String("No License");
491 FILE* file=fopen(license_file.c_str(),"w");
494 fprintf(file,"%s",key.c_str());
498 synfig::error("Unable to save license key!");
500 synfig::info("License Authenticated -- Serial #%05d",serial);
509 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
511 action_group_list.push_back(action_group);
512 Gtk::UIManager::insert_action_group(action_group, pos);
516 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
518 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
519 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
520 if(*iter==action_group)
522 action_group_list.erase(iter);
523 Gtk::UIManager::remove_action_group(action_group);
526 synfig::error("Unable to find action group");
530 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
532 ui_manager->insert_action_group(group,0);
535 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
536 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
539 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
542 if(*iter && (*iter)->get_name()!="menus")
544 synfig::info("Removing action group "+(*iter)->get_name());
545 ui_manager->remove_action_group(*iter);
549 ui_manager->insert_action_group(group,0);
552 for(;!prev_groups.empty();prev_groups.pop_front())
554 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
555 ui_manager->insert_action_group(prev_groups.front(),1);
560 class Preferences : public synfigapp::Settings
563 virtual bool get_value(const synfig::String& key, synfig::String& value)const
567 value=strprintf("%f %f %f %f",
568 App::gamma.get_gamma_r(),
569 App::gamma.get_gamma_g(),
570 App::gamma.get_gamma_b(),
571 App::gamma.get_black_level()
575 if(key=="time_format")
577 value=strprintf("%i",App::get_time_format());
580 if(key=="file_history.size")
582 value=strprintf("%i",App::get_max_recent_files());
585 if(key=="use_colorspace_gamma")
587 value=strprintf("%i",(int)App::use_colorspace_gamma);
590 if(key=="distance_system")
592 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
595 if(key=="auto_recover_backup_interval")
597 value=strprintf("%i",App::auto_recover->get_timeout());
601 return synfigapp::Settings::get_value(key,value);
604 virtual bool set_value(const synfig::String& key,const synfig::String& value)
610 strscanf(value,"%f %f %f %f",
617 App::gamma.set_all(r,g,b,blk);
621 if(key=="time_format")
623 int i(atoi(value.c_str()));
624 App::set_time_format(static_cast<synfig::Time::Format>(i));
627 if(key=="auto_recover_backup_interval")
629 int i(atoi(value.c_str()));
630 App::auto_recover->set_timeout(i);
633 if(key=="file_history.size")
635 int i(atoi(value.c_str()));
636 App::set_max_recent_files(i);
639 if(key=="use_colorspace_gamma")
641 int i(atoi(value.c_str()));
642 App::use_colorspace_gamma=i;
645 if(key=="distance_system")
647 App::distance_system=Distance::ident_system(value);;
651 return synfigapp::Settings::set_value(key,value);
654 virtual KeyList get_key_list()const
656 KeyList ret(synfigapp::Settings::get_key_list());
657 ret.push_back("gamma");
658 ret.push_back("time_format");
659 ret.push_back("distance_system");
660 ret.push_back("file_history.size");
661 ret.push_back("use_colorspace_gamma");
662 ret.push_back("auto_recover_backup_interval");
667 static ::Preferences _preferences;
672 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
674 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
676 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
678 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
679 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
680 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
681 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
682 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
683 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Show/Hide Ducks") );
684 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
685 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
686 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
687 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
688 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
689 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
691 // Add the synfigapp actions...
692 synfigapp::Action::Book::iterator iter;
693 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
695 actions_action_group->add(Gtk::Action::create(
696 "action-"+iter->second.name,
697 get_action_stock_id(iter->second),
698 iter->second.local_name,iter->second.local_name
702 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
703 #define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock,label,label) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
704 #define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ group->add(action,sig); }
706 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
707 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
708 DEFINE_ACTION("open", Gtk::Stock::OPEN);
709 DEFINE_ACTION("save", Gtk::Stock::SAVE);
710 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
711 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
712 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
713 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
714 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
715 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
716 DEFINE_ACTION("import", _("Import"));
717 DEFINE_ACTION("render", _("Render"));
718 DEFINE_ACTION("preview", _("Preview"));
719 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
720 DEFINE_ACTION("sound", _("Sound File"));
721 DEFINE_ACTION("options", _("Options"));
722 DEFINE_ACTION("close", _("Close"));
725 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
726 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
727 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
728 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
729 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
730 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
731 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
732 DEFINE_ACTION("properties", _("Properties"));
734 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
735 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
736 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
737 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
738 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
739 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
740 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
741 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
742 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
743 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
744 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
745 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
746 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
747 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
748 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
749 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
750 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
751 DEFINE_ACTION("play", _("Play"));
752 DEFINE_ACTION("pause", _("Pause"));
753 DEFINE_ACTION("stop", _("Stop"));
754 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
755 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
756 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
757 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
758 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
759 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
760 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
761 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
762 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
763 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
764 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
765 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
766 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
767 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
768 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
769 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
770 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
771 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
772 DEFINE_ACTION("seek-end", _("Seek to End"));
774 DEFINE_ACTION("action-group_add", _("Add group"));
776 DEFINE_ACTION("canvas-new", _("New Canvas"));
778 DEFINE_ACTION("amount-inc", _("Increase Amount"));
779 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
784 // Set up synfigapp actions
786 synfigapp::Action::Book::iterator iter;
788 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
790 Gtk::StockID stock_id;
792 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
794 //Gtk::Image* image(manage(new Gtk::Image()));
795 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
796 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
797 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
798 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
799 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
800 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
801 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
802 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
803 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
804 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
806 actions_action_group->add(Gtk::Action::create(
807 "action-"+iter->second.name,
809 iter->second.local_name,iter->second.local_name
817 Glib::ustring ui_info =
819 " <popup name='menu-toolbox' action='menu-toolbox'>"
820 " <menu action='menu-file'>"
823 " <popup name='menu-main' action='menu-main'>"
824 " <menu action='menu-file'>"
825 " <menuitem action='save' />"
826 " <menuitem action='save-as' />"
827 " <menuitem action='revert' />"
828 " <separator name='bleh01'/>"
829 " <menuitem action='cvs-add' />"
830 " <menuitem action='cvs-update' />"
831 " <menuitem action='cvs-commit' />"
832 " <menuitem action='cvs-revert' />"
833 " <separator name='bleh02'/>"
834 " <menuitem action='import' />"
835 " <separator name='bleh03'/>"
836 " <menuitem action='render' />"
837 " <menuitem action='preview' />"
838 " <menuitem action='sound' />"
839 " <separator name='bleh04'/>"
840 " <menuitem action='options' />"
841 " <menuitem action='close' />"
843 " <menu action='menu-edit'>"
844 " <menuitem action='undo'/>"
845 " <menuitem action='redo'/>"
846 " <separator name='bleh05'/>"
847 " <menuitem action='cut'/>"
848 " <menuitem action='copy'/>"
849 " <menuitem action='paste'/>"
850 " <separator name='bleh06'/>"
851 " <menuitem action='select-all-ducks'/>"
852 " <menuitem action='unselect-all-layers'/>"
853 " <separator name='bleh07'/>"
854 " <menuitem action='properties'/>"
856 " <menu action='menu-view'>"
857 " <menu action='menu-duck-mask'>"
858 " <menuitem action='mask-position-ducks' />"
859 " <menuitem action='mask-vertex-ducks' />"
860 " <menuitem action='mask-tangent-ducks' />"
861 " <menuitem action='mask-radius-ducks' />"
862 " <menuitem action='mask-width-ducks' />"
863 " <menuitem action='mask-angle-ducks' />"
865 " <menu action='menu-preview-quality'>"
866 " <menuitem action='quality-00' />"
867 " <menuitem action='quality-01' />"
868 " <menuitem action='quality-02' />"
869 " <menuitem action='quality-03' />"
870 " <menuitem action='quality-04' />"
871 " <menuitem action='quality-05' />"
872 " <menuitem action='quality-06' />"
873 " <menuitem action='quality-07' />"
874 " <menuitem action='quality-08' />"
875 " <menuitem action='quality-09' />"
876 " <menuitem action='quality-10' />"
878 " <separator name='bleh08'/>"
879 " <menuitem action='play'/>"
880 " <menuitem action='pause'/>"
881 " <menuitem action='stop'/>"
882 " <menuitem action='dialog-flipbook'/>"
883 " <separator name='bleh09'/>"
884 " <menuitem action='toggle-grid-show'/>"
885 " <menuitem action='toggle-grid-snap'/>"
886 " <menuitem action='toggle-guide-show'/>"
887 " <menuitem action='toggle-low-res'/>"
888 " <menuitem action='toggle-onion-skin'/>"
889 " <separator name='bleh10'/>"
890 " <menuitem action='canvas-zoom-in'/>"
891 " <menuitem action='canvas-zoom-out'/>"
892 " <menuitem action='canvas-zoom-fit'/>"
893 " <menuitem action='canvas-zoom-100'/>"
894 " <separator name='bleh11'/>"
895 " <menuitem action='time-zoom-in'/>"
896 " <menuitem action='time-zoom-out'/>"
897 " <separator name='bleh12'/>"
898 " <menuitem action='jump-next-keyframe'/>"
899 " <menuitem action='jump-prev-keyframe'/>"
900 " <menuitem action='seek-next-frame'/>"
901 " <menuitem action='seek-prev-frame'/>"
902 " <menuitem action='seek-next-second'/>"
903 " <menuitem action='seek-prev-second'/>"
904 " <menuitem action='seek-begin'/>"
905 " <menuitem action='seek-end'/>"
907 " <menu action='menu-canvas'>"
908 " <menuitem action='canvas-new'/>"
909 " <menuitem action='amount-inc'/>"
910 " <menuitem action='amount-dec'/>"
912 " <menu name='menu-state' action='menu-state'>"
914 " <menu action='menu-group'>"
915 " <menuitem action='action-group_add'/>"
917 " <menu action='menu-layer'>"
918 //" <menuitem action='cut'/>"
919 //" <menuitem action='copy'/>"
920 //" <menuitem action='paste'/>"
921 //" <separator name='bleh06'/>"
922 " <menu action='menu-layer-new'></menu>"
924 " <menu action='menu-keyframe'>"
925 " <menuitem action='keyframe-properties'/>"
932 " <menubar name='MenuBar'>"
933 " <menu action='MenuFile'>"
934 " <menuitem action='New'/>"
935 " <menuitem action='Open'/>"
937 " <menuitem action='Quit'/>"
939 " <menu action='MenuEdit'>"
940 " <menuitem action='Cut'/>"
941 " <menuitem action='Copy'/>"
942 " <menuitem action='Paste'/>"
945 " <toolbar name='ToolBar'>"
946 " <toolitem action='Open'/>"
947 " <toolitem action='Quit'/>"
953 actions_action_group->set_sensitive(false);
954 App::ui_manager()->set_add_tearoffs(true);
955 App::ui_manager()->insert_action_group(menus_action_group,1);
956 App::ui_manager()->insert_action_group(actions_action_group,1);
957 App::ui_manager()->add_ui_from_string(ui_info);
959 //App::ui_manager()->get_accel_group()->unlock();
961 catch(const Glib::Error& ex)
963 synfig::error("building menus and toolbars failed: " + ex.what());
966 // Add default keyboard accelerators
967 #define ACCEL(path,accel) \
969 Gtk::AccelKey accel_key(accel,path); \
970 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
973 #define ACCEL2(accel) \
975 Gtk::AccelKey accel_key(accel); \
976 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
979 ACCEL("<Actions>//select-all-ducks","<Control>a");
980 ACCEL("<Actions>//unselect-all-layers","<Control>d");
981 ACCEL("<Actions>//render","F9");
982 ACCEL("<Actions>//preview","F11");
983 ACCEL("<Actions>//properties","F8");
984 ACCEL("<Actions>//options","F12");
985 ACCEL("<Actions>//import","<control>i");
986 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
987 ACCEL("<Actions>//toggle-grid-show","<Control>g");
988 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
989 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
990 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
991 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
992 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
993 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
994 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
995 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
997 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
998 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
1000 ACCEL("<Actions>//quality-01","<Control>1");
1001 ACCEL("<Actions>//quality-02","<Control>2");
1002 ACCEL("<Actions>//quality-03","<Control>3");
1003 ACCEL("<Actions>//quality-04","<Control>4");
1004 ACCEL("<Actions>//quality-05","<Control>5");
1005 ACCEL("<Actions>//quality-06","<Control>6");
1006 ACCEL("<Actions>//quality-07","<Control>7");
1007 ACCEL("<Actions>//quality-08","<Control>8");
1008 ACCEL("<Actions>//quality-09","<Control>9");
1009 ACCEL("<Actions>//quality-10","<Control>0");
1010 ACCEL("<Actions>//undo","<Control>z");
1011 ACCEL("<Actions>//redo","<Control>r");
1012 ACCEL("<Actions>//action-layer_remove","Delete");
1014 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1015 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1016 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1017 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1018 ACCEL("<Actions>//time-zoom-in","+");
1019 ACCEL("<Actions>//time-zoom-out","_");
1021 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1022 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1024 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1025 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1026 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1027 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1028 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1029 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1030 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1031 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1032 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1033 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1034 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1035 ACCEL("<Actions>//seek-begin","Home");
1036 ACCEL("<Actions>//seek-end","End");
1037 ACCEL("<Actions>//state-normal","<Mod1>a");
1038 ACCEL("<Actions>//state-rotate","<Mod1>s");
1039 ACCEL("<Actions>//state-scale","<Mod1>d");
1040 ACCEL("<Actions>//state-bline","<Mod1>b");
1041 ACCEL("<Actions>//state-fill","<Mod1>f");
1042 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1043 ACCEL("<Actions>//state-gradient","<Mod1>g");
1044 ACCEL("<Actions>//state-zoom","<Mod1>z");
1045 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1051 #define mkdir(x,y) mkdir(x)
1054 /* === M E T H O D S ======================================================= */
1056 App::App(int *argc, char ***argv):
1057 Gtk::Main(argc,argv),
1058 IconControler(etl::dirname((*argv)[0]))
1060 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1063 serial_=check_license(app_base_path_);
1066 ui_interface_=new GlobalUIInterface();
1070 Glib::thread_init();
1072 distance_system=Distance::SYSTEM_UNITS;
1074 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1077 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1081 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1089 if(!SYNFIG_CHECK_VERSION())
1091 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1092 dialog_error_blocking("Synfig Studio",
1093 "This copy of Synfig Studio was compiled against a\n"
1094 "different version of libsynfig than what is currently\n"
1095 "installed. Synfig Studio will now abort. Try downloading\n"
1096 "the latest version from the Synfig website at\n"
1097 "http://www.synfig.com/ "
1102 catch(synfig::SoftwareExpired)
1104 cerr<<"FATAL: Software Expired"<<endl;
1105 dialog_error_blocking("Synfig Studio",
1106 "This copy of Synfig Studio has expired.\n"
1107 "Please erase this copy, or download and\n"
1108 "install the latest copy from the Synfig\n"
1109 "website at http://www.synfig.com/ ."
1113 Glib::set_application_name(_("Synfig Studio"));
1116 about_window.set_can_self_destruct(false);
1117 about_window.show();
1119 shutdown_in_progress=false;
1120 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1121 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1123 // Initialize the Synfig library
1124 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1127 get_ui_interface()->error("Failed to initialize synfig!");
1131 // add the preferences to the settings
1132 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1136 studio_init_cb.task("Init UI Manager...");
1137 App::ui_manager_=studio::UIManager::create();
1140 studio_init_cb.task("Init Dock Manager...");
1141 dock_manager=new studio::DockManager();
1143 studio_init_cb.task("Init State Manager...");
1144 state_manager=new StateManager();
1146 studio_init_cb.task("Init Toolbox...");
1147 toolbox=new studio::Toolbox();
1149 studio_init_cb.task("Init Tool Options...");
1150 dialog_tool_options=new studio::Dialog_ToolOptions();
1151 dock_manager->register_dockable(*dialog_tool_options);
1153 studio_init_cb.task("Init History...");
1154 dock_history=new studio::Dock_History();
1155 dock_manager->register_dockable(*dock_history);
1157 studio_init_cb.task("Init Canvases...");
1158 dock_canvases=new studio::Dock_Canvases();
1159 dock_manager->register_dockable(*dock_canvases);
1161 studio_init_cb.task("Init Keyframes...");
1162 dock_keyframes=new studio::Dock_Keyframes();
1163 dock_manager->register_dockable(*dock_keyframes);
1165 studio_init_cb.task("Init Layers...");
1166 dock_layers=new studio::Dock_Layers();
1167 dock_manager->register_dockable(*dock_layers);
1169 studio_init_cb.task("Init Params...");
1170 dock_params=new studio::Dock_Params();
1171 dock_manager->register_dockable(*dock_params);
1173 studio_init_cb.task("Init MetaData...");
1174 dock_meta_data=new studio::Dock_MetaData();
1175 dock_manager->register_dockable(*dock_meta_data);
1177 studio_init_cb.task("Init Children...");
1178 dock_children=new studio::Dock_Children();
1179 dock_manager->register_dockable(*dock_children);
1181 studio_init_cb.task("Init Info...");
1182 dock_info = new studio::Dock_Info();
1183 dock_manager->register_dockable(*dock_info);
1185 studio_init_cb.task("Init Navigator...");
1186 dock_navigator = new studio::Dock_Navigator();
1187 dock_manager->register_dockable(*dock_navigator);
1189 studio_init_cb.task("Init Timetrack...");
1190 dock_timetrack = new studio::Dock_Timetrack();
1191 dock_manager->register_dockable(*dock_timetrack);
1193 studio_init_cb.task("Init Curve Editor...");
1194 dock_curves = new studio::Dock_Curves();
1195 dock_manager->register_dockable(*dock_curves);
1197 studio_init_cb.task("Init Layer Groups...");
1198 dock_layer_groups = new studio::Dock_LayerGroups();
1199 dock_manager->register_dockable(*dock_layer_groups);
1202 studio_init_cb.task("Init Color Dialog...");
1203 dialog_color=new studio::Dialog_Color();
1205 studio_init_cb.task("Init Gradient Dialog...");
1206 dialog_gradient=new studio::Dialog_Gradient();
1208 studio_init_cb.task("Init DeviceTracker...");
1209 device_tracker=new studio::DeviceTracker();
1211 studio_init_cb.task("Init Tools...");
1212 state_manager->add_state(&state_normal);
1213 state_manager->add_state(&state_smooth_move);
1214 state_manager->add_state(&state_scale);
1215 state_manager->add_state(&state_rotate);
1217 state_manager->add_state(&state_bline);
1220 state_manager->add_state(&state_circle);
1221 state_manager->add_state(&state_rectangle);
1223 state_manager->add_state(&state_gradient);
1224 state_manager->add_state(&state_eyedrop);
1225 state_manager->add_state(&state_fill);
1227 state_manager->add_state(&state_zoom);
1229 // Disabled this tool because it should be
1230 // considered deprecated. Use the bline tool instead.
1231 if(getenv("SYNFIG_ENABLE_POLYGON")) state_manager->add_state(&state_polygon);
1233 // These tools are disabled by default for now,
1234 // because they tend to confuse users.
1235 if(getenv("SYNFIG_ENABLE_DRAW" )) state_manager->add_state(&state_draw);
1236 if(getenv("SYNFIG_ENABLE_SKETCH")) state_manager->add_state(&state_sketch);
1237 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1239 studio_init_cb.task("Init ModPalette...");
1240 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1242 studio_init_cb.task("Init ModMirror...");
1243 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1246 studio_init_cb.task("Init Setup Dialog...");
1247 dialog_setup=new studio::Dialog_Setup();
1249 studio_init_cb.task("Init Input Dialog...");
1250 dialog_input=new Gtk::InputDialog();
1251 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1252 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1254 studio_init_cb.task("Init auto recovery...");
1255 auto_recover=new AutoRecover();
1257 studio_init_cb.amount_complete(9250,10000);
1258 studio_init_cb.task("Loading Settings...");
1260 studio_init_cb.task("Checking auto-recover...");
1262 studio_init_cb.amount_complete(9900,10000);
1264 if(auto_recover->recovery_needed())
1266 about_window.hide();
1268 get_ui_interface()->yes_no(
1270 "Synfig Studio seems to have crashed\n"
1271 "before you could save all your files.\n"
1272 "Would you like to re-open those files\n"
1273 "and recover your unsaved changes?"
1274 )==synfigapp::UIInterface::RESPONSE_YES
1277 if(!auto_recover->recover())
1279 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1282 get_ui_interface()->error(
1283 _("Synfig Studio has attempted to recover\n"
1284 "from a previous crash. The files that it has\n"
1285 "recovered are NOT YET SAVED. It would be a good\n"
1286 "idea to review them and save them now.")
1289 about_window.show();
1292 // Look for any files given on the command line,
1293 // and load them if found.
1294 for(;*argc>=1;(*argc)--)
1295 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1297 studio_init_cb.task("Loading files...");
1298 about_window.hide();
1299 open((*argv)[*argc]);
1300 about_window.show();
1303 studio_init_cb.task("Done.");
1304 studio_init_cb.amount_complete(10000,10000);
1310 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1314 StateManager* App::get_state_manager() { return state_manager; }
1318 shutdown_in_progress=true;
1322 synfigapp::Main::settings().remove_domain("pref");
1324 selected_instance=0;
1326 // Unload all of the modules
1327 for(;!module_list_.empty();module_list_.pop_back());
1329 delete state_manager;
1333 delete auto_recover;
1337 // studio::App::iteration(false);
1341 // studio::App::iteration(false);
1343 // studio::App::iteration(false);
1345 delete dialog_setup;
1347 delete dialog_gradient;
1349 delete dialog_color;
1351 delete dialog_input;
1353 delete dock_manager;
1355 instance_list.clear();
1357 // studio::App::iteration(false);
1361 App::get_user_app_directory()
1363 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1367 App::get_config_file(const synfig::String& file)
1369 return Glib::build_filename(get_user_app_directory(),file);
1373 App::add_recent_file(const std::string &file_name)
1375 std::string filename(file_name);
1377 assert(!filename.empty());
1379 if(filename.empty())
1382 // Toss out any "hidden" files
1383 if(basename(filename)[0]=='.')
1386 // If we aren't an absolute path, turn outselves into one
1387 if(!is_absolute_path(filename))
1388 filename=absolute_path(filename);
1390 list<string>::iterator iter;
1391 // Check to see if the file is already on the list.
1392 // If it is, then remove it from the list
1393 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1396 recent_files.erase(iter);
1401 // Push the filename to the front of the list
1402 recent_files.push_front(filename);
1404 // Clean out the files at the end of the list.
1405 while(recent_files.size()>(unsigned)get_max_recent_files())
1406 recent_files.pop_back();
1408 signal_recent_files_changed_();
1413 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1416 App::get_time_format()
1418 return _App_time_format;
1422 App::set_time_format(synfig::Time::Format x)
1429 App::save_settings()
1434 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1435 setlocale(LC_NUMERIC, "C");
1437 std::string filename=get_config_file("accelrc");
1438 Gtk::AccelMap::save(filename);
1441 std::string filename=get_config_file("recentfiles");
1443 std::ofstream file(filename.c_str());
1447 synfig::warning("Unable to save %s",filename.c_str());
1451 list<string>::reverse_iterator iter;
1453 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1457 std::string filename=get_config_file("settings");
1458 synfigapp::Main::settings().save_to_file(filename);
1459 setlocale(LC_NUMERIC,old_locale);
1463 synfig::warning("Caught exception when attempting to save settings.");
1468 App::load_settings()
1473 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1474 setlocale(LC_NUMERIC, "C");
1476 std::string filename=get_config_file("accelrc");
1477 Gtk::AccelMap::load(filename);
1480 std::string filename=get_config_file("recentfiles");
1482 std::ifstream file(filename.c_str());
1486 std::string recent_file;
1487 getline(file,recent_file);
1488 if(!recent_file.empty())
1489 add_recent_file(recent_file);
1492 std::string filename=get_config_file("settings");
1493 if(!synfigapp::Main::settings().load_from_file(filename))
1495 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1496 //if(!synfigapp::Main::settings().load_from_file(filename))
1498 gamma.set_gamma(1.0/2.2);
1499 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1500 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1501 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1502 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1503 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1504 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1505 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1506 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1507 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1508 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1509 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1510 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1511 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1514 setlocale(LC_NUMERIC,old_locale);
1518 synfig::warning("Caught exception when attempting to load settings.");
1523 App::shutdown_request(GdkEventAny*)
1527 //return !shutdown_in_progress;
1533 if(shutdown_in_progress)return;
1536 get_ui_interface()->task("Quit Request");
1539 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1543 std::list<etl::handle<Instance> >::iterator iter;
1544 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1546 if(!(*iter)->safe_close())
1550 if((*iter)->synfigapp::Instance::get_action_count())
1552 handle<synfigapp::UIInterface> uim;
1553 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1555 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1556 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1558 case synfigapp::UIInterface::RESPONSE_NO:
1560 case synfigapp::UIInterface::RESPONSE_YES:
1563 case synfigapp::UIInterface::RESPONSE_CANCEL:
1572 if((*iter)->synfigapp::Instance::is_modified())
1574 handle<synfigapp::UIInterface> uim;
1575 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1577 string str=strprintf(_("%s has changes not yet on the CVS repository.\nWould you like to commit these changes?"),(*iter)->get_file_name().c_str() );
1578 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1580 case synfigapp::UIInterface::RESPONSE_NO:
1582 case synfigapp::UIInterface::RESPONSE_YES:
1583 (*iter)->dialog_cvs_commit();
1585 case synfigapp::UIInterface::RESPONSE_CANCEL:
1594 // This next line causes things to crash for some reason
1598 shutdown_in_progress=true;
1600 instance_list.clear();
1602 while(studio::App::events_pending())studio::App::iteration(false);
1605 auto_recover->normal_shutdown();
1607 get_ui_interface()->task("Quit Request sent");
1613 dialog_setup->refresh();
1614 dialog_setup->show();
1617 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1618 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1621 //#define USE_WIN32_FILE_DIALOGS 1
1624 #ifdef USE_WIN32_FILE_DIALOGS
1625 static OPENFILENAME ofn={};
1629 #include <gdk/gdkwin32.h>
1633 App::dialog_open_file(const std::string &title, std::string &filename)
1635 #ifdef USE_WIN32_FILE_DIALOGS
1636 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1638 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1639 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1640 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1642 ofn.lStructSize=sizeof(OPENFILENAME);
1643 ofn.hwndOwner = hWnd;
1644 ofn.hInstance = hInstance;
1645 ofn.lpstrFilter = szFilter;
1646 // ofn.lpstrCustomFilter=NULL;
1647 // ofn.nMaxCustFilter=0;
1648 // ofn.nFilterIndex=0;
1649 // ofn.lpstrFile=NULL;
1650 ofn.nMaxFile=MAX_PATH;
1651 // ofn.lpstrFileTitle=NULL;
1652 // ofn.lpstrInitialDir=NULL;
1653 // ofn.lpstrTitle=NULL;
1654 ofn.Flags=OFN_HIDEREADONLY;
1655 // ofn.nFileOffset=0;
1656 // ofn.nFileExtension=0;
1657 ofn.lpstrDefExt=TEXT("sif");
1658 // ofn.lCustData = 0l;
1660 // ofn.lpTemplateName=NULL;
1662 CHAR szFilename[MAX_PATH];
1664 strcpy(szFilename,filename.c_str());
1665 strcpy(szTitle,title.c_str());
1667 ofn.lpstrFile=szFilename;
1668 ofn.lpstrFileTitle=szTitle;
1670 if(GetOpenFileName(&ofn))
1672 filename=szFilename;
1678 synfig::String prev_path;
1679 if(!_preferences.get_value("curr_path",prev_path))
1682 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1683 dialog->set_current_folder(prev_path);
1684 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1685 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1686 if(!filename.empty())
1687 dialog->set_filename(filename);
1688 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1689 filename=dialog->get_filename();
1701 GtkWidget *fileselection;
1702 fileselection = gtk_file_selection_new(title.c_str());
1705 if(basename(filename)==filename)
1707 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1710 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1712 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1714 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1715 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1717 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1718 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1720 gtk_widget_show(fileselection);
1728 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1729 _preferences.set_value("curr_path",dirname(filename));
1733 gtk_widget_destroy(fileselection);
1736 gtk_widget_destroy(fileselection);
1743 App::dialog_save_file(const std::string &title, std::string &filename)
1745 #ifdef USE_WIN32_FILE_DIALOGS
1746 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1748 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1749 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1750 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1752 ofn.lStructSize=sizeof(OPENFILENAME);
1753 ofn.hwndOwner = hWnd;
1754 ofn.hInstance = hInstance;
1755 ofn.lpstrFilter = szFilter;
1756 // ofn.lpstrCustomFilter=NULL;
1757 // ofn.nMaxCustFilter=0;
1758 // ofn.nFilterIndex=0;
1759 // ofn.lpstrFile=NULL;
1760 ofn.nMaxFile=MAX_PATH;
1761 // ofn.lpstrFileTitle=NULL;
1762 // ofn.lpstrInitialDir=NULL;
1763 // ofn.lpstrTitle=NULL;
1764 ofn.Flags=OFN_OVERWRITEPROMPT;
1765 // ofn.nFileOffset=0;
1766 // ofn.nFileExtension=0;
1767 ofn.lpstrDefExt=TEXT("sif");
1768 // ofn.lCustData = 0l;
1770 // ofn.lpTemplateName=NULL;
1772 CHAR szFilename[MAX_PATH];
1774 strcpy(szFilename,filename.c_str());
1775 strcpy(szTitle,title.c_str());
1777 ofn.lpstrFile=szFilename;
1778 ofn.lpstrFileTitle=szTitle;
1780 if(GetSaveFileName(&ofn))
1782 filename=szFilename;
1787 synfig::String prev_path;
1788 if(!_preferences.get_value("curr_path",prev_path))
1791 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1792 dialog->set_current_folder(prev_path);
1793 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1794 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1795 if(!filename.empty())
1796 dialog->set_filename(filename);
1797 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1798 filename=dialog->get_filename();
1804 // return dialog_open_file(title, filename);
1809 App::dialog_saveas_file(const std::string &title, std::string &filename)
1811 #if USE_WIN32_FILE_DIALOGS
1812 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1814 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1815 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1816 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1818 ofn.lStructSize=sizeof(OPENFILENAME);
1819 ofn.hwndOwner = hWnd;
1820 ofn.hInstance = hInstance;
1821 ofn.lpstrFilter = szFilter;
1822 // ofn.lpstrCustomFilter=NULL;
1823 // ofn.nMaxCustFilter=0;
1824 // ofn.nFilterIndex=0;
1825 // ofn.lpstrFile=NULL;
1826 ofn.nMaxFile=MAX_PATH;
1827 // ofn.lpstrFileTitle=NULL;
1828 // ofn.lpstrInitialDir=NULL;
1829 // ofn.lpstrTitle=NULL;
1830 ofn.Flags=OFN_OVERWRITEPROMPT;
1831 // ofn.nFileOffset=0;
1832 // ofn.nFileExtension=0;
1833 ofn.lpstrDefExt=TEXT("sif");
1834 // ofn.lCustData = 0l;
1836 // ofn.lpTemplateName=NULL;
1838 CHAR szFilename[MAX_PATH];
1840 strcpy(szFilename,filename.c_str());
1841 strcpy(szTitle,title.c_str());
1843 ofn.lpstrFile=szFilename;
1844 ofn.lpstrFileTitle=szTitle;
1846 if(GetSaveFileName(&ofn))
1848 filename=szFilename;
1853 synfig::String prev_path;
1854 if(!_preferences.get_value("curr_path",prev_path))
1857 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1858 dialog->set_current_folder(prev_path);
1859 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1860 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1861 if(!filename.empty())
1862 dialog->set_filename(filename);
1863 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1864 filename=dialog->get_filename();
1870 // return dialog_open_file(title, filename);
1875 App::dialog_error_blocking(const std::string &title, const std::string &message)
1877 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1878 dialog.set_title(title);
1884 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1886 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
1887 dialog.set_title(title);
1893 App::dialog_yes_no(const std::string &title, const std::string &message)
1898 true // use_separator
1900 Gtk::Label label(message);
1903 dialog.get_vbox()->pack_start(label);
1904 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1905 dialog.add_button(Gtk::StockID("gtk-no"),0);
1907 return dialog.run();
1911 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1916 true // use_separator
1918 Gtk::Label label(message);
1921 dialog.get_vbox()->pack_start(label);
1922 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1923 dialog.add_button(Gtk::StockID("gtk-no"),0);
1924 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1926 return dialog.run();
1930 App::dialog_not_implemented()
1932 Gtk::MessageDialog dialog("Feature not available", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1933 dialog.set_secondary_text("Sorry, this feature has not yet been implemented.");
1938 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1943 true // use_separator
1945 Gtk::Label label(message);
1947 dialog.get_vbox()->pack_start(label);
1950 entry.set_text(text);
1952 entry.set_activates_default(true);
1953 dialog.get_vbox()->pack_start(entry);
1955 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1956 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1957 dialog.set_default_response(Gtk::RESPONSE_OK);
1958 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1961 if(dialog.run()!=Gtk::RESPONSE_OK)
1964 text=entry.get_text();
1973 App::open(std::string filename)
1975 return open_as(filename,filename);
1979 App::open_as(std::string filename,std::string as)
1982 char long_name[1024];
1983 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1989 OneMoment one_moment;
1991 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1992 if(canvas && get_instance(canvas))
1994 get_instance(canvas)->find_canvas_view(canvas)->present();
1995 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1998 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2000 add_recent_file(as);
2002 handle<Instance> instance(Instance::create(canvas));
2005 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2009 if(instance->is_updated() && App::dialog_yes_no(_("CVS Update"), _("There appears to be a newer version of this file available on the CVS repository.\nWould you like to update now? (It would probably be a good idea)")))
2010 instance->dialog_cvs_update();
2014 dialog_error_blocking(_("Error"), x);
2019 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2023 _preferences.set_value("curr_path",dirname(as));
2032 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2033 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2035 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2037 canvas->rend_desc().set_frame_rate(24.0);
2038 canvas->rend_desc().set_time_start(0.0);
2039 canvas->rend_desc().set_time_end(00.0);
2040 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2041 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2042 canvas->rend_desc().set_tl(Vector(-4,2.25));
2043 canvas->rend_desc().set_br(Vector(4,-2.25));
2044 canvas->rend_desc().set_w(480);
2045 canvas->rend_desc().set_h(270);
2046 canvas->rend_desc().set_antialias(1);
2047 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2048 canvas->set_file_name(file_name);
2050 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2056 string filename="*.sif";
2058 while(dialog_open_file("Open", filename))
2060 // If the filename still has wildcards, then we should
2061 // continue looking for the file we want
2062 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2068 get_ui_interface()->error(_("Unable to open file"));
2073 App::set_selected_instance(etl::loose_handle<Instance> instance)
2075 /* if(get_selected_instance()==instance)
2077 selected_instance=instance;
2078 signal_instance_selected()(instance);
2084 selected_instance=instance;
2085 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2089 instance->focus(instance->get_canvas());
2092 set_selected_canvas_view(0);
2094 signal_instance_selected()(instance);
2098 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2100 selected_canvas_view=canvas_view;
2101 signal_canvas_view_focus()(selected_canvas_view);
2104 selected_instance=canvas_view->get_instance();
2105 signal_instance_selected()(canvas_view->get_instance());
2108 if(get_selected_canvas_view()==canvas_view)
2110 signal_canvas_view_focus()(selected_canvas_view);
2111 signal_instance_selected()(canvas_view->get_instance());
2114 selected_canvas_view=canvas_view;
2115 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2116 set_selected_instance(canvas_view->get_instance());
2117 signal_canvas_view_focus()(selected_canvas_view);
2121 etl::loose_handle<Instance>
2122 App::get_instance(Canvas::Handle canvas)
2124 if(!canvas) return 0;
2125 canvas=canvas->get_root();
2127 std::list<etl::handle<Instance> >::iterator iter;
2128 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2130 if((*iter)->get_canvas()==canvas)
2139 (new class About())->show();
2145 if(selected_instance)
2146 selected_instance->undo();
2152 if(selected_instance)
2153 selected_instance->redo();
2157 studio::App::get_base_path()
2159 return app_base_path_;