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)
453 #ifdef LICENSE_KEY_REQUIRED
458 license_file="/usr/local/etc/.synfiglicense";
460 license_file=basedir+"\\etc\\.synfiglicense";
464 key=Glib::file_get_contents(license_file);
465 } catch (Glib::FileError) { }
467 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
469 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
473 if(!App::dialog_entry(
474 _("Synfig Studio Authentication"),
475 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
478 throw String("No License");
481 FILE* file=fopen(license_file.c_str(),"w");
484 fprintf(file,"%s",key.c_str());
488 synfig::error("Unable to save license key!");
490 synfig::info("License Authenticated -- Serial #%05d",serial);
499 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
501 action_group_list.push_back(action_group);
502 Gtk::UIManager::insert_action_group(action_group, pos);
506 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
508 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
509 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
510 if(*iter==action_group)
512 action_group_list.erase(iter);
513 Gtk::UIManager::remove_action_group(action_group);
516 synfig::error("Unable to find action group");
520 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
522 ui_manager->insert_action_group(group,0);
525 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
526 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
529 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
532 if(*iter && (*iter)->get_name()!="menus")
534 synfig::info("Removing action group "+(*iter)->get_name());
535 ui_manager->remove_action_group(*iter);
539 ui_manager->insert_action_group(group,0);
542 for(;!prev_groups.empty();prev_groups.pop_front())
544 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
545 ui_manager->insert_action_group(prev_groups.front(),1);
550 class Preferences : public synfigapp::Settings
553 virtual bool get_value(const synfig::String& key, synfig::String& value)const
557 value=strprintf("%f %f %f %f",
558 App::gamma.get_gamma_r(),
559 App::gamma.get_gamma_g(),
560 App::gamma.get_gamma_b(),
561 App::gamma.get_black_level()
565 if(key=="time_format")
567 value=strprintf("%i",App::get_time_format());
570 if(key=="file_history.size")
572 value=strprintf("%i",App::get_max_recent_files());
575 if(key=="use_colorspace_gamma")
577 value=strprintf("%i",(int)App::use_colorspace_gamma);
580 if(key=="distance_system")
582 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
585 if(key=="auto_recover_backup_interval")
587 value=strprintf("%i",App::auto_recover->get_timeout());
591 return synfigapp::Settings::get_value(key,value);
594 virtual bool set_value(const synfig::String& key,const synfig::String& value)
600 strscanf(value,"%f %f %f %f",
607 App::gamma.set_all(r,g,b,blk);
611 if(key=="time_format")
613 int i(atoi(value.c_str()));
614 App::set_time_format(static_cast<synfig::Time::Format>(i));
617 if(key=="auto_recover_backup_interval")
619 int i(atoi(value.c_str()));
620 App::auto_recover->set_timeout(i);
623 if(key=="file_history.size")
625 int i(atoi(value.c_str()));
626 App::set_max_recent_files(i);
629 if(key=="use_colorspace_gamma")
631 int i(atoi(value.c_str()));
632 App::use_colorspace_gamma=i;
635 if(key=="distance_system")
637 App::distance_system=Distance::ident_system(value);;
641 return synfigapp::Settings::set_value(key,value);
644 virtual KeyList get_key_list()const
646 KeyList ret(synfigapp::Settings::get_key_list());
647 ret.push_back("gamma");
648 ret.push_back("time_format");
649 ret.push_back("distance_system");
650 ret.push_back("file_history.size");
651 ret.push_back("use_colorspace_gamma");
652 ret.push_back("auto_recover_backup_interval");
657 static Preferences _preferences;
662 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
664 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
666 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
668 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
669 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
670 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
671 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
672 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
673 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
674 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
675 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
676 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
677 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
678 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
679 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
681 // Add the synfigapp actions...
682 synfigapp::Action::Book::iterator iter;
683 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
685 actions_action_group->add(Gtk::Action::create(
686 "action-"+iter->second.name,
687 get_action_stock_id(iter->second),
688 iter->second.local_name,iter->second.local_name
692 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
693 #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); }
694 #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); }
696 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
697 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
698 DEFINE_ACTION("open", Gtk::Stock::OPEN);
699 DEFINE_ACTION("save", Gtk::Stock::SAVE);
700 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
701 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
702 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
703 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
704 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
705 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
706 DEFINE_ACTION("import", _("Import"));
707 DEFINE_ACTION("render", _("Render"));
708 DEFINE_ACTION("preview", _("Preview"));
709 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
710 DEFINE_ACTION("sound", _("Sound File"));
711 DEFINE_ACTION("options", _("Options"));
712 DEFINE_ACTION("close", _("Close"));
715 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
716 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
717 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
718 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
719 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
720 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
721 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
722 DEFINE_ACTION("properties", _("Properties"));
724 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
725 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
726 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
727 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
728 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
729 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
730 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
731 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
732 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
733 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
734 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
735 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
736 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
737 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
738 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
739 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
740 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
741 DEFINE_ACTION("play", _("Play"));
742 DEFINE_ACTION("pause", _("Pause"));
743 DEFINE_ACTION("stop", _("Stop"));
744 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
745 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
746 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
747 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
748 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
749 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
750 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
751 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
752 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
753 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
754 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
755 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
756 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
757 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
758 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
759 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
760 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
761 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
762 DEFINE_ACTION("seek-end", _("Seek to End"));
764 DEFINE_ACTION("action-group_add", _("Add group"));
766 DEFINE_ACTION("canvas-new", _("New Canvas"));
768 DEFINE_ACTION("amount-inc", _("Increase Amount"));
769 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
774 // Set up synfigapp actions
776 synfigapp::Action::Book::iterator iter;
778 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
780 Gtk::StockID stock_id;
782 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
784 //Gtk::Image* image(manage(new Gtk::Image()));
785 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
786 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
787 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
788 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
789 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
790 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
791 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
792 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
793 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
794 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
796 actions_action_group->add(Gtk::Action::create(
797 "action-"+iter->second.name,
799 iter->second.local_name,iter->second.local_name
807 Glib::ustring ui_info =
809 " <popup name='menu-toolbox' action='menu-toolbox'>"
810 " <menu action='menu-file'>"
813 " <popup name='menu-main' action='menu-main'>"
814 " <menu action='menu-file'>"
815 " <menuitem action='save' />"
816 " <menuitem action='save-as' />"
817 " <menuitem action='revert' />"
818 " <separator name='bleh01'/>"
819 " <menuitem action='cvs-add' />"
820 " <menuitem action='cvs-update' />"
821 " <menuitem action='cvs-commit' />"
822 " <menuitem action='cvs-revert' />"
823 " <separator name='bleh02'/>"
824 " <menuitem action='import' />"
825 " <separator name='bleh03'/>"
826 " <menuitem action='render' />"
827 " <menuitem action='preview' />"
828 " <menuitem action='sound' />"
829 " <separator name='bleh04'/>"
830 " <menuitem action='options' />"
831 " <menuitem action='close' />"
833 " <menu action='menu-edit'>"
834 " <menuitem action='undo'/>"
835 " <menuitem action='redo'/>"
836 " <separator name='bleh05'/>"
837 " <menuitem action='cut'/>"
838 " <menuitem action='copy'/>"
839 " <menuitem action='paste'/>"
840 " <separator name='bleh06'/>"
841 " <menuitem action='select-all-ducks'/>"
842 " <menuitem action='unselect-all-layers'/>"
843 " <separator name='bleh07'/>"
844 " <menuitem action='properties'/>"
846 " <menu action='menu-view'>"
847 " <menu action='menu-duck-mask'>"
848 " <menuitem action='mask-position-ducks' />"
849 " <menuitem action='mask-vertex-ducks' />"
850 " <menuitem action='mask-tangent-ducks' />"
851 " <menuitem action='mask-radius-ducks' />"
852 " <menuitem action='mask-width-ducks' />"
853 " <menuitem action='mask-angle-ducks' />"
855 " <menu action='menu-preview-quality'>"
856 " <menuitem action='quality-00' />"
857 " <menuitem action='quality-01' />"
858 " <menuitem action='quality-02' />"
859 " <menuitem action='quality-03' />"
860 " <menuitem action='quality-04' />"
861 " <menuitem action='quality-05' />"
862 " <menuitem action='quality-06' />"
863 " <menuitem action='quality-07' />"
864 " <menuitem action='quality-08' />"
865 " <menuitem action='quality-09' />"
866 " <menuitem action='quality-10' />"
868 " <separator name='bleh08'/>"
869 " <menuitem action='play'/>"
870 " <menuitem action='pause'/>"
871 " <menuitem action='stop'/>"
872 " <menuitem action='dialog-flipbook'/>"
873 " <separator name='bleh09'/>"
874 " <menuitem action='toggle-grid-show'/>"
875 " <menuitem action='toggle-grid-snap'/>"
876 " <menuitem action='toggle-guide-show'/>"
877 " <menuitem action='toggle-low-res'/>"
878 " <menuitem action='toggle-onion-skin'/>"
879 " <separator name='bleh10'/>"
880 " <menuitem action='canvas-zoom-in'/>"
881 " <menuitem action='canvas-zoom-out'/>"
882 " <menuitem action='canvas-zoom-fit'/>"
883 " <menuitem action='canvas-zoom-100'/>"
884 " <separator name='bleh11'/>"
885 " <menuitem action='time-zoom-in'/>"
886 " <menuitem action='time-zoom-out'/>"
887 " <separator name='bleh12'/>"
888 " <menuitem action='jump-next-keyframe'/>"
889 " <menuitem action='jump-prev-keyframe'/>"
890 " <menuitem action='seek-next-frame'/>"
891 " <menuitem action='seek-prev-frame'/>"
892 " <menuitem action='seek-next-second'/>"
893 " <menuitem action='seek-prev-second'/>"
894 " <menuitem action='seek-begin'/>"
895 " <menuitem action='seek-end'/>"
897 " <menu action='menu-canvas'>"
898 " <menuitem action='canvas-new'/>"
899 " <menuitem action='amount-inc'/>"
900 " <menuitem action='amount-dec'/>"
902 " <menu name='menu-state' action='menu-state'>"
904 " <menu action='menu-group'>"
905 " <menuitem action='action-group_add'/>"
907 " <menu action='menu-layer'>"
908 //" <menuitem action='cut'/>"
909 //" <menuitem action='copy'/>"
910 //" <menuitem action='paste'/>"
911 //" <separator name='bleh06'/>"
912 " <menu action='menu-layer-new'></menu>"
914 " <menu action='menu-keyframe'>"
915 " <menuitem action='keyframe-properties'/>"
922 " <menubar name='MenuBar'>"
923 " <menu action='MenuFile'>"
924 " <menuitem action='New'/>"
925 " <menuitem action='Open'/>"
927 " <menuitem action='Quit'/>"
929 " <menu action='MenuEdit'>"
930 " <menuitem action='Cut'/>"
931 " <menuitem action='Copy'/>"
932 " <menuitem action='Paste'/>"
935 " <toolbar name='ToolBar'>"
936 " <toolitem action='Open'/>"
937 " <toolitem action='Quit'/>"
943 actions_action_group->set_sensitive(false);
944 App::ui_manager()->set_add_tearoffs(true);
945 App::ui_manager()->insert_action_group(menus_action_group,1);
946 App::ui_manager()->insert_action_group(actions_action_group,1);
947 App::ui_manager()->add_ui_from_string(ui_info);
949 //App::ui_manager()->get_accel_group()->unlock();
951 catch(const Glib::Error& ex)
953 synfig::error("building menus and toolbars failed: " + ex.what());
956 // Add default keyboard accelerators
957 #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()); }
958 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
959 ACCEL("<Actions>//select-all-ducks","<Control>a");
960 ACCEL("<Actions>//unselect-all-layers","<Control>d");
961 ACCEL("<Actions>//render","F9");
962 ACCEL("<Actions>//preview","F11");
963 ACCEL("<Actions>//properties","F8");
964 ACCEL("<Actions>//options","F12");
965 ACCEL("<Actions>//import","<control>i");
966 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
967 ACCEL("<Actions>//toggle-grid-show","<Control>g");
968 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
969 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
970 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
971 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
972 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
973 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
974 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
975 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
978 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
979 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
981 ACCEL("<Actions>//quality-01","<Control>1");
982 ACCEL("<Actions>//quality-02","<Control>2");
983 ACCEL("<Actions>//quality-03","<Control>3");
984 ACCEL("<Actions>//quality-04","<Control>4");
985 ACCEL("<Actions>//quality-05","<Control>5");
986 ACCEL("<Actions>//quality-06","<Control>6");
987 ACCEL("<Actions>//quality-07","<Control>7");
988 ACCEL("<Actions>//quality-08","<Control>8");
989 ACCEL("<Actions>//quality-09","<Control>9");
990 ACCEL("<Actions>//quality-10","<Control>0");
991 ACCEL("<Actions>//undo","<Control>z");
992 ACCEL("<Actions>//redo","<Control>r");
993 ACCEL("<Actions>//action-layer_remove","Delete");
995 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
996 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
997 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
998 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
999 ACCEL("<Actions>//time-zoom-in","+");
1000 ACCEL("<Actions>//time-zoom-out","_");
1002 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1003 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1005 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1006 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1007 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1008 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1009 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1010 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1011 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1012 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1013 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1014 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1015 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1016 ACCEL("<Actions>//seek-begin","Home");
1017 ACCEL("<Actions>//seek-end","End");
1018 ACCEL("<Actions>//state-normal","<Mod1>a");
1019 ACCEL("<Actions>//state-rotate","<Mod1>s");
1020 ACCEL("<Actions>//state-scale","<Mod1>d");
1021 ACCEL("<Actions>//state-bline","<Mod1>b");
1022 ACCEL("<Actions>//state-fill","<Mod1>f");
1023 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1024 ACCEL("<Actions>//state-gradient","<Mod1>g");
1025 ACCEL("<Actions>//state-zoom","<Mod1>z");
1026 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1032 #define mkdir(x,y) mkdir(x)
1035 /* === M E T H O D S ======================================================= */
1037 App::App(int *argc, char ***argv):
1038 Gtk::Main(argc,argv),
1039 IconControler(etl::dirname((*argv)[0]))
1041 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1044 serial_=check_license(app_base_path_);
1047 ui_interface_=new GlobalUIInterface();
1051 Glib::thread_init();
1053 distance_system=Distance::SYSTEM_UNITS;
1055 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1058 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1062 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1070 if(!SYNFIG_CHECK_VERSION())
1072 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1073 dialog_error_blocking("SYNFIG Studio",
1074 "This copy of SYNFIG Studio was compiled against a\n"
1075 "different version of libsynfig than what is currently\n"
1076 "installed. Synfig Studio will now abort. Try downloading\n"
1077 "the latest version from the SYNFIG Development Website at\n"
1078 "http://dev.synfig.com/ "
1083 catch(synfig::SoftwareExpired)
1085 cerr<<"FATAL: Software Expired"<<endl;
1086 dialog_error_blocking("SYNFIG Studio",
1087 "This copy of SYNFIG Studio has expired.\n"
1088 "Please erase this copy, or download and\n"
1089 "install the latest copy from the SYNFIG\n"
1090 "Development Website at http://dev.synfig.com/ ."
1094 Glib::set_application_name(_("SYNFIG Studio"));
1097 about_window.set_can_self_destruct(false);
1098 about_window.show();
1100 shutdown_in_progress=false;
1101 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1102 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1104 // Initialize the Synfig library
1105 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1108 get_ui_interface()->error("Failed to initialize synfig!");
1112 // add the preferences to the settings
1113 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1117 studio_init_cb.task("Init UI Manager...");
1118 App::ui_manager_=studio::UIManager::create();
1121 studio_init_cb.task("Init Dock Manager...");
1122 dock_manager=new studio::DockManager();
1124 studio_init_cb.task("Init State Manager...");
1125 state_manager=new StateManager();
1127 studio_init_cb.task("Init Toolbox...");
1128 toolbox=new studio::Toolbox();
1130 studio_init_cb.task("Init Tool Options...");
1131 dialog_tool_options=new studio::Dialog_ToolOptions();
1132 dock_manager->register_dockable(*dialog_tool_options);
1134 studio_init_cb.task("Init History...");
1135 dock_history=new studio::Dock_History();
1136 dock_manager->register_dockable(*dock_history);
1138 studio_init_cb.task("Init Canvases...");
1139 dock_canvases=new studio::Dock_Canvases();
1140 dock_manager->register_dockable(*dock_canvases);
1142 studio_init_cb.task("Init Keyframes...");
1143 dock_keyframes=new studio::Dock_Keyframes();
1144 dock_manager->register_dockable(*dock_keyframes);
1146 studio_init_cb.task("Init Layers...");
1147 dock_layers=new studio::Dock_Layers();
1148 dock_manager->register_dockable(*dock_layers);
1150 studio_init_cb.task("Init Params...");
1151 dock_params=new studio::Dock_Params();
1152 dock_manager->register_dockable(*dock_params);
1154 studio_init_cb.task("Init MetaData...");
1155 dock_meta_data=new studio::Dock_MetaData();
1156 dock_manager->register_dockable(*dock_meta_data);
1158 studio_init_cb.task("Init Children...");
1159 dock_children=new studio::Dock_Children();
1160 dock_manager->register_dockable(*dock_children);
1162 studio_init_cb.task("Init Info...");
1163 dock_info = new studio::Dock_Info();
1164 dock_manager->register_dockable(*dock_info);
1166 studio_init_cb.task("Init Navigator...");
1167 dock_navigator = new studio::Dock_Navigator();
1168 dock_manager->register_dockable(*dock_navigator);
1170 studio_init_cb.task("Init Timetrack...");
1171 dock_timetrack = new studio::Dock_Timetrack();
1172 dock_manager->register_dockable(*dock_timetrack);
1174 studio_init_cb.task("Init Curve Editor...");
1175 dock_curves = new studio::Dock_Curves();
1176 dock_manager->register_dockable(*dock_curves);
1178 studio_init_cb.task("Init Layer Groups...");
1179 dock_layer_groups = new studio::Dock_LayerGroups();
1180 dock_manager->register_dockable(*dock_layer_groups);
1183 studio_init_cb.task("Init Color Dialog...");
1184 dialog_color=new studio::Dialog_Color();
1186 studio_init_cb.task("Init Gradient Dialog...");
1187 dialog_gradient=new studio::Dialog_Gradient();
1189 studio_init_cb.task("Init DeviceTracker...");
1190 device_tracker=new studio::DeviceTracker();
1192 studio_init_cb.task("Init Tools...");
1193 state_manager->add_state(&state_normal);
1194 state_manager->add_state(&state_smooth_move);
1195 state_manager->add_state(&state_scale);
1196 state_manager->add_state(&state_rotate);
1198 state_manager->add_state(&state_bline);
1199 state_manager->add_state(&state_polygon);
1200 state_manager->add_state(&state_circle);
1201 state_manager->add_state(&state_rectangle);
1203 state_manager->add_state(&state_draw);
1204 state_manager->add_state(&state_sketch);
1206 state_manager->add_state(&state_eyedrop);
1207 state_manager->add_state(&state_fill);
1209 state_manager->add_state(&state_width);
1210 state_manager->add_state(&state_gradient);
1212 state_manager->add_state(&state_zoom);
1214 studio_init_cb.task("Init ModPalette...");
1215 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1217 studio_init_cb.task("Init ModMirror...");
1218 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1221 studio_init_cb.task("Init Setup Dialog...");
1222 dialog_setup=new studio::Dialog_Setup();
1224 studio_init_cb.task("Init Input Dialog...");
1225 dialog_input=new Gtk::InputDialog();
1227 studio_init_cb.task("Init auto recovery...");
1228 auto_recover=new AutoRecover();
1230 studio_init_cb.amount_complete(9250,10000);
1231 studio_init_cb.task("Loading Settings...");
1233 studio_init_cb.task("Checking auto-recover...");
1235 studio_init_cb.amount_complete(9900,10000);
1237 if(auto_recover->recovery_needed())
1239 about_window.hide();
1241 get_ui_interface()->yes_no(
1243 "SYNFIG Studio seems to have crashed\n"
1244 "before you could save all your files.\n"
1245 "Would you like to re-open those files\n"
1246 "and recover your unsaved changes?"
1247 )==synfigapp::UIInterface::RESPONSE_YES
1250 if(!auto_recover->recover())
1252 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1255 get_ui_interface()->error(
1256 _("SYNFIG Studio has attempted to recover\n"
1257 "from a previous crash. The files that it has\n"
1258 "recovered are NOT YET SAVED. It would be a good\n"
1259 "idea to review them and save them now.")
1262 about_window.show();
1265 // Look for any files given on the command line,
1266 // and load them if found.
1267 for(;*argc>=1;(*argc)--)
1268 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1270 studio_init_cb.task("Loading files...");
1271 about_window.hide();
1272 open((*argv)[*argc]);
1273 about_window.show();
1276 studio_init_cb.task("Done.");
1277 studio_init_cb.amount_complete(10000,10000);
1283 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1287 StateManager* App::get_state_manager() { return state_manager; }
1291 shutdown_in_progress=true;
1295 synfigapp::Main::settings().remove_domain("pref");
1297 selected_instance=0;
1299 // Unload all of the modules
1300 for(;!module_list_.empty();module_list_.pop_back());
1302 delete state_manager;
1306 delete auto_recover;
1310 // studio::App::iteration(false);
1314 // studio::App::iteration(false);
1316 // studio::App::iteration(false);
1318 delete dialog_setup;
1320 delete dialog_gradient;
1322 delete dialog_color;
1324 delete dialog_input;
1326 delete dock_manager;
1328 instance_list.clear();
1330 // studio::App::iteration(false);
1334 App::get_user_app_directory()
1337 return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
1339 return Glib::build_filename(Glib::get_home_dir(),"Synfig");
1344 App::get_config_file(const synfig::String& file)
1346 return Glib::build_filename(get_user_app_directory(),file);
1350 App::add_recent_file(const std::string &file_name)
1352 std::string filename(file_name);
1354 assert(!filename.empty());
1356 if(filename.empty())
1359 // Toss out any "hidden" files
1360 if(basename(filename)[0]=='.')
1363 // If we aren't an absolute path, turn outselves into one
1364 if(!is_absolute_path(filename))
1365 filename=absolute_path(filename);
1367 list<string>::iterator iter;
1368 // Check to see if the file is already on the list.
1369 // If it is, then remove it from the list
1370 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1373 recent_files.erase(iter);
1378 // Push the filename to the front of the list
1379 recent_files.push_front(filename);
1381 // Clean out the files at the end of the list.
1382 while(recent_files.size()>(unsigned)get_max_recent_files())
1383 recent_files.pop_back();
1385 signal_recent_files_changed_();
1390 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1393 App::get_time_format()
1395 return _App_time_format;
1399 App::set_time_format(synfig::Time::Format x)
1406 App::save_settings()
1411 std::string filename=get_config_file("accelrc");
1412 Gtk::AccelMap::save(filename);
1415 std::string filename=get_config_file("recentfiles");
1417 std::ofstream file(filename.c_str());
1421 synfig::warning("Unable to save %s",filename.c_str());
1425 list<string>::reverse_iterator iter;
1427 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1431 std::string filename=get_config_file("settings");
1432 synfigapp::Main::settings().save_to_file(filename);
1436 synfig::warning("Caught exception when attempting to save settings.");
1441 App::load_settings()
1446 std::string filename=get_config_file("accelrc");
1447 Gtk::AccelMap::load(filename);
1450 std::string filename=get_config_file("recentfiles");
1452 std::ifstream file(filename.c_str());
1456 std::string recent_file;
1457 getline(file,recent_file);
1458 if(!recent_file.empty())
1459 add_recent_file(recent_file);
1462 std::string filename=get_config_file("settings");
1463 if(!synfigapp::Main::settings().load_from_file(filename))
1465 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1466 //if(!synfigapp::Main::settings().load_from_file(filename))
1468 gamma.set_gamma(1.0/2.2);
1469 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1470 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1471 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1472 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1473 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1474 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1475 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1476 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1477 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1478 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1479 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1480 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1481 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1488 synfig::warning("Caught exception when attempting to load settings.");
1493 App::shutdown_request(GdkEventAny*)
1497 //return !shutdown_in_progress;
1503 if(shutdown_in_progress)return;
1506 get_ui_interface()->task("Quit Request");
1509 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1513 std::list<etl::handle<Instance> >::iterator iter;
1514 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1516 if(!(*iter)->safe_close())
1520 if((*iter)->synfigapp::Instance::get_action_count())
1522 handle<synfigapp::UIInterface> uim;
1523 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1525 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1526 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1528 case synfigapp::UIInterface::RESPONSE_NO:
1530 case synfigapp::UIInterface::RESPONSE_YES:
1533 case synfigapp::UIInterface::RESPONSE_CANCEL:
1542 if((*iter)->synfigapp::Instance::is_modified())
1544 handle<synfigapp::UIInterface> uim;
1545 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1547 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() );
1548 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1550 case synfigapp::UIInterface::RESPONSE_NO:
1552 case synfigapp::UIInterface::RESPONSE_YES:
1553 (*iter)->dialog_cvs_commit();
1555 case synfigapp::UIInterface::RESPONSE_CANCEL:
1564 // This next line causes things to crash for some reason
1568 shutdown_in_progress=true;
1570 instance_list.clear();
1572 while(studio::App::events_pending())studio::App::iteration(false);
1575 auto_recover->normal_shutdown();
1577 get_ui_interface()->task("Quit Request sent");
1583 dialog_setup->refresh();
1584 dialog_setup->show();
1587 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1588 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1591 //#define USE_WIN32_FILE_DIALOGS 1
1594 #ifdef USE_WIN32_FILE_DIALOGS
1595 static OPENFILENAME ofn={};
1599 #include <gdk/gdkwin32.h>
1603 App::dialog_open_file(const std::string &title, std::string &filename)
1605 #ifdef USE_WIN32_FILE_DIALOGS
1606 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1608 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1609 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1610 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1612 ofn.lStructSize=sizeof(OPENFILENAME);
1613 ofn.hwndOwner = hWnd;
1614 ofn.hInstance = hInstance;
1615 ofn.lpstrFilter = szFilter;
1616 // ofn.lpstrCustomFilter=NULL;
1617 // ofn.nMaxCustFilter=0;
1618 // ofn.nFilterIndex=0;
1619 // ofn.lpstrFile=NULL;
1620 ofn.nMaxFile=MAX_PATH;
1621 // ofn.lpstrFileTitle=NULL;
1622 // ofn.lpstrInitialDir=NULL;
1623 // ofn.lpstrTitle=NULL;
1624 ofn.Flags=OFN_HIDEREADONLY;
1625 // ofn.nFileOffset=0;
1626 // ofn.nFileExtension=0;
1627 ofn.lpstrDefExt=TEXT("sif");
1628 // ofn.lCustData = 0l;
1630 // ofn.lpTemplateName=NULL;
1632 CHAR szFilename[MAX_PATH];
1634 strcpy(szFilename,filename.c_str());
1635 strcpy(szTitle,title.c_str());
1637 ofn.lpstrFile=szFilename;
1638 ofn.lpstrFileTitle=szTitle;
1640 if(GetOpenFileName(&ofn))
1642 filename=szFilename;
1648 synfig::String prev_path;
1649 if(!_preferences.get_value("curr_path",prev_path))
1656 GtkWidget *fileselection;
1657 fileselection = gtk_file_selection_new(title.c_str());
1660 if(basename(filename)==filename)
1662 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1665 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1667 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1669 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1670 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1672 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1673 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1675 gtk_widget_show(fileselection);
1683 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1684 _preferences.set_value("curr_path",dirname(filename));
1688 gtk_widget_destroy(fileselection);
1691 gtk_widget_destroy(fileselection);
1697 App::dialog_save_file(const std::string &title, std::string &filename)
1699 #ifdef USE_WIN32_FILE_DIALOGS
1700 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1702 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1703 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1704 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1706 ofn.lStructSize=sizeof(OPENFILENAME);
1707 ofn.hwndOwner = hWnd;
1708 ofn.hInstance = hInstance;
1709 ofn.lpstrFilter = szFilter;
1710 // ofn.lpstrCustomFilter=NULL;
1711 // ofn.nMaxCustFilter=0;
1712 // ofn.nFilterIndex=0;
1713 // ofn.lpstrFile=NULL;
1714 ofn.nMaxFile=MAX_PATH;
1715 // ofn.lpstrFileTitle=NULL;
1716 // ofn.lpstrInitialDir=NULL;
1717 // ofn.lpstrTitle=NULL;
1718 ofn.Flags=OFN_OVERWRITEPROMPT;
1719 // ofn.nFileOffset=0;
1720 // ofn.nFileExtension=0;
1721 ofn.lpstrDefExt=TEXT("sif");
1722 // ofn.lCustData = 0l;
1724 // ofn.lpTemplateName=NULL;
1726 CHAR szFilename[MAX_PATH];
1728 strcpy(szFilename,filename.c_str());
1729 strcpy(szTitle,title.c_str());
1731 ofn.lpstrFile=szFilename;
1732 ofn.lpstrFileTitle=szTitle;
1734 if(GetSaveFileName(&ofn))
1736 filename=szFilename;
1741 return dialog_open_file(title, filename);
1746 App::dialog_saveas_file(const std::string &title, std::string &filename)
1748 #if USE_WIN32_FILE_DIALOGS
1749 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1751 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1752 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1753 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1755 ofn.lStructSize=sizeof(OPENFILENAME);
1756 ofn.hwndOwner = hWnd;
1757 ofn.hInstance = hInstance;
1758 ofn.lpstrFilter = szFilter;
1759 // ofn.lpstrCustomFilter=NULL;
1760 // ofn.nMaxCustFilter=0;
1761 // ofn.nFilterIndex=0;
1762 // ofn.lpstrFile=NULL;
1763 ofn.nMaxFile=MAX_PATH;
1764 // ofn.lpstrFileTitle=NULL;
1765 // ofn.lpstrInitialDir=NULL;
1766 // ofn.lpstrTitle=NULL;
1767 ofn.Flags=OFN_OVERWRITEPROMPT;
1768 // ofn.nFileOffset=0;
1769 // ofn.nFileExtension=0;
1770 ofn.lpstrDefExt=TEXT("sif");
1771 // ofn.lCustData = 0l;
1773 // ofn.lpTemplateName=NULL;
1775 CHAR szFilename[MAX_PATH];
1777 strcpy(szFilename,filename.c_str());
1778 strcpy(szTitle,title.c_str());
1780 ofn.lpstrFile=szFilename;
1781 ofn.lpstrFileTitle=szTitle;
1783 if(GetSaveFileName(&ofn))
1785 filename=szFilename;
1790 return dialog_open_file(title, filename);
1795 App::dialog_error_blocking(const std::string &title, const std::string &message)
1800 true // use_separator
1802 Gtk::Label label(message);
1805 dialog.get_vbox()->pack_start(label);
1806 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1812 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1817 true // use_separator
1819 Gtk::Label label(message);
1822 dialog.get_vbox()->pack_start(label);
1823 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1829 App::dialog_yes_no(const std::string &title, const std::string &message)
1834 true // use_separator
1836 Gtk::Label label(message);
1839 dialog.get_vbox()->pack_start(label);
1840 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1841 dialog.add_button(Gtk::StockID("gtk-no"),0);
1843 return dialog.run();
1847 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1852 true // use_separator
1854 Gtk::Label label(message);
1857 dialog.get_vbox()->pack_start(label);
1858 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1859 dialog.add_button(Gtk::StockID("gtk-no"),0);
1860 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1862 return dialog.run();
1866 App::dialog_not_implemented()
1869 "Feature not available", // Title
1871 true // use_separator
1873 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1876 dialog.get_vbox()->pack_start(label);
1877 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1883 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1888 true // use_separator
1890 Gtk::Label label(message);
1892 dialog.get_vbox()->pack_start(label);
1895 entry.set_text(text);
1897 entry.set_activates_default(true);
1898 dialog.get_vbox()->pack_start(entry);
1900 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1901 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1902 dialog.set_default_response(Gtk::RESPONSE_OK);
1903 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1906 if(dialog.run()!=Gtk::RESPONSE_OK)
1909 text=entry.get_text();
1918 App::open(std::string filename)
1920 return open_as(filename,filename);
1924 App::open_as(std::string filename,std::string as)
1928 OneMoment one_moment;
1930 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1931 if(canvas && get_instance(canvas))
1933 get_instance(canvas)->find_canvas_view(canvas)->present();
1934 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1937 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1939 add_recent_file(as);
1941 handle<Instance> instance(Instance::create(canvas));
1944 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1948 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)")))
1949 instance->dialog_cvs_update();
1953 dialog_error_blocking(_("Error"), x);
1958 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1962 _preferences.set_value("curr_path",dirname(as));
1971 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1972 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
1974 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
1976 canvas->rend_desc().set_frame_rate(24.0);
1977 canvas->rend_desc().set_time_start(0.0);
1978 canvas->rend_desc().set_time_end(00.0);
1979 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1980 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1981 canvas->rend_desc().set_tl(Vector(-4,2.25));
1982 canvas->rend_desc().set_br(Vector(4,-2.25));
1983 canvas->rend_desc().set_w(480);
1984 canvas->rend_desc().set_h(270);
1985 canvas->rend_desc().set_antialias(1);
1986 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1987 canvas->set_file_name(file_name);
1989 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
1995 string filename="*.sif";
1997 while(dialog_open_file("Open", filename))
1999 // If the filename still has wildcards, then we should
2000 // continue looking for the file we want
2001 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2007 get_ui_interface()->error(_("Unable to open file"));
2012 App::set_selected_instance(etl::loose_handle<Instance> instance)
2014 /* if(get_selected_instance()==instance)
2016 selected_instance=instance;
2017 signal_instance_selected()(instance);
2023 selected_instance=instance;
2024 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2028 instance->focus(instance->get_canvas());
2031 set_selected_canvas_view(0);
2033 signal_instance_selected()(instance);
2037 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2039 selected_canvas_view=canvas_view;
2040 signal_canvas_view_focus()(selected_canvas_view);
2043 selected_instance=canvas_view->get_instance();
2044 signal_instance_selected()(canvas_view->get_instance());
2047 if(get_selected_canvas_view()==canvas_view)
2049 signal_canvas_view_focus()(selected_canvas_view);
2050 signal_instance_selected()(canvas_view->get_instance());
2053 selected_canvas_view=canvas_view;
2054 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2055 set_selected_instance(canvas_view->get_instance());
2056 signal_canvas_view_focus()(selected_canvas_view);
2060 etl::loose_handle<Instance>
2061 App::get_instance(Canvas::Handle canvas)
2063 if(!canvas) return 0;
2064 canvas=canvas->get_root();
2066 std::list<etl::handle<Instance> >::iterator iter;
2067 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2069 if((*iter)->get_canvas()==canvas)
2078 (new class About())->show();
2084 if(selected_instance)
2085 selected_instance->undo();
2091 if(selected_instance)
2092 selected_instance->redo();
2096 studio::App::get_base_path()
2098 return app_base_path_;