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"
140 #define SYNFIG_USER_APP_DIR "Synfig"
145 #define DPM2DPI(x) (float(x)/39.3700787402f)
146 #define DPI2DPM(x) (float(x)*39.3700787402f)
152 # define IMAGE_DIR "share\\pixmaps"
157 # define IMAGE_DIR "/usr/local/share/pixmaps"
161 # define IMAGE_EXT "tif"
164 #include <synfigapp/main.h>
166 /* === S I G N A L S ======================================================= */
168 static sigc::signal<void> signal_present_all_;
170 App::signal_present_all() { return signal_present_all_; }
172 static sigc::signal<void> signal_recent_files_changed_;
174 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
176 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
177 sigc::signal<void,etl::loose_handle<CanvasView> >&
178 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
180 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
181 sigc::signal<void,etl::handle<Instance> >&
182 App::signal_instance_selected() { return signal_instance_selected_; }
184 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
185 sigc::signal<void,etl::handle<Instance> >&
186 App::signal_instance_created() { return signal_instance_created_; }
188 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
189 sigc::signal<void,etl::handle<Instance> >&
190 App::signal_instance_deleted() { return signal_instance_deleted_; }
192 /* === G L O B A L S ======================================================= */
194 static std::list<std::string> recent_files;
195 const std::list<std::string>& App::get_recent_files() { return recent_files; }
197 int App::Busy::count;
198 bool App::shutdown_in_progress;
200 synfig::Gamma App::gamma;
202 Glib::RefPtr<studio::UIManager> App::ui_manager_;
204 synfig::Distance::System App::distance_system;
206 studio::Dialog_Setup* App::dialog_setup;
208 etl::handle< studio::ModPalette > mod_palette_;
209 //studio::Dialog_Palette* App::dialog_palette;
211 std::list<etl::handle<Instance> > App::instance_list;
213 static etl::handle<synfigapp::UIInterface> ui_interface_;
214 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
216 etl::handle<Instance> App::selected_instance;
217 etl::handle<CanvasView> App::selected_canvas_view;
219 studio::Toolbox *studio::App::toolbox=NULL;
221 studio::AutoRecover *studio::App::auto_recover=NULL;
223 studio::IPC *ipc=NULL;
225 studio::DockManager* studio::App::dock_manager=0;
227 studio::DeviceTracker* studio::App::device_tracker=0;
229 studio::Dialog_Gradient* studio::App::dialog_gradient;
231 studio::Dialog_Color* studio::App::dialog_color;
233 Gtk::InputDialog* studio::App::dialog_input;
235 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
237 studio::Dock_History* dock_history;
238 studio::Dock_Canvases* dock_canvases;
239 studio::Dock_Keyframes* dock_keyframes;
240 studio::Dock_Layers* dock_layers;
241 studio::Dock_Params* dock_params;
242 studio::Dock_MetaData* dock_meta_data;
243 studio::Dock_Children* dock_children;
244 studio::Dock_Info* dock_info;
245 studio::Dock_LayerGroups* dock_layer_groups;
246 studio::Dock_Navigator* dock_navigator;
247 studio::Dock_Timetrack* dock_timetrack;
248 studio::Dock_Curves* dock_curves;
250 std::list< etl::handle< studio::Module > > module_list_;
252 bool studio::App::use_colorspace_gamma=true;
254 static int max_recent_files_=25;
255 int studio::App::get_max_recent_files() { return max_recent_files_; }
256 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
258 static synfig::String app_base_path_;
261 }; // END of namespace studio
262 studio::StateManager* state_manager;
267 class GlobalUIInterface : public synfigapp::UIInterface
271 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
276 true // use_separator
278 Gtk::Label label(message);
281 dialog.get_vbox()->pack_start(label);
282 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
283 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
285 dialog.set_default_response(dflt);
287 return (Response)dialog.run();
289 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
294 true // use_separator
296 Gtk::Label label(message);
299 dialog.get_vbox()->pack_start(label);
300 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
301 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
302 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
304 dialog.set_default_response(dflt);
306 return (Response)dialog.run();
308 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
313 true // use_separator
315 Gtk::Label label(message);
318 dialog.get_vbox()->pack_start(label);
319 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
320 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
322 dialog.set_default_response(dflt);
324 return (Response)dialog.run();
328 task(const std::string &task)
330 std::cerr<<task<<std::endl;
331 while(studio::App::events_pending())studio::App::iteration(false);
336 error(const std::string &err)
338 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
345 warning(const std::string &err)
347 std::cerr<<"warning: "<<err<<std::endl;
348 while(studio::App::events_pending())studio::App::iteration(false);
353 amount_complete(int current, int total)
355 while(studio::App::events_pending())studio::App::iteration(false);
360 /* === P R O C E D U R E S ================================================= */
362 typedef unsigned char U8;
363 typedef unsigned short U16;
364 typedef unsigned long U32;
374 static inline U32 hash_U32(U32 i)
376 i=i*1664525+1013904223;
377 i=i*1664525+1013904223;
378 i=i*1664525+1013904223;
383 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
384 #define endian_fix(x) (endian_fix_table[x])
386 #define endian_fix(x) (x)
389 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
392 unwound->element.serial=0;
393 unwound->element.checksum=0;
401 case '0': data=0; break;
402 case '1': data=1; break;
403 case '2': data=2; break;
404 case '3': data=3; break;
405 case '4': data=4; break;
406 case '5': data=5; break;
407 case '6': data=6; break;
408 case '7': data=7; break;
409 case '8': data=8; break;
410 case '9': data=9; break;
411 case 'a': case 'A': data=10; break;
412 case 'b': case 'B': data=11; break;
413 case 'c': case 'C': data=12; break;
414 case 'd': case 'D': data=13; break;
415 case 'e': case 'E': data=14; break;
416 case 'f': case 'F': data=15; break;
417 default: return 0; break;
420 unwound->element.checksum|=(((U32)data&3)<<bit);
421 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
426 int v_key_check(const char* key, U32* serial, U32 appid)
428 V_KeyUnwound unwound_key;
429 U32 appid_mask_a=hash_U32(appid);
430 U32 appid_mask_b=hash_U32(appid_mask_a);
432 if(!v_unwind_key(&unwound_key, key))
434 // Invalid characters in key
439 // Undo obfuscation pass
441 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
446 unwound_key.raw[endian_fix(i)]^=(next>>24);
450 unwound_key.element.serial^=appid_mask_a;
451 unwound_key.element.checksum^=appid_mask_b;
453 *serial=unwound_key.element.serial;
455 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
459 int check_license(String basedir)
461 #ifdef LICENSE_KEY_REQUIRED
466 license_file="/usr/local/etc/.synfiglicense";
468 license_file=basedir+"\\etc\\.synfiglicense";
472 key=Glib::file_get_contents(license_file);
473 } catch (Glib::FileError) { }
475 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
477 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
481 if(!App::dialog_entry(
482 _("Synfig Studio Authentication"),
483 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
486 throw String("No License");
489 FILE* file=fopen(license_file.c_str(),"w");
492 fprintf(file,"%s",key.c_str());
496 synfig::error("Unable to save license key!");
498 synfig::info("License Authenticated -- Serial #%05d",serial);
507 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
509 action_group_list.push_back(action_group);
510 Gtk::UIManager::insert_action_group(action_group, pos);
514 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
516 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
517 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
518 if(*iter==action_group)
520 action_group_list.erase(iter);
521 Gtk::UIManager::remove_action_group(action_group);
524 synfig::error("Unable to find action group");
528 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
530 ui_manager->insert_action_group(group,0);
533 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
534 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
537 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
540 if(*iter && (*iter)->get_name()!="menus")
542 synfig::info("Removing action group "+(*iter)->get_name());
543 ui_manager->remove_action_group(*iter);
547 ui_manager->insert_action_group(group,0);
550 for(;!prev_groups.empty();prev_groups.pop_front())
552 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
553 ui_manager->insert_action_group(prev_groups.front(),1);
558 class Preferences : public synfigapp::Settings
561 virtual bool get_value(const synfig::String& key, synfig::String& value)const
565 value=strprintf("%f %f %f %f",
566 App::gamma.get_gamma_r(),
567 App::gamma.get_gamma_g(),
568 App::gamma.get_gamma_b(),
569 App::gamma.get_black_level()
573 if(key=="time_format")
575 value=strprintf("%i",App::get_time_format());
578 if(key=="file_history.size")
580 value=strprintf("%i",App::get_max_recent_files());
583 if(key=="use_colorspace_gamma")
585 value=strprintf("%i",(int)App::use_colorspace_gamma);
588 if(key=="distance_system")
590 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
593 if(key=="auto_recover_backup_interval")
595 value=strprintf("%i",App::auto_recover->get_timeout());
599 return synfigapp::Settings::get_value(key,value);
602 virtual bool set_value(const synfig::String& key,const synfig::String& value)
608 strscanf(value,"%f %f %f %f",
615 App::gamma.set_all(r,g,b,blk);
619 if(key=="time_format")
621 int i(atoi(value.c_str()));
622 App::set_time_format(static_cast<synfig::Time::Format>(i));
625 if(key=="auto_recover_backup_interval")
627 int i(atoi(value.c_str()));
628 App::auto_recover->set_timeout(i);
631 if(key=="file_history.size")
633 int i(atoi(value.c_str()));
634 App::set_max_recent_files(i);
637 if(key=="use_colorspace_gamma")
639 int i(atoi(value.c_str()));
640 App::use_colorspace_gamma=i;
643 if(key=="distance_system")
645 App::distance_system=Distance::ident_system(value);;
649 return synfigapp::Settings::set_value(key,value);
652 virtual KeyList get_key_list()const
654 KeyList ret(synfigapp::Settings::get_key_list());
655 ret.push_back("gamma");
656 ret.push_back("time_format");
657 ret.push_back("distance_system");
658 ret.push_back("file_history.size");
659 ret.push_back("use_colorspace_gamma");
660 ret.push_back("auto_recover_backup_interval");
665 static ::Preferences _preferences;
670 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
672 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
674 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
676 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
677 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
678 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
679 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
680 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
681 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Show/Hide Ducks") );
682 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
683 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
684 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
685 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
686 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
687 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
689 // Add the synfigapp actions...
690 synfigapp::Action::Book::iterator iter;
691 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
693 actions_action_group->add(Gtk::Action::create(
694 "action-"+iter->second.name,
695 get_action_stock_id(iter->second),
696 iter->second.local_name,iter->second.local_name
700 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
701 #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); }
702 #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); }
704 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
705 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
706 DEFINE_ACTION("open", Gtk::Stock::OPEN);
707 DEFINE_ACTION("save", Gtk::Stock::SAVE);
708 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
709 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
710 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
711 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
712 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
713 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
714 DEFINE_ACTION("import", _("Import"));
715 DEFINE_ACTION("render", _("Render"));
716 DEFINE_ACTION("preview", _("Preview"));
717 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
718 DEFINE_ACTION("sound", _("Sound File"));
719 DEFINE_ACTION("options", _("Options"));
720 DEFINE_ACTION("close", _("Close"));
723 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
724 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
725 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
726 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
727 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
728 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
729 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
730 DEFINE_ACTION("properties", _("Properties"));
732 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
733 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
734 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
735 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
736 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
737 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
738 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
739 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
740 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
741 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
742 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
743 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
744 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
745 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
746 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
747 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
748 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
749 DEFINE_ACTION("play", _("Play"));
750 DEFINE_ACTION("pause", _("Pause"));
751 DEFINE_ACTION("stop", _("Stop"));
752 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
753 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
754 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
755 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
756 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
757 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
758 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
759 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
760 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
761 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
762 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
763 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
764 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
765 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
766 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
767 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
768 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
769 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
770 DEFINE_ACTION("seek-end", _("Seek to End"));
772 DEFINE_ACTION("action-group_add", _("Add group"));
774 DEFINE_ACTION("canvas-new", _("New Canvas"));
776 DEFINE_ACTION("amount-inc", _("Increase Amount"));
777 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
782 // Set up synfigapp actions
784 synfigapp::Action::Book::iterator iter;
786 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
788 Gtk::StockID stock_id;
790 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
792 //Gtk::Image* image(manage(new Gtk::Image()));
793 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
794 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
795 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
796 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
797 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
798 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
799 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
800 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
801 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
802 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
804 actions_action_group->add(Gtk::Action::create(
805 "action-"+iter->second.name,
807 iter->second.local_name,iter->second.local_name
815 Glib::ustring ui_info =
817 " <popup name='menu-toolbox' action='menu-toolbox'>"
818 " <menu action='menu-file'>"
821 " <popup name='menu-main' action='menu-main'>"
822 " <menu action='menu-file'>"
823 " <menuitem action='save' />"
824 " <menuitem action='save-as' />"
825 " <menuitem action='revert' />"
826 " <separator name='bleh01'/>"
827 " <menuitem action='cvs-add' />"
828 " <menuitem action='cvs-update' />"
829 " <menuitem action='cvs-commit' />"
830 " <menuitem action='cvs-revert' />"
831 " <separator name='bleh02'/>"
832 " <menuitem action='import' />"
833 " <separator name='bleh03'/>"
834 " <menuitem action='render' />"
835 " <menuitem action='preview' />"
836 " <menuitem action='sound' />"
837 " <separator name='bleh04'/>"
838 " <menuitem action='options' />"
839 " <menuitem action='close' />"
841 " <menu action='menu-edit'>"
842 " <menuitem action='undo'/>"
843 " <menuitem action='redo'/>"
844 " <separator name='bleh05'/>"
845 " <menuitem action='cut'/>"
846 " <menuitem action='copy'/>"
847 " <menuitem action='paste'/>"
848 " <separator name='bleh06'/>"
849 " <menuitem action='select-all-ducks'/>"
850 " <menuitem action='unselect-all-layers'/>"
851 " <separator name='bleh07'/>"
852 " <menuitem action='properties'/>"
854 " <menu action='menu-view'>"
855 " <menu action='menu-duck-mask'>"
856 " <menuitem action='mask-position-ducks' />"
857 " <menuitem action='mask-vertex-ducks' />"
858 " <menuitem action='mask-tangent-ducks' />"
859 " <menuitem action='mask-radius-ducks' />"
860 " <menuitem action='mask-width-ducks' />"
861 " <menuitem action='mask-angle-ducks' />"
863 " <menu action='menu-preview-quality'>"
864 " <menuitem action='quality-00' />"
865 " <menuitem action='quality-01' />"
866 " <menuitem action='quality-02' />"
867 " <menuitem action='quality-03' />"
868 " <menuitem action='quality-04' />"
869 " <menuitem action='quality-05' />"
870 " <menuitem action='quality-06' />"
871 " <menuitem action='quality-07' />"
872 " <menuitem action='quality-08' />"
873 " <menuitem action='quality-09' />"
874 " <menuitem action='quality-10' />"
876 " <separator name='bleh08'/>"
877 " <menuitem action='play'/>"
878 " <menuitem action='pause'/>"
879 " <menuitem action='stop'/>"
880 " <menuitem action='dialog-flipbook'/>"
881 " <separator name='bleh09'/>"
882 " <menuitem action='toggle-grid-show'/>"
883 " <menuitem action='toggle-grid-snap'/>"
884 " <menuitem action='toggle-guide-show'/>"
885 " <menuitem action='toggle-low-res'/>"
886 " <menuitem action='toggle-onion-skin'/>"
887 " <separator name='bleh10'/>"
888 " <menuitem action='canvas-zoom-in'/>"
889 " <menuitem action='canvas-zoom-out'/>"
890 " <menuitem action='canvas-zoom-fit'/>"
891 " <menuitem action='canvas-zoom-100'/>"
892 " <separator name='bleh11'/>"
893 " <menuitem action='time-zoom-in'/>"
894 " <menuitem action='time-zoom-out'/>"
895 " <separator name='bleh12'/>"
896 " <menuitem action='jump-next-keyframe'/>"
897 " <menuitem action='jump-prev-keyframe'/>"
898 " <menuitem action='seek-next-frame'/>"
899 " <menuitem action='seek-prev-frame'/>"
900 " <menuitem action='seek-next-second'/>"
901 " <menuitem action='seek-prev-second'/>"
902 " <menuitem action='seek-begin'/>"
903 " <menuitem action='seek-end'/>"
905 " <menu action='menu-canvas'>"
906 " <menuitem action='canvas-new'/>"
907 " <menuitem action='amount-inc'/>"
908 " <menuitem action='amount-dec'/>"
910 " <menu name='menu-state' action='menu-state'>"
912 " <menu action='menu-group'>"
913 " <menuitem action='action-group_add'/>"
915 " <menu action='menu-layer'>"
916 //" <menuitem action='cut'/>"
917 //" <menuitem action='copy'/>"
918 //" <menuitem action='paste'/>"
919 //" <separator name='bleh06'/>"
920 " <menu action='menu-layer-new'></menu>"
922 " <menu action='menu-keyframe'>"
923 " <menuitem action='keyframe-properties'/>"
930 " <menubar name='MenuBar'>"
931 " <menu action='MenuFile'>"
932 " <menuitem action='New'/>"
933 " <menuitem action='Open'/>"
935 " <menuitem action='Quit'/>"
937 " <menu action='MenuEdit'>"
938 " <menuitem action='Cut'/>"
939 " <menuitem action='Copy'/>"
940 " <menuitem action='Paste'/>"
943 " <toolbar name='ToolBar'>"
944 " <toolitem action='Open'/>"
945 " <toolitem action='Quit'/>"
951 actions_action_group->set_sensitive(false);
952 App::ui_manager()->set_add_tearoffs(true);
953 App::ui_manager()->insert_action_group(menus_action_group,1);
954 App::ui_manager()->insert_action_group(actions_action_group,1);
955 App::ui_manager()->add_ui_from_string(ui_info);
957 //App::ui_manager()->get_accel_group()->unlock();
959 catch(const Glib::Error& ex)
961 synfig::error("building menus and toolbars failed: " + ex.what());
964 // Add default keyboard accelerators
965 #define ACCEL(path,accel) \
967 Gtk::AccelKey accel_key(accel,path); \
968 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
971 #define ACCEL2(accel) \
973 Gtk::AccelKey accel_key(accel); \
974 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
977 ACCEL("<Actions>//select-all-ducks","<Control>a");
978 ACCEL("<Actions>//unselect-all-layers","<Control>d");
979 ACCEL("<Actions>//render","F9");
980 ACCEL("<Actions>//preview","F11");
981 ACCEL("<Actions>//properties","F8");
982 ACCEL("<Actions>//options","F12");
983 ACCEL("<Actions>//import","<control>i");
984 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
985 ACCEL("<Actions>//toggle-grid-show","<Control>g");
986 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
987 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
988 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
989 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
990 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
991 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
992 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
993 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
995 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
996 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
998 ACCEL("<Actions>//quality-01","<Control>1");
999 ACCEL("<Actions>//quality-02","<Control>2");
1000 ACCEL("<Actions>//quality-03","<Control>3");
1001 ACCEL("<Actions>//quality-04","<Control>4");
1002 ACCEL("<Actions>//quality-05","<Control>5");
1003 ACCEL("<Actions>//quality-06","<Control>6");
1004 ACCEL("<Actions>//quality-07","<Control>7");
1005 ACCEL("<Actions>//quality-08","<Control>8");
1006 ACCEL("<Actions>//quality-09","<Control>9");
1007 ACCEL("<Actions>//quality-10","<Control>0");
1008 ACCEL("<Actions>//undo","<Control>z");
1009 ACCEL("<Actions>//redo","<Control>r");
1010 ACCEL("<Actions>//action-layer_remove","Delete");
1012 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1013 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1014 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1015 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1016 ACCEL("<Actions>//time-zoom-in","+");
1017 ACCEL("<Actions>//time-zoom-out","_");
1019 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1020 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1022 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1023 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1024 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1025 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1026 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1027 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1028 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1029 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1030 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1031 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1032 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1033 ACCEL("<Actions>//seek-begin","Home");
1034 ACCEL("<Actions>//seek-end","End");
1035 ACCEL("<Actions>//state-normal","<Mod1>a");
1036 ACCEL("<Actions>//state-rotate","<Mod1>s");
1037 ACCEL("<Actions>//state-scale","<Mod1>d");
1038 ACCEL("<Actions>//state-bline","<Mod1>b");
1039 ACCEL("<Actions>//state-fill","<Mod1>f");
1040 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1041 ACCEL("<Actions>//state-gradient","<Mod1>g");
1042 ACCEL("<Actions>//state-zoom","<Mod1>z");
1043 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1049 #define mkdir(x,y) mkdir(x)
1052 /* === M E T H O D S ======================================================= */
1054 App::App(int *argc, char ***argv):
1055 Gtk::Main(argc,argv),
1056 IconControler(etl::dirname((*argv)[0]))
1058 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1061 serial_=check_license(app_base_path_);
1064 ui_interface_=new GlobalUIInterface();
1068 Glib::thread_init();
1070 distance_system=Distance::SYSTEM_UNITS;
1072 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1075 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1079 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1087 if(!SYNFIG_CHECK_VERSION())
1089 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1090 dialog_error_blocking("Synfig Studio",
1091 "This copy of Synfig Studio was compiled against a\n"
1092 "different version of libsynfig than what is currently\n"
1093 "installed. Synfig Studio will now abort. Try downloading\n"
1094 "the latest version from the Synfig website at\n"
1095 "http://www.synfig.com/ "
1100 catch(synfig::SoftwareExpired)
1102 cerr<<"FATAL: Software Expired"<<endl;
1103 dialog_error_blocking("Synfig Studio",
1104 "This copy of Synfig Studio has expired.\n"
1105 "Please erase this copy, or download and\n"
1106 "install the latest copy from the Synfig\n"
1107 "website at http://www.synfig.com/ ."
1111 Glib::set_application_name(_("Synfig Studio"));
1114 about_window.set_can_self_destruct(false);
1115 about_window.show();
1117 shutdown_in_progress=false;
1118 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1119 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1121 // Initialize the Synfig library
1122 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1125 get_ui_interface()->error("Failed to initialize synfig!");
1129 // add the preferences to the settings
1130 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1134 studio_init_cb.task("Init UI Manager...");
1135 App::ui_manager_=studio::UIManager::create();
1138 studio_init_cb.task("Init Dock Manager...");
1139 dock_manager=new studio::DockManager();
1141 studio_init_cb.task("Init State Manager...");
1142 state_manager=new StateManager();
1144 studio_init_cb.task("Init Toolbox...");
1145 toolbox=new studio::Toolbox();
1147 studio_init_cb.task("Init Tool Options...");
1148 dialog_tool_options=new studio::Dialog_ToolOptions();
1149 dock_manager->register_dockable(*dialog_tool_options);
1151 studio_init_cb.task("Init History...");
1152 dock_history=new studio::Dock_History();
1153 dock_manager->register_dockable(*dock_history);
1155 studio_init_cb.task("Init Canvases...");
1156 dock_canvases=new studio::Dock_Canvases();
1157 dock_manager->register_dockable(*dock_canvases);
1159 studio_init_cb.task("Init Keyframes...");
1160 dock_keyframes=new studio::Dock_Keyframes();
1161 dock_manager->register_dockable(*dock_keyframes);
1163 studio_init_cb.task("Init Layers...");
1164 dock_layers=new studio::Dock_Layers();
1165 dock_manager->register_dockable(*dock_layers);
1167 studio_init_cb.task("Init Params...");
1168 dock_params=new studio::Dock_Params();
1169 dock_manager->register_dockable(*dock_params);
1171 studio_init_cb.task("Init MetaData...");
1172 dock_meta_data=new studio::Dock_MetaData();
1173 dock_manager->register_dockable(*dock_meta_data);
1175 studio_init_cb.task("Init Children...");
1176 dock_children=new studio::Dock_Children();
1177 dock_manager->register_dockable(*dock_children);
1179 studio_init_cb.task("Init Info...");
1180 dock_info = new studio::Dock_Info();
1181 dock_manager->register_dockable(*dock_info);
1183 studio_init_cb.task("Init Navigator...");
1184 dock_navigator = new studio::Dock_Navigator();
1185 dock_manager->register_dockable(*dock_navigator);
1187 studio_init_cb.task("Init Timetrack...");
1188 dock_timetrack = new studio::Dock_Timetrack();
1189 dock_manager->register_dockable(*dock_timetrack);
1191 studio_init_cb.task("Init Curve Editor...");
1192 dock_curves = new studio::Dock_Curves();
1193 dock_manager->register_dockable(*dock_curves);
1195 studio_init_cb.task("Init Layer Groups...");
1196 dock_layer_groups = new studio::Dock_LayerGroups();
1197 dock_manager->register_dockable(*dock_layer_groups);
1200 studio_init_cb.task("Init Color Dialog...");
1201 dialog_color=new studio::Dialog_Color();
1203 studio_init_cb.task("Init Gradient Dialog...");
1204 dialog_gradient=new studio::Dialog_Gradient();
1206 studio_init_cb.task("Init DeviceTracker...");
1207 device_tracker=new studio::DeviceTracker();
1209 studio_init_cb.task("Init Tools...");
1210 state_manager->add_state(&state_normal);
1211 state_manager->add_state(&state_smooth_move);
1212 state_manager->add_state(&state_scale);
1213 state_manager->add_state(&state_rotate);
1215 state_manager->add_state(&state_bline);
1218 state_manager->add_state(&state_circle);
1219 state_manager->add_state(&state_rectangle);
1221 state_manager->add_state(&state_gradient);
1222 state_manager->add_state(&state_eyedrop);
1223 state_manager->add_state(&state_fill);
1225 state_manager->add_state(&state_zoom);
1227 // Disabled this tool because it should be
1228 // considered deprecated. Use the bline tool instead.
1229 if(getenv("SYNFIG_ENABLE_POLYGON")) state_manager->add_state(&state_polygon);
1231 // These tools are disabled by default for now,
1232 // because they tend to confuse users.
1233 if(getenv("SYNFIG_ENABLE_DRAW" )) state_manager->add_state(&state_draw);
1234 if(getenv("SYNFIG_ENABLE_SKETCH")) state_manager->add_state(&state_sketch);
1235 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1237 studio_init_cb.task("Init ModPalette...");
1238 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1240 studio_init_cb.task("Init ModMirror...");
1241 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1244 studio_init_cb.task("Init Setup Dialog...");
1245 dialog_setup=new studio::Dialog_Setup();
1247 studio_init_cb.task("Init Input Dialog...");
1248 dialog_input=new Gtk::InputDialog();
1249 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1251 studio_init_cb.task("Init auto recovery...");
1252 auto_recover=new AutoRecover();
1254 studio_init_cb.amount_complete(9250,10000);
1255 studio_init_cb.task("Loading Settings...");
1257 studio_init_cb.task("Checking auto-recover...");
1259 studio_init_cb.amount_complete(9900,10000);
1261 if(auto_recover->recovery_needed())
1263 about_window.hide();
1265 get_ui_interface()->yes_no(
1267 "Synfig Studio seems to have crashed\n"
1268 "before you could save all your files.\n"
1269 "Would you like to re-open those files\n"
1270 "and recover your unsaved changes?"
1271 )==synfigapp::UIInterface::RESPONSE_YES
1274 if(!auto_recover->recover())
1276 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1279 get_ui_interface()->error(
1280 _("Synfig Studio has attempted to recover\n"
1281 "from a previous crash. The files that it has\n"
1282 "recovered are NOT YET SAVED. It would be a good\n"
1283 "idea to review them and save them now.")
1286 about_window.show();
1289 // Look for any files given on the command line,
1290 // and load them if found.
1291 for(;*argc>=1;(*argc)--)
1292 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1294 studio_init_cb.task("Loading files...");
1295 about_window.hide();
1296 open((*argv)[*argc]);
1297 about_window.show();
1300 studio_init_cb.task("Done.");
1301 studio_init_cb.amount_complete(10000,10000);
1307 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1311 StateManager* App::get_state_manager() { return state_manager; }
1315 shutdown_in_progress=true;
1319 synfigapp::Main::settings().remove_domain("pref");
1321 selected_instance=0;
1323 // Unload all of the modules
1324 for(;!module_list_.empty();module_list_.pop_back());
1326 delete state_manager;
1330 delete auto_recover;
1334 // studio::App::iteration(false);
1338 // studio::App::iteration(false);
1340 // studio::App::iteration(false);
1342 delete dialog_setup;
1344 delete dialog_gradient;
1346 delete dialog_color;
1348 delete dialog_input;
1350 delete dock_manager;
1352 instance_list.clear();
1354 // studio::App::iteration(false);
1358 App::get_user_app_directory()
1360 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1364 App::get_config_file(const synfig::String& file)
1366 return Glib::build_filename(get_user_app_directory(),file);
1370 App::add_recent_file(const std::string &file_name)
1372 std::string filename(file_name);
1374 assert(!filename.empty());
1376 if(filename.empty())
1379 // Toss out any "hidden" files
1380 if(basename(filename)[0]=='.')
1383 // If we aren't an absolute path, turn outselves into one
1384 if(!is_absolute_path(filename))
1385 filename=absolute_path(filename);
1387 list<string>::iterator iter;
1388 // Check to see if the file is already on the list.
1389 // If it is, then remove it from the list
1390 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1393 recent_files.erase(iter);
1398 // Push the filename to the front of the list
1399 recent_files.push_front(filename);
1401 // Clean out the files at the end of the list.
1402 while(recent_files.size()>(unsigned)get_max_recent_files())
1403 recent_files.pop_back();
1405 signal_recent_files_changed_();
1410 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1413 App::get_time_format()
1415 return _App_time_format;
1419 App::set_time_format(synfig::Time::Format x)
1426 App::save_settings()
1431 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1432 setlocale(LC_NUMERIC, "C");
1434 std::string filename=get_config_file("accelrc");
1435 Gtk::AccelMap::save(filename);
1438 std::string filename=get_config_file("recentfiles");
1440 std::ofstream file(filename.c_str());
1444 synfig::warning("Unable to save %s",filename.c_str());
1448 list<string>::reverse_iterator iter;
1450 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1454 std::string filename=get_config_file("settings");
1455 synfigapp::Main::settings().save_to_file(filename);
1456 setlocale(LC_NUMERIC,old_locale);
1460 synfig::warning("Caught exception when attempting to save settings.");
1465 App::load_settings()
1470 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1471 setlocale(LC_NUMERIC, "C");
1473 std::string filename=get_config_file("accelrc");
1474 Gtk::AccelMap::load(filename);
1477 std::string filename=get_config_file("recentfiles");
1479 std::ifstream file(filename.c_str());
1483 std::string recent_file;
1484 getline(file,recent_file);
1485 if(!recent_file.empty())
1486 add_recent_file(recent_file);
1489 std::string filename=get_config_file("settings");
1490 if(!synfigapp::Main::settings().load_from_file(filename))
1492 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1493 //if(!synfigapp::Main::settings().load_from_file(filename))
1495 gamma.set_gamma(1.0/2.2);
1496 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1497 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1498 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1499 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1500 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1501 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1502 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1503 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1504 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1505 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1506 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1507 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1508 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1511 setlocale(LC_NUMERIC,old_locale);
1515 synfig::warning("Caught exception when attempting to load settings.");
1520 App::shutdown_request(GdkEventAny*)
1524 //return !shutdown_in_progress;
1530 if(shutdown_in_progress)return;
1533 get_ui_interface()->task("Quit Request");
1536 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1540 std::list<etl::handle<Instance> >::iterator iter;
1541 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1543 if(!(*iter)->safe_close())
1547 if((*iter)->synfigapp::Instance::get_action_count())
1549 handle<synfigapp::UIInterface> uim;
1550 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1552 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1553 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1555 case synfigapp::UIInterface::RESPONSE_NO:
1557 case synfigapp::UIInterface::RESPONSE_YES:
1560 case synfigapp::UIInterface::RESPONSE_CANCEL:
1569 if((*iter)->synfigapp::Instance::is_modified())
1571 handle<synfigapp::UIInterface> uim;
1572 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1574 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() );
1575 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1577 case synfigapp::UIInterface::RESPONSE_NO:
1579 case synfigapp::UIInterface::RESPONSE_YES:
1580 (*iter)->dialog_cvs_commit();
1582 case synfigapp::UIInterface::RESPONSE_CANCEL:
1591 // This next line causes things to crash for some reason
1595 shutdown_in_progress=true;
1597 instance_list.clear();
1599 while(studio::App::events_pending())studio::App::iteration(false);
1602 auto_recover->normal_shutdown();
1604 get_ui_interface()->task("Quit Request sent");
1610 dialog_setup->refresh();
1611 dialog_setup->show();
1614 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1615 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1618 //#define USE_WIN32_FILE_DIALOGS 1
1621 #ifdef USE_WIN32_FILE_DIALOGS
1622 static OPENFILENAME ofn={};
1626 #include <gdk/gdkwin32.h>
1630 App::dialog_open_file(const std::string &title, std::string &filename)
1632 #ifdef USE_WIN32_FILE_DIALOGS
1633 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1635 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1636 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1637 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1639 ofn.lStructSize=sizeof(OPENFILENAME);
1640 ofn.hwndOwner = hWnd;
1641 ofn.hInstance = hInstance;
1642 ofn.lpstrFilter = szFilter;
1643 // ofn.lpstrCustomFilter=NULL;
1644 // ofn.nMaxCustFilter=0;
1645 // ofn.nFilterIndex=0;
1646 // ofn.lpstrFile=NULL;
1647 ofn.nMaxFile=MAX_PATH;
1648 // ofn.lpstrFileTitle=NULL;
1649 // ofn.lpstrInitialDir=NULL;
1650 // ofn.lpstrTitle=NULL;
1651 ofn.Flags=OFN_HIDEREADONLY;
1652 // ofn.nFileOffset=0;
1653 // ofn.nFileExtension=0;
1654 ofn.lpstrDefExt=TEXT("sif");
1655 // ofn.lCustData = 0l;
1657 // ofn.lpTemplateName=NULL;
1659 CHAR szFilename[MAX_PATH];
1661 strcpy(szFilename,filename.c_str());
1662 strcpy(szTitle,title.c_str());
1664 ofn.lpstrFile=szFilename;
1665 ofn.lpstrFileTitle=szTitle;
1667 if(GetOpenFileName(&ofn))
1669 filename=szFilename;
1675 synfig::String prev_path;
1676 if(!_preferences.get_value("curr_path",prev_path))
1679 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1680 dialog->set_current_folder(prev_path);
1681 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1682 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1683 if(!filename.empty())
1684 dialog->set_filename(filename);
1685 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1686 filename=dialog->get_filename();
1698 GtkWidget *fileselection;
1699 fileselection = gtk_file_selection_new(title.c_str());
1702 if(basename(filename)==filename)
1704 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1707 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1709 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1711 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1712 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1714 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1715 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1717 gtk_widget_show(fileselection);
1725 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1726 _preferences.set_value("curr_path",dirname(filename));
1730 gtk_widget_destroy(fileselection);
1733 gtk_widget_destroy(fileselection);
1740 App::dialog_save_file(const std::string &title, std::string &filename)
1742 #ifdef USE_WIN32_FILE_DIALOGS
1743 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1745 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1746 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1747 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1749 ofn.lStructSize=sizeof(OPENFILENAME);
1750 ofn.hwndOwner = hWnd;
1751 ofn.hInstance = hInstance;
1752 ofn.lpstrFilter = szFilter;
1753 // ofn.lpstrCustomFilter=NULL;
1754 // ofn.nMaxCustFilter=0;
1755 // ofn.nFilterIndex=0;
1756 // ofn.lpstrFile=NULL;
1757 ofn.nMaxFile=MAX_PATH;
1758 // ofn.lpstrFileTitle=NULL;
1759 // ofn.lpstrInitialDir=NULL;
1760 // ofn.lpstrTitle=NULL;
1761 ofn.Flags=OFN_OVERWRITEPROMPT;
1762 // ofn.nFileOffset=0;
1763 // ofn.nFileExtension=0;
1764 ofn.lpstrDefExt=TEXT("sif");
1765 // ofn.lCustData = 0l;
1767 // ofn.lpTemplateName=NULL;
1769 CHAR szFilename[MAX_PATH];
1771 strcpy(szFilename,filename.c_str());
1772 strcpy(szTitle,title.c_str());
1774 ofn.lpstrFile=szFilename;
1775 ofn.lpstrFileTitle=szTitle;
1777 if(GetSaveFileName(&ofn))
1779 filename=szFilename;
1784 synfig::String prev_path;
1785 if(!_preferences.get_value("curr_path",prev_path))
1788 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1789 dialog->set_current_folder(prev_path);
1790 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1791 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1792 if(!filename.empty())
1793 dialog->set_filename(filename);
1794 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1795 filename=dialog->get_filename();
1801 // return dialog_open_file(title, filename);
1806 App::dialog_saveas_file(const std::string &title, std::string &filename)
1808 #if USE_WIN32_FILE_DIALOGS
1809 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1811 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1812 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1813 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1815 ofn.lStructSize=sizeof(OPENFILENAME);
1816 ofn.hwndOwner = hWnd;
1817 ofn.hInstance = hInstance;
1818 ofn.lpstrFilter = szFilter;
1819 // ofn.lpstrCustomFilter=NULL;
1820 // ofn.nMaxCustFilter=0;
1821 // ofn.nFilterIndex=0;
1822 // ofn.lpstrFile=NULL;
1823 ofn.nMaxFile=MAX_PATH;
1824 // ofn.lpstrFileTitle=NULL;
1825 // ofn.lpstrInitialDir=NULL;
1826 // ofn.lpstrTitle=NULL;
1827 ofn.Flags=OFN_OVERWRITEPROMPT;
1828 // ofn.nFileOffset=0;
1829 // ofn.nFileExtension=0;
1830 ofn.lpstrDefExt=TEXT("sif");
1831 // ofn.lCustData = 0l;
1833 // ofn.lpTemplateName=NULL;
1835 CHAR szFilename[MAX_PATH];
1837 strcpy(szFilename,filename.c_str());
1838 strcpy(szTitle,title.c_str());
1840 ofn.lpstrFile=szFilename;
1841 ofn.lpstrFileTitle=szTitle;
1843 if(GetSaveFileName(&ofn))
1845 filename=szFilename;
1850 synfig::String prev_path;
1851 if(!_preferences.get_value("curr_path",prev_path))
1854 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1855 dialog->set_current_folder(prev_path);
1856 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1857 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1858 if(!filename.empty())
1859 dialog->set_filename(filename);
1860 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1861 filename=dialog->get_filename();
1867 // return dialog_open_file(title, filename);
1872 App::dialog_error_blocking(const std::string &title, const std::string &message)
1874 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1875 dialog.set_title(title);
1881 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1883 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
1884 dialog.set_title(title);
1890 App::dialog_yes_no(const std::string &title, const std::string &message)
1895 true // use_separator
1897 Gtk::Label label(message);
1900 dialog.get_vbox()->pack_start(label);
1901 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1902 dialog.add_button(Gtk::StockID("gtk-no"),0);
1904 return dialog.run();
1908 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1913 true // use_separator
1915 Gtk::Label label(message);
1918 dialog.get_vbox()->pack_start(label);
1919 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1920 dialog.add_button(Gtk::StockID("gtk-no"),0);
1921 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1923 return dialog.run();
1927 App::dialog_not_implemented()
1929 Gtk::MessageDialog dialog("Feature not available", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1930 dialog.set_secondary_text("Sorry, this feature has not yet been implemented.");
1935 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1940 true // use_separator
1942 Gtk::Label label(message);
1944 dialog.get_vbox()->pack_start(label);
1947 entry.set_text(text);
1949 entry.set_activates_default(true);
1950 dialog.get_vbox()->pack_start(entry);
1952 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1953 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1954 dialog.set_default_response(Gtk::RESPONSE_OK);
1955 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1958 if(dialog.run()!=Gtk::RESPONSE_OK)
1961 text=entry.get_text();
1970 App::open(std::string filename)
1972 return open_as(filename,filename);
1976 App::open_as(std::string filename,std::string as)
1979 char long_name[1024];
1980 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1986 OneMoment one_moment;
1988 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1989 if(canvas && get_instance(canvas))
1991 get_instance(canvas)->find_canvas_view(canvas)->present();
1992 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1995 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1997 add_recent_file(as);
1999 handle<Instance> instance(Instance::create(canvas));
2002 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2006 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)")))
2007 instance->dialog_cvs_update();
2011 dialog_error_blocking(_("Error"), x);
2016 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2020 _preferences.set_value("curr_path",dirname(as));
2029 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2030 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2032 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2034 canvas->rend_desc().set_frame_rate(24.0);
2035 canvas->rend_desc().set_time_start(0.0);
2036 canvas->rend_desc().set_time_end(00.0);
2037 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2038 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2039 canvas->rend_desc().set_tl(Vector(-4,2.25));
2040 canvas->rend_desc().set_br(Vector(4,-2.25));
2041 canvas->rend_desc().set_w(480);
2042 canvas->rend_desc().set_h(270);
2043 canvas->rend_desc().set_antialias(1);
2044 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2045 canvas->set_file_name(file_name);
2047 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2053 string filename="*.sif";
2055 while(dialog_open_file("Open", filename))
2057 // If the filename still has wildcards, then we should
2058 // continue looking for the file we want
2059 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2065 get_ui_interface()->error(_("Unable to open file"));
2070 App::set_selected_instance(etl::loose_handle<Instance> instance)
2072 /* if(get_selected_instance()==instance)
2074 selected_instance=instance;
2075 signal_instance_selected()(instance);
2081 selected_instance=instance;
2082 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2086 instance->focus(instance->get_canvas());
2089 set_selected_canvas_view(0);
2091 signal_instance_selected()(instance);
2095 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2097 selected_canvas_view=canvas_view;
2098 signal_canvas_view_focus()(selected_canvas_view);
2101 selected_instance=canvas_view->get_instance();
2102 signal_instance_selected()(canvas_view->get_instance());
2105 if(get_selected_canvas_view()==canvas_view)
2107 signal_canvas_view_focus()(selected_canvas_view);
2108 signal_instance_selected()(canvas_view->get_instance());
2111 selected_canvas_view=canvas_view;
2112 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2113 set_selected_instance(canvas_view->get_instance());
2114 signal_canvas_view_focus()(selected_canvas_view);
2118 etl::loose_handle<Instance>
2119 App::get_instance(Canvas::Handle canvas)
2121 if(!canvas) return 0;
2122 canvas=canvas->get_root();
2124 std::list<etl::handle<Instance> >::iterator iter;
2125 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2127 if((*iter)->get_canvas()==canvas)
2136 (new class About())->show();
2142 if(selected_instance)
2143 selected_instance->undo();
2149 if(selected_instance)
2150 selected_instance->redo();
2154 studio::App::get_base_path()
2156 return app_base_path_;