1 /* === S Y N F I G ========================================================= */
5 ** $Id: app.cpp,v 1.11 2005/03/24 21:47:28 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
34 #include <gtkmm/fileselection.h>
35 #include <gtkmm/dialog.h>
36 #include <gtkmm/label.h>
37 #include <gtkmm/stock.h>
38 #include <gtkmm/stockitem.h>
39 #include <gtkmm/iconsource.h>
40 #include <gtkmm/inputdialog.h>
41 #include <gtkmm/accelmap.h>
42 #include <gtkmm/uimanager.h>
46 #include <synfig/loadcanvas.h>
51 #include "canvasview.h"
52 #include "dialog_setup.h"
53 #include "dialog_gradient.h"
54 #include "dialog_color.h"
57 #include "onemoment.h"
59 #include "dockmanager.h"
61 #include "state_eyedrop.h"
62 #include "state_normal.h"
63 #include "state_draw.h"
64 #include "state_fill.h"
65 #include "state_bline.h"
66 #include "state_polygon.h"
67 #include "state_sketch.h"
68 #include "state_gradient.h"
69 #include "state_circle.h"
70 #include "state_rectangle.h"
71 #include "state_smoothmove.h"
72 #include "state_scale.h"
73 #include "state_width.h"
74 #include "state_rotate.h"
75 #include "state_zoom.h"
77 #include "devicetracker.h"
78 #include "dialog_tooloptions.h"
80 #include "autorecover.h"
82 #include <synfigapp/settings.h>
83 #include "dock_history.h"
84 #include "dock_canvases.h"
85 #include "dock_keyframes.h"
86 #include "dock_layers.h"
87 #include "dock_params.h"
88 #include "dock_metadata.h"
89 #include "dock_children.h"
90 #include "dock_info.h"
91 #include "dock_navigator.h"
92 #include "dock_layergroups.h"
93 #include "dock_timetrack.h"
94 #include "dock_curves.h"
96 #include "mod_palette/mod_palette.h"
97 #include "mod_mirror/mod_mirror.h"
105 #include "statemanager.h"
114 #include <gtkmm/accelmap.h>
118 /* === U S I N G =========================================================== */
122 using namespace synfig;
123 using namespace studio;
125 /* === M A C R O S ========================================================= */
128 #define DPM2DPI(x) (float(x)/39.3700787402f)
129 #define DPI2DPM(x) (float(x)*39.3700787402f)
135 # define IMAGE_DIR "share\\pixmaps"
140 # define IMAGE_DIR "/usr/local/share/pixmaps"
144 # define IMAGE_EXT "tif"
147 #include <synfigapp/main.h>
149 /* === S I G N A L S ======================================================= */
151 static sigc::signal<void> signal_present_all_;
153 App::signal_present_all() { return signal_present_all_; }
155 static sigc::signal<void> signal_recent_files_changed_;
157 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
159 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
160 sigc::signal<void,etl::loose_handle<CanvasView> >&
161 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
163 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
164 sigc::signal<void,etl::handle<Instance> >&
165 App::signal_instance_selected() { return signal_instance_selected_; }
167 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
168 sigc::signal<void,etl::handle<Instance> >&
169 App::signal_instance_created() { return signal_instance_created_; }
171 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
172 sigc::signal<void,etl::handle<Instance> >&
173 App::signal_instance_deleted() { return signal_instance_deleted_; }
175 /* === G L O B A L S ======================================================= */
177 static std::list<std::string> recent_files;
178 const std::list<std::string>& App::get_recent_files() { return recent_files; }
180 int App::Busy::count;
181 bool App::shutdown_in_progress;
183 synfig::Gamma App::gamma;
185 Glib::RefPtr<studio::UIManager> App::ui_manager_;
187 synfig::Distance::System App::distance_system;
189 studio::Dialog_Setup* App::dialog_setup;
191 etl::handle< studio::ModPalette > mod_palette_;
192 //studio::Dialog_Palette* App::dialog_palette;
194 std::list<etl::handle<Instance> > App::instance_list;
196 static etl::handle<synfigapp::UIInterface> ui_interface_;
197 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
199 etl::handle<Instance> App::selected_instance;
200 etl::handle<CanvasView> App::selected_canvas_view;
202 studio::Toolbox *studio::App::toolbox=NULL;
204 studio::AutoRecover *studio::App::auto_recover=NULL;
206 studio::IPC *ipc=NULL;
208 studio::DockManager* studio::App::dock_manager=0;
210 studio::DeviceTracker* studio::App::device_tracker=0;
212 studio::Dialog_Gradient* studio::App::dialog_gradient;
214 studio::Dialog_Color* studio::App::dialog_color;
216 Gtk::InputDialog* studio::App::dialog_input;
218 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
220 studio::Dock_History* dock_history;
221 studio::Dock_Canvases* dock_canvases;
222 studio::Dock_Keyframes* dock_keyframes;
223 studio::Dock_Layers* dock_layers;
224 studio::Dock_Params* dock_params;
225 studio::Dock_MetaData* dock_meta_data;
226 studio::Dock_Children* dock_children;
227 studio::Dock_Info* dock_info;
228 studio::Dock_LayerGroups* dock_layer_groups;
229 studio::Dock_Navigator* dock_navigator;
230 studio::Dock_Timetrack* dock_timetrack;
231 studio::Dock_Curves* dock_curves;
233 std::list< etl::handle< studio::Module > > module_list_;
235 bool studio::App::use_colorspace_gamma=true;
237 static int max_recent_files_=25;
238 int studio::App::get_max_recent_files() { return max_recent_files_; }
239 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
241 static synfig::String app_base_path_;
244 }; // END of namespace studio
245 studio::StateManager* state_manager;
250 class GlobalUIInterface : public synfigapp::UIInterface
254 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
259 true // use_separator
261 Gtk::Label label(message);
264 dialog.get_vbox()->pack_start(label);
265 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
266 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
268 dialog.set_default_response(dflt);
270 return (Response)dialog.run();
272 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
277 true // use_separator
279 Gtk::Label label(message);
282 dialog.get_vbox()->pack_start(label);
283 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
284 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
285 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
287 dialog.set_default_response(dflt);
289 return (Response)dialog.run();
291 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
296 true // use_separator
298 Gtk::Label label(message);
301 dialog.get_vbox()->pack_start(label);
302 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
303 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
305 dialog.set_default_response(dflt);
307 return (Response)dialog.run();
311 task(const std::string &task)
313 std::cerr<<task<<std::endl;
314 while(studio::App::events_pending())studio::App::iteration(false);
319 error(const std::string &err)
324 true // use_separator
326 Gtk::Label label(err);
329 dialog.get_vbox()->pack_start(label);
330 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
337 warning(const std::string &err)
339 std::cerr<<"warning: "<<err<<std::endl;
340 while(studio::App::events_pending())studio::App::iteration(false);
345 amount_complete(int current, int total)
347 while(studio::App::events_pending())studio::App::iteration(false);
352 /* === P R O C E D U R E S ================================================= */
354 typedef unsigned char U8;
355 typedef unsigned short U16;
356 typedef unsigned long U32;
366 static inline U32 hash_U32(U32 i)
368 i=i*1664525+1013904223;
369 i=i*1664525+1013904223;
370 i=i*1664525+1013904223;
375 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
376 #define endian_fix(x) (endian_fix_table[x])
378 #define endian_fix(x) (x)
381 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
384 unwound->element.serial=0;
385 unwound->element.checksum=0;
393 case '0': data=0; break;
394 case '1': data=1; break;
395 case '2': data=2; break;
396 case '3': data=3; break;
397 case '4': data=4; break;
398 case '5': data=5; break;
399 case '6': data=6; break;
400 case '7': data=7; break;
401 case '8': data=8; break;
402 case '9': data=9; break;
403 case 'a': case 'A': data=10; break;
404 case 'b': case 'B': data=11; break;
405 case 'c': case 'C': data=12; break;
406 case 'd': case 'D': data=13; break;
407 case 'e': case 'E': data=14; break;
408 case 'f': case 'F': data=15; break;
409 default: return 0; break;
412 unwound->element.checksum|=(((U32)data&3)<<bit);
413 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
418 int v_key_check(const char* key, U32* serial, U32 appid)
420 V_KeyUnwound unwound_key;
421 U32 appid_mask_a=hash_U32(appid);
422 U32 appid_mask_b=hash_U32(appid_mask_a);
424 if(!v_unwind_key(&unwound_key, key))
426 // Invalid characters in key
431 // Undo obfuscation pass
433 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
438 unwound_key.raw[endian_fix(i)]^=(next>>24);
442 unwound_key.element.serial^=appid_mask_a;
443 unwound_key.element.checksum^=appid_mask_b;
445 *serial=unwound_key.element.serial;
447 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
451 int check_license(String basedir)
457 license_file="/usr/local/etc/.synfiglicense";
459 license_file=basedir+"\\etc\\.synfiglicense";
463 key=Glib::file_get_contents(license_file);
464 } catch (Glib::FileError) { }
466 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
468 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
472 if(!App::dialog_entry(
473 _("Synfig Studio Authentication"),
474 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
477 throw String("No License");
480 FILE* file=fopen(license_file.c_str(),"w");
483 fprintf(file,"%s",key.c_str());
487 synfig::error("Unable to save license key!");
489 synfig::info("License Authenticated -- Serial #%05d",serial);
495 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
497 action_group_list.push_back(action_group);
498 Gtk::UIManager::insert_action_group(action_group, pos);
502 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
504 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
505 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
506 if(*iter==action_group)
508 action_group_list.erase(iter);
509 Gtk::UIManager::remove_action_group(action_group);
512 synfig::error("Unable to find action group");
516 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
518 ui_manager->insert_action_group(group,0);
521 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
522 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
525 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
528 if(*iter && (*iter)->get_name()!="menus")
530 synfig::info("Removing action group "+(*iter)->get_name());
531 ui_manager->remove_action_group(*iter);
535 ui_manager->insert_action_group(group,0);
538 for(;!prev_groups.empty();prev_groups.pop_front())
540 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
541 ui_manager->insert_action_group(prev_groups.front(),1);
546 class Preferences : public synfigapp::Settings
549 virtual bool get_value(const synfig::String& key, synfig::String& value)const
553 value=strprintf("%f %f %f %f",
554 App::gamma.get_gamma_r(),
555 App::gamma.get_gamma_g(),
556 App::gamma.get_gamma_b(),
557 App::gamma.get_black_level()
561 if(key=="time_format")
563 value=strprintf("%i",App::get_time_format());
566 if(key=="file_history.size")
568 value=strprintf("%i",App::get_max_recent_files());
571 if(key=="use_colorspace_gamma")
573 value=strprintf("%i",(int)App::use_colorspace_gamma);
576 if(key=="distance_system")
578 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
581 if(key=="auto_recover_backup_interval")
583 value=strprintf("%i",App::auto_recover->get_timeout());
587 return synfigapp::Settings::get_value(key,value);
590 virtual bool set_value(const synfig::String& key,const synfig::String& value)
596 strscanf(value,"%f %f %f %f",
603 App::gamma.set_all(r,g,b,blk);
607 if(key=="time_format")
609 int i(atoi(value.c_str()));
610 App::set_time_format(static_cast<synfig::Time::Format>(i));
613 if(key=="auto_recover_backup_interval")
615 int i(atoi(value.c_str()));
616 App::auto_recover->set_timeout(i);
619 if(key=="file_history.size")
621 int i(atoi(value.c_str()));
622 App::set_max_recent_files(i);
625 if(key=="use_colorspace_gamma")
627 int i(atoi(value.c_str()));
628 App::use_colorspace_gamma=i;
631 if(key=="distance_system")
633 App::distance_system=Distance::ident_system(value);;
637 return synfigapp::Settings::set_value(key,value);
640 virtual KeyList get_key_list()const
642 KeyList ret(synfigapp::Settings::get_key_list());
643 ret.push_back("gamma");
644 ret.push_back("time_format");
645 ret.push_back("distance_system");
646 ret.push_back("file_history.size");
647 ret.push_back("use_colorspace_gamma");
648 ret.push_back("auto_recover_backup_interval");
653 static Preferences _preferences;
658 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
660 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
662 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
664 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
665 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
666 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
667 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
668 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
669 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
670 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
671 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
672 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
673 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
674 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
675 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
677 // Add the synfigapp actions...
678 synfigapp::Action::Book::iterator iter;
679 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
681 actions_action_group->add(Gtk::Action::create(
682 "action-"+iter->second.name,
683 get_action_stock_id(iter->second),
684 iter->second.local_name,iter->second.local_name
688 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
689 #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); }
690 #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); }
692 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
693 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
694 DEFINE_ACTION("open", Gtk::Stock::OPEN);
695 DEFINE_ACTION("save", Gtk::Stock::SAVE);
696 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
697 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
698 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
699 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
700 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
701 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
702 DEFINE_ACTION("import", _("Import"));
703 DEFINE_ACTION("render", _("Render"));
704 DEFINE_ACTION("preview", _("Preview"));
705 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
706 DEFINE_ACTION("sound", _("Sound File"));
707 DEFINE_ACTION("options", _("Options"));
708 DEFINE_ACTION("close", _("Close"));
711 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
712 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
713 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
714 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
715 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
716 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
717 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
718 DEFINE_ACTION("properties", _("Properties"));
720 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
721 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
722 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
723 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
724 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
725 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
726 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
727 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
728 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
729 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
730 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
731 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
732 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
733 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
734 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
735 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
736 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
737 DEFINE_ACTION("play", _("Play"));
738 DEFINE_ACTION("pause", _("Pause"));
739 DEFINE_ACTION("stop", _("Stop"));
740 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
741 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
742 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
743 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
744 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
745 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
746 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
747 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
748 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
749 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
750 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
751 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
752 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
753 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
754 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
755 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
756 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
757 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
758 DEFINE_ACTION("seek-end", _("Seek to End"));
760 DEFINE_ACTION("action-group_add", _("Add group"));
762 DEFINE_ACTION("canvas-new", _("New Canvas"));
764 DEFINE_ACTION("amount-inc", _("Increase Amount"));
765 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
770 // Set up synfigapp actions
772 synfigapp::Action::Book::iterator iter;
774 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
776 Gtk::StockID stock_id;
778 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
780 //Gtk::Image* image(manage(new Gtk::Image()));
781 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
782 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
783 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
784 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
785 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
786 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
787 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
788 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
789 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
790 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
792 actions_action_group->add(Gtk::Action::create(
793 "action-"+iter->second.name,
795 iter->second.local_name,iter->second.local_name
803 Glib::ustring ui_info =
805 " <popup name='menu-toolbox' action='menu-toolbox'>"
806 " <menu action='menu-file'>"
809 " <popup name='menu-main' action='menu-main'>"
810 " <menu action='menu-file'>"
811 " <menuitem action='save' />"
812 " <menuitem action='save-as' />"
813 " <menuitem action='revert' />"
814 " <separator name='bleh01'/>"
815 " <menuitem action='cvs-add' />"
816 " <menuitem action='cvs-update' />"
817 " <menuitem action='cvs-commit' />"
818 " <menuitem action='cvs-revert' />"
819 " <separator name='bleh02'/>"
820 " <menuitem action='import' />"
821 " <separator name='bleh03'/>"
822 " <menuitem action='render' />"
823 " <menuitem action='preview' />"
824 " <menuitem action='sound' />"
825 " <separator name='bleh04'/>"
826 " <menuitem action='options' />"
827 " <menuitem action='close' />"
829 " <menu action='menu-edit'>"
830 " <menuitem action='undo'/>"
831 " <menuitem action='redo'/>"
832 " <separator name='bleh05'/>"
833 " <menuitem action='cut'/>"
834 " <menuitem action='copy'/>"
835 " <menuitem action='paste'/>"
836 " <separator name='bleh06'/>"
837 " <menuitem action='select-all-ducks'/>"
838 " <menuitem action='unselect-all-layers'/>"
839 " <separator name='bleh07'/>"
840 " <menuitem action='properties'/>"
842 " <menu action='menu-view'>"
843 " <menu action='menu-duck-mask'>"
844 " <menuitem action='mask-position-ducks' />"
845 " <menuitem action='mask-vertex-ducks' />"
846 " <menuitem action='mask-tangent-ducks' />"
847 " <menuitem action='mask-radius-ducks' />"
848 " <menuitem action='mask-width-ducks' />"
849 " <menuitem action='mask-angle-ducks' />"
851 " <menu action='menu-preview-quality'>"
852 " <menuitem action='quality-00' />"
853 " <menuitem action='quality-01' />"
854 " <menuitem action='quality-02' />"
855 " <menuitem action='quality-03' />"
856 " <menuitem action='quality-04' />"
857 " <menuitem action='quality-05' />"
858 " <menuitem action='quality-06' />"
859 " <menuitem action='quality-07' />"
860 " <menuitem action='quality-08' />"
861 " <menuitem action='quality-09' />"
862 " <menuitem action='quality-10' />"
864 " <separator name='bleh08'/>"
865 " <menuitem action='play'/>"
866 " <menuitem action='pause'/>"
867 " <menuitem action='stop'/>"
868 " <menuitem action='dialog-flipbook'/>"
869 " <separator name='bleh09'/>"
870 " <menuitem action='toggle-grid-show'/>"
871 " <menuitem action='toggle-grid-snap'/>"
872 " <menuitem action='toggle-guide-show'/>"
873 " <menuitem action='toggle-low-res'/>"
874 " <menuitem action='toggle-onion-skin'/>"
875 " <separator name='bleh10'/>"
876 " <menuitem action='canvas-zoom-in'/>"
877 " <menuitem action='canvas-zoom-out'/>"
878 " <menuitem action='canvas-zoom-fit'/>"
879 " <menuitem action='canvas-zoom-100'/>"
880 " <separator name='bleh11'/>"
881 " <menuitem action='time-zoom-in'/>"
882 " <menuitem action='time-zoom-out'/>"
883 " <separator name='bleh12'/>"
884 " <menuitem action='jump-next-keyframe'/>"
885 " <menuitem action='jump-prev-keyframe'/>"
886 " <menuitem action='seek-next-frame'/>"
887 " <menuitem action='seek-prev-frame'/>"
888 " <menuitem action='seek-next-second'/>"
889 " <menuitem action='seek-prev-second'/>"
890 " <menuitem action='seek-begin'/>"
891 " <menuitem action='seek-end'/>"
893 " <menu action='menu-canvas'>"
894 " <menuitem action='canvas-new'/>"
895 " <menuitem action='amount-inc'/>"
896 " <menuitem action='amount-dec'/>"
898 " <menu name='menu-state' action='menu-state'>"
900 " <menu action='menu-group'>"
901 " <menuitem action='action-group_add'/>"
903 " <menu action='menu-layer'>"
904 //" <menuitem action='cut'/>"
905 //" <menuitem action='copy'/>"
906 //" <menuitem action='paste'/>"
907 //" <separator name='bleh06'/>"
908 " <menu action='menu-layer-new'></menu>"
910 " <menu action='menu-keyframe'>"
911 " <menuitem action='keyframe-properties'/>"
918 " <menubar name='MenuBar'>"
919 " <menu action='MenuFile'>"
920 " <menuitem action='New'/>"
921 " <menuitem action='Open'/>"
923 " <menuitem action='Quit'/>"
925 " <menu action='MenuEdit'>"
926 " <menuitem action='Cut'/>"
927 " <menuitem action='Copy'/>"
928 " <menuitem action='Paste'/>"
931 " <toolbar name='ToolBar'>"
932 " <toolitem action='Open'/>"
933 " <toolitem action='Quit'/>"
939 actions_action_group->set_sensitive(false);
940 App::ui_manager()->set_add_tearoffs(true);
941 App::ui_manager()->insert_action_group(menus_action_group,1);
942 App::ui_manager()->insert_action_group(actions_action_group,1);
943 App::ui_manager()->add_ui_from_string(ui_info);
945 //App::ui_manager()->get_accel_group()->unlock();
947 catch(const Glib::Error& ex)
949 synfig::error("building menus and toolbars failed: " + ex.what());
952 // Add default keyboard accelerators
953 #define ACCEL(path,accel) { Gtk::AccelKey accel_key(accel,path); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
954 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
955 ACCEL("<Actions>//select-all-ducks","<Control>a");
956 ACCEL("<Actions>//unselect-all-layers","<Control>d");
957 ACCEL("<Actions>//render","F9");
958 ACCEL("<Actions>//preview","F11");
959 ACCEL("<Actions>//properties","F8");
960 ACCEL("<Actions>//options","F12");
961 ACCEL("<Actions>//import","<control>i");
962 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
963 ACCEL("<Actions>//toggle-grid-show","<Control>g");
964 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
965 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
966 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
967 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
968 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
969 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
970 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
971 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
974 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
975 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
977 ACCEL("<Actions>//quality-01","<Control>1");
978 ACCEL("<Actions>//quality-02","<Control>2");
979 ACCEL("<Actions>//quality-03","<Control>3");
980 ACCEL("<Actions>//quality-04","<Control>4");
981 ACCEL("<Actions>//quality-05","<Control>5");
982 ACCEL("<Actions>//quality-06","<Control>6");
983 ACCEL("<Actions>//quality-07","<Control>7");
984 ACCEL("<Actions>//quality-08","<Control>8");
985 ACCEL("<Actions>//quality-09","<Control>9");
986 ACCEL("<Actions>//quality-10","<Control>0");
987 ACCEL("<Actions>//undo","<Control>z");
988 ACCEL("<Actions>//redo","<Control>r");
989 ACCEL("<Actions>//action-layer_remove","Delete");
991 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
992 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
993 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
994 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
995 ACCEL("<Actions>//time-zoom-in","+");
996 ACCEL("<Actions>//time-zoom-out","_");
998 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
999 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1001 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1002 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1003 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1004 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1005 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1006 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1007 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1008 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1009 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1010 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1011 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1012 ACCEL("<Actions>//seek-begin","Home");
1013 ACCEL("<Actions>//seek-end","End");
1014 ACCEL("<Actions>//state-normal","<Mod1>a");
1015 ACCEL("<Actions>//state-rotate","<Mod1>s");
1016 ACCEL("<Actions>//state-scale","<Mod1>d");
1017 ACCEL("<Actions>//state-bline","<Mod1>b");
1018 ACCEL("<Actions>//state-fill","<Mod1>f");
1019 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1020 ACCEL("<Actions>//state-gradient","<Mod1>g");
1021 ACCEL("<Actions>//state-zoom","<Mod1>z");
1022 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1028 #define mkdir(x,y) mkdir(x)
1031 /* === M E T H O D S ======================================================= */
1033 App::App(int *argc, char ***argv):
1034 Gtk::Main(argc,argv),
1035 IconControler(etl::dirname((*argv)[0]))
1037 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1040 serial_=check_license(app_base_path_);
1043 ui_interface_=new GlobalUIInterface();
1047 Glib::thread_init();
1049 distance_system=Distance::SYSTEM_UNITS;
1051 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1054 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1058 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1066 if(!SYNFIG_CHECK_VERSION())
1068 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1069 dialog_error_blocking("SYNFIG Studio",
1070 "This copy of SYNFIG Studio was compiled against a\n"
1071 "different version of libsynfig than what is currently\n"
1072 "installed. Synfig Studio will now abort. Try downloading\n"
1073 "the latest version from the SYNFIG Development Website at\n"
1074 "http://dev.synfig.com/ "
1079 catch(synfig::SoftwareExpired)
1081 cerr<<"FATAL: Software Expired"<<endl;
1082 dialog_error_blocking("SYNFIG Studio",
1083 "This copy of SYNFIG Studio has expired.\n"
1084 "Please erase this copy, or download and\n"
1085 "install the latest copy from the SYNFIG\n"
1086 "Development Website at http://dev.synfig.com/ ."
1090 Glib::set_application_name(_("SYNFIG Studio"));
1093 about_window.set_can_self_destruct(false);
1094 about_window.show();
1096 shutdown_in_progress=false;
1097 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1098 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1100 // Initialize the Synfig library
1101 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1104 get_ui_interface()->error("Failed to initialize synfig!");
1108 // add the preferences to the settings
1109 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1113 studio_init_cb.task("Init UI Manager...");
1114 App::ui_manager_=studio::UIManager::create();
1117 studio_init_cb.task("Init Dock Manager...");
1118 dock_manager=new studio::DockManager();
1120 studio_init_cb.task("Init State Manager...");
1121 state_manager=new StateManager();
1123 studio_init_cb.task("Init Toolbox...");
1124 toolbox=new studio::Toolbox();
1126 studio_init_cb.task("Init Tool Options...");
1127 dialog_tool_options=new studio::Dialog_ToolOptions();
1128 dock_manager->register_dockable(*dialog_tool_options);
1130 studio_init_cb.task("Init History...");
1131 dock_history=new studio::Dock_History();
1132 dock_manager->register_dockable(*dock_history);
1134 studio_init_cb.task("Init Canvases...");
1135 dock_canvases=new studio::Dock_Canvases();
1136 dock_manager->register_dockable(*dock_canvases);
1138 studio_init_cb.task("Init Keyframes...");
1139 dock_keyframes=new studio::Dock_Keyframes();
1140 dock_manager->register_dockable(*dock_keyframes);
1142 studio_init_cb.task("Init Layers...");
1143 dock_layers=new studio::Dock_Layers();
1144 dock_manager->register_dockable(*dock_layers);
1146 studio_init_cb.task("Init Params...");
1147 dock_params=new studio::Dock_Params();
1148 dock_manager->register_dockable(*dock_params);
1150 studio_init_cb.task("Init MetaData...");
1151 dock_meta_data=new studio::Dock_MetaData();
1152 dock_manager->register_dockable(*dock_meta_data);
1154 studio_init_cb.task("Init Children...");
1155 dock_children=new studio::Dock_Children();
1156 dock_manager->register_dockable(*dock_children);
1158 studio_init_cb.task("Init Info...");
1159 dock_info = new studio::Dock_Info();
1160 dock_manager->register_dockable(*dock_info);
1162 studio_init_cb.task("Init Navigator...");
1163 dock_navigator = new studio::Dock_Navigator();
1164 dock_manager->register_dockable(*dock_navigator);
1166 studio_init_cb.task("Init Timetrack...");
1167 dock_timetrack = new studio::Dock_Timetrack();
1168 dock_manager->register_dockable(*dock_timetrack);
1170 studio_init_cb.task("Init Curve Editor...");
1171 dock_curves = new studio::Dock_Curves();
1172 dock_manager->register_dockable(*dock_curves);
1174 studio_init_cb.task("Init Layer Groups...");
1175 dock_layer_groups = new studio::Dock_LayerGroups();
1176 dock_manager->register_dockable(*dock_layer_groups);
1179 studio_init_cb.task("Init Color Dialog...");
1180 dialog_color=new studio::Dialog_Color();
1182 studio_init_cb.task("Init Gradient Dialog...");
1183 dialog_gradient=new studio::Dialog_Gradient();
1185 studio_init_cb.task("Init DeviceTracker...");
1186 device_tracker=new studio::DeviceTracker();
1188 studio_init_cb.task("Init Tools...");
1189 state_manager->add_state(&state_normal);
1190 state_manager->add_state(&state_smooth_move);
1191 state_manager->add_state(&state_scale);
1192 state_manager->add_state(&state_rotate);
1194 state_manager->add_state(&state_bline);
1195 state_manager->add_state(&state_polygon);
1196 state_manager->add_state(&state_circle);
1197 state_manager->add_state(&state_rectangle);
1199 state_manager->add_state(&state_draw);
1200 state_manager->add_state(&state_sketch);
1202 state_manager->add_state(&state_eyedrop);
1203 state_manager->add_state(&state_fill);
1205 state_manager->add_state(&state_width);
1206 state_manager->add_state(&state_gradient);
1208 state_manager->add_state(&state_zoom);
1210 studio_init_cb.task("Init ModPalette...");
1211 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1213 studio_init_cb.task("Init ModMirror...");
1214 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1217 studio_init_cb.task("Init Setup Dialog...");
1218 dialog_setup=new studio::Dialog_Setup();
1220 studio_init_cb.task("Init Input Dialog...");
1221 dialog_input=new Gtk::InputDialog();
1223 studio_init_cb.task("Init auto recovery...");
1224 auto_recover=new AutoRecover();
1226 studio_init_cb.amount_complete(9250,10000);
1227 studio_init_cb.task("Loading Settings...");
1229 studio_init_cb.task("Checking auto-recover...");
1231 studio_init_cb.amount_complete(9900,10000);
1233 if(auto_recover->recovery_needed())
1235 about_window.hide();
1237 get_ui_interface()->yes_no(
1239 "SYNFIG Studio seems to have crashed\n"
1240 "before you could save all your files.\n"
1241 "Would you like to re-open those files\n"
1242 "and recover your unsaved changes?"
1243 )==synfigapp::UIInterface::RESPONSE_YES
1246 if(!auto_recover->recover())
1248 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1251 get_ui_interface()->error(
1252 _("SYNFIG Studio has attempted to recover\n"
1253 "from a previous crash. The files that it has\n"
1254 "recovered are NOT YET SAVED. It would be a good\n"
1255 "idea to review them and save them now.")
1258 about_window.show();
1261 // Look for any files given on the command line,
1262 // and load them if found.
1263 for(;*argc>=1;(*argc)--)
1264 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1266 studio_init_cb.task("Loading files...");
1267 about_window.hide();
1268 open((*argv)[*argc]);
1269 about_window.show();
1272 studio_init_cb.task("Done.");
1273 studio_init_cb.amount_complete(10000,10000);
1279 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1283 StateManager* App::get_state_manager() { return state_manager; }
1287 shutdown_in_progress=true;
1291 synfigapp::Main::settings().remove_domain("pref");
1293 selected_instance=0;
1295 // Unload all of the modules
1296 for(;!module_list_.empty();module_list_.pop_back());
1298 delete state_manager;
1302 delete auto_recover;
1306 // studio::App::iteration(false);
1310 // studio::App::iteration(false);
1312 // studio::App::iteration(false);
1314 delete dialog_setup;
1316 delete dialog_gradient;
1318 delete dialog_color;
1320 delete dialog_input;
1322 delete dock_manager;
1324 instance_list.clear();
1326 // studio::App::iteration(false);
1330 App::get_user_app_directory()
1333 return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
1335 return Glib::build_filename(Glib::get_home_dir(),"Synfig");
1340 App::get_config_file(const synfig::String& file)
1342 return Glib::build_filename(get_user_app_directory(),file);
1346 App::add_recent_file(const std::string &file_name)
1348 std::string filename(file_name);
1350 assert(!filename.empty());
1352 if(filename.empty())
1355 // Toss out any "hidden" files
1356 if(basename(filename)[0]=='.')
1359 // If we aren't an absolute path, turn outselves into one
1360 if(!is_absolute_path(filename))
1361 filename=absolute_path(filename);
1363 list<string>::iterator iter;
1364 // Check to see if the file is already on the list.
1365 // If it is, then remove it from the list
1366 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1369 recent_files.erase(iter);
1374 // Push the filename to the front of the list
1375 recent_files.push_front(filename);
1377 // Clean out the files at the end of the list.
1378 while(recent_files.size()>(unsigned)get_max_recent_files())
1379 recent_files.pop_back();
1381 signal_recent_files_changed_();
1386 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1389 App::get_time_format()
1391 return _App_time_format;
1395 App::set_time_format(synfig::Time::Format x)
1402 App::save_settings()
1407 std::string filename=get_config_file("accelrc");
1408 Gtk::AccelMap::save(filename);
1411 std::string filename=get_config_file("recentfiles");
1413 std::ofstream file(filename.c_str());
1417 synfig::warning("Unable to save %s",filename.c_str());
1421 list<string>::reverse_iterator iter;
1423 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1427 std::string filename=get_config_file("settings");
1428 synfigapp::Main::settings().save_to_file(filename);
1432 synfig::warning("Caught exception when attempting to save settings.");
1437 App::load_settings()
1442 std::string filename=get_config_file("accelrc");
1443 Gtk::AccelMap::load(filename);
1446 std::string filename=get_config_file("recentfiles");
1448 std::ifstream file(filename.c_str());
1452 std::string recent_file;
1453 getline(file,recent_file);
1454 if(!recent_file.empty())
1455 add_recent_file(recent_file);
1458 std::string filename=get_config_file("settings");
1459 if(!synfigapp::Main::settings().load_from_file(filename))
1461 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1462 //if(!synfigapp::Main::settings().load_from_file(filename))
1464 gamma.set_gamma(1.0/2.2);
1465 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1466 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1467 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1468 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1469 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1470 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1471 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1472 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1473 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1474 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1475 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1476 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1477 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1484 synfig::warning("Caught exception when attempting to load settings.");
1489 App::shutdown_request(GdkEventAny*)
1493 //return !shutdown_in_progress;
1499 if(shutdown_in_progress)return;
1502 get_ui_interface()->task("Quit Request");
1505 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1509 std::list<etl::handle<Instance> >::iterator iter;
1510 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1512 if(!(*iter)->safe_close())
1516 if((*iter)->synfigapp::Instance::get_action_count())
1518 handle<synfigapp::UIInterface> uim;
1519 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1521 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1522 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1524 case synfigapp::UIInterface::RESPONSE_NO:
1526 case synfigapp::UIInterface::RESPONSE_YES:
1529 case synfigapp::UIInterface::RESPONSE_CANCEL:
1538 if((*iter)->synfigapp::Instance::is_modified())
1540 handle<synfigapp::UIInterface> uim;
1541 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1543 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() );
1544 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1546 case synfigapp::UIInterface::RESPONSE_NO:
1548 case synfigapp::UIInterface::RESPONSE_YES:
1549 (*iter)->dialog_cvs_commit();
1551 case synfigapp::UIInterface::RESPONSE_CANCEL:
1560 // This next line causes things to crash for some reason
1564 shutdown_in_progress=true;
1566 instance_list.clear();
1568 while(studio::App::events_pending())studio::App::iteration(false);
1571 auto_recover->normal_shutdown();
1573 get_ui_interface()->task("Quit Request sent");
1579 dialog_setup->refresh();
1580 dialog_setup->show();
1583 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1584 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1587 //#define USE_WIN32_FILE_DIALOGS 1
1590 #ifdef USE_WIN32_FILE_DIALOGS
1591 static OPENFILENAME ofn={};
1595 #include <gdk/gdkwin32.h>
1599 App::dialog_open_file(const std::string &title, std::string &filename)
1601 #ifdef USE_WIN32_FILE_DIALOGS
1602 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1604 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1605 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1606 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1608 ofn.lStructSize=sizeof(OPENFILENAME);
1609 ofn.hwndOwner = hWnd;
1610 ofn.hInstance = hInstance;
1611 ofn.lpstrFilter = szFilter;
1612 // ofn.lpstrCustomFilter=NULL;
1613 // ofn.nMaxCustFilter=0;
1614 // ofn.nFilterIndex=0;
1615 // ofn.lpstrFile=NULL;
1616 ofn.nMaxFile=MAX_PATH;
1617 // ofn.lpstrFileTitle=NULL;
1618 // ofn.lpstrInitialDir=NULL;
1619 // ofn.lpstrTitle=NULL;
1620 ofn.Flags=OFN_HIDEREADONLY;
1621 // ofn.nFileOffset=0;
1622 // ofn.nFileExtension=0;
1623 ofn.lpstrDefExt=TEXT("sif");
1624 // ofn.lCustData = 0l;
1626 // ofn.lpTemplateName=NULL;
1628 CHAR szFilename[MAX_PATH];
1630 strcpy(szFilename,filename.c_str());
1631 strcpy(szTitle,title.c_str());
1633 ofn.lpstrFile=szFilename;
1634 ofn.lpstrFileTitle=szTitle;
1636 if(GetOpenFileName(&ofn))
1638 filename=szFilename;
1644 synfig::String prev_path;
1645 if(!_preferences.get_value("curr_path",prev_path))
1652 GtkWidget *fileselection;
1653 fileselection = gtk_file_selection_new(title.c_str());
1656 if(basename(filename)==filename)
1658 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1661 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1663 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1665 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1666 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1668 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1669 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1671 gtk_widget_show(fileselection);
1679 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1680 _preferences.set_value("curr_path",dirname(filename));
1684 gtk_widget_destroy(fileselection);
1687 gtk_widget_destroy(fileselection);
1693 App::dialog_save_file(const std::string &title, std::string &filename)
1695 #ifdef USE_WIN32_FILE_DIALOGS
1696 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1698 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1699 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1700 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1702 ofn.lStructSize=sizeof(OPENFILENAME);
1703 ofn.hwndOwner = hWnd;
1704 ofn.hInstance = hInstance;
1705 ofn.lpstrFilter = szFilter;
1706 // ofn.lpstrCustomFilter=NULL;
1707 // ofn.nMaxCustFilter=0;
1708 // ofn.nFilterIndex=0;
1709 // ofn.lpstrFile=NULL;
1710 ofn.nMaxFile=MAX_PATH;
1711 // ofn.lpstrFileTitle=NULL;
1712 // ofn.lpstrInitialDir=NULL;
1713 // ofn.lpstrTitle=NULL;
1714 ofn.Flags=OFN_OVERWRITEPROMPT;
1715 // ofn.nFileOffset=0;
1716 // ofn.nFileExtension=0;
1717 ofn.lpstrDefExt=TEXT("sif");
1718 // ofn.lCustData = 0l;
1720 // ofn.lpTemplateName=NULL;
1722 CHAR szFilename[MAX_PATH];
1724 strcpy(szFilename,filename.c_str());
1725 strcpy(szTitle,title.c_str());
1727 ofn.lpstrFile=szFilename;
1728 ofn.lpstrFileTitle=szTitle;
1730 if(GetSaveFileName(&ofn))
1732 filename=szFilename;
1737 return dialog_open_file(title, filename);
1742 App::dialog_saveas_file(const std::string &title, std::string &filename)
1744 #if USE_WIN32_FILE_DIALOGS
1745 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1747 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1748 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1749 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1751 ofn.lStructSize=sizeof(OPENFILENAME);
1752 ofn.hwndOwner = hWnd;
1753 ofn.hInstance = hInstance;
1754 ofn.lpstrFilter = szFilter;
1755 // ofn.lpstrCustomFilter=NULL;
1756 // ofn.nMaxCustFilter=0;
1757 // ofn.nFilterIndex=0;
1758 // ofn.lpstrFile=NULL;
1759 ofn.nMaxFile=MAX_PATH;
1760 // ofn.lpstrFileTitle=NULL;
1761 // ofn.lpstrInitialDir=NULL;
1762 // ofn.lpstrTitle=NULL;
1763 ofn.Flags=OFN_OVERWRITEPROMPT;
1764 // ofn.nFileOffset=0;
1765 // ofn.nFileExtension=0;
1766 ofn.lpstrDefExt=TEXT("sif");
1767 // ofn.lCustData = 0l;
1769 // ofn.lpTemplateName=NULL;
1771 CHAR szFilename[MAX_PATH];
1773 strcpy(szFilename,filename.c_str());
1774 strcpy(szTitle,title.c_str());
1776 ofn.lpstrFile=szFilename;
1777 ofn.lpstrFileTitle=szTitle;
1779 if(GetSaveFileName(&ofn))
1781 filename=szFilename;
1786 return dialog_open_file(title, filename);
1791 App::dialog_error_blocking(const std::string &title, const std::string &message)
1796 true // use_separator
1798 Gtk::Label label(message);
1801 dialog.get_vbox()->pack_start(label);
1802 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1808 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1813 true // use_separator
1815 Gtk::Label label(message);
1818 dialog.get_vbox()->pack_start(label);
1819 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1825 App::dialog_yes_no(const std::string &title, const std::string &message)
1830 true // use_separator
1832 Gtk::Label label(message);
1835 dialog.get_vbox()->pack_start(label);
1836 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1837 dialog.add_button(Gtk::StockID("gtk-no"),0);
1839 return dialog.run();
1843 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1848 true // use_separator
1850 Gtk::Label label(message);
1853 dialog.get_vbox()->pack_start(label);
1854 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1855 dialog.add_button(Gtk::StockID("gtk-no"),0);
1856 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1858 return dialog.run();
1862 App::dialog_not_implemented()
1865 "Feature not available", // Title
1867 true // use_separator
1869 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1872 dialog.get_vbox()->pack_start(label);
1873 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1879 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1884 true // use_separator
1886 Gtk::Label label(message);
1888 dialog.get_vbox()->pack_start(label);
1891 entry.set_text(text);
1893 entry.set_activates_default(true);
1894 dialog.get_vbox()->pack_start(entry);
1896 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1897 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1898 dialog.set_default_response(Gtk::RESPONSE_OK);
1899 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1902 if(dialog.run()!=Gtk::RESPONSE_OK)
1905 text=entry.get_text();
1914 App::open(std::string filename)
1916 return open_as(filename,filename);
1920 App::open_as(std::string filename,std::string as)
1924 OneMoment one_moment;
1926 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1927 if(canvas && get_instance(canvas))
1929 get_instance(canvas)->find_canvas_view(canvas)->present();
1930 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1933 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1935 add_recent_file(as);
1937 handle<Instance> instance(Instance::create(canvas));
1940 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1944 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)")))
1945 instance->dialog_cvs_update();
1949 dialog_error_blocking(_("Error"), x);
1954 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1958 _preferences.set_value("curr_path",dirname(as));
1967 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1968 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
1970 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
1972 canvas->rend_desc().set_frame_rate(24.0);
1973 canvas->rend_desc().set_time_start(0.0);
1974 canvas->rend_desc().set_time_end(00.0);
1975 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1976 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1977 canvas->rend_desc().set_tl(Vector(-4,2.25));
1978 canvas->rend_desc().set_br(Vector(4,-2.25));
1979 canvas->rend_desc().set_w(480);
1980 canvas->rend_desc().set_h(270);
1981 canvas->rend_desc().set_antialias(1);
1982 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1983 canvas->set_file_name(file_name);
1985 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
1991 string filename="*.sif";
1993 while(dialog_open_file("Open", filename))
1995 // If the filename still has wildcards, then we should
1996 // continue looking for the file we want
1997 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2003 get_ui_interface()->error(_("Unable to open file"));
2008 App::set_selected_instance(etl::loose_handle<Instance> instance)
2010 /* if(get_selected_instance()==instance)
2012 selected_instance=instance;
2013 signal_instance_selected()(instance);
2019 selected_instance=instance;
2020 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2024 instance->focus(instance->get_canvas());
2027 set_selected_canvas_view(0);
2029 signal_instance_selected()(instance);
2033 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2035 selected_canvas_view=canvas_view;
2036 signal_canvas_view_focus()(selected_canvas_view);
2039 selected_instance=canvas_view->get_instance();
2040 signal_instance_selected()(canvas_view->get_instance());
2043 if(get_selected_canvas_view()==canvas_view)
2045 signal_canvas_view_focus()(selected_canvas_view);
2046 signal_instance_selected()(canvas_view->get_instance());
2049 selected_canvas_view=canvas_view;
2050 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2051 set_selected_instance(canvas_view->get_instance());
2052 signal_canvas_view_focus()(selected_canvas_view);
2056 etl::loose_handle<Instance>
2057 App::get_instance(Canvas::Handle canvas)
2059 if(!canvas) return 0;
2060 canvas=canvas->get_root();
2062 std::list<etl::handle<Instance> >::iterator iter;
2063 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2065 if((*iter)->get_canvas()==canvas)
2074 (new class About())->show();
2080 if(selected_instance)
2081 selected_instance->undo();
2087 if(selected_instance)
2088 selected_instance->redo();
2092 studio::App::get_base_path()
2094 return app_base_path_;