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-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
35 #ifdef HAVE_SYS_ERRNO_H
36 #include <sys/errno.h>
38 #include <gtkmm/fileselection.h>
39 #include <gtkmm/dialog.h>
40 #include <gtkmm/label.h>
41 #include <gtkmm/stock.h>
42 #include <gtkmm/stockitem.h>
43 #include <gtkmm/iconsource.h>
44 #include <gtkmm/inputdialog.h>
45 #include <gtkmm/accelmap.h>
46 #include <gtkmm/uimanager.h>
50 #include <synfig/loadcanvas.h>
55 #include "canvasview.h"
56 #include "dialog_setup.h"
57 #include "dialog_gradient.h"
58 #include "dialog_color.h"
61 #include "onemoment.h"
63 #include "dockmanager.h"
65 #include "state_eyedrop.h"
66 #include "state_normal.h"
67 #include "state_draw.h"
68 #include "state_fill.h"
69 #include "state_bline.h"
70 #include "state_polygon.h"
71 #include "state_sketch.h"
72 #include "state_gradient.h"
73 #include "state_circle.h"
74 #include "state_rectangle.h"
75 #include "state_smoothmove.h"
76 #include "state_scale.h"
77 #include "state_width.h"
78 #include "state_rotate.h"
79 #include "state_zoom.h"
81 #include "devicetracker.h"
82 #include "dialog_tooloptions.h"
84 #include "autorecover.h"
86 #include <synfigapp/settings.h>
87 #include "dock_history.h"
88 #include "dock_canvases.h"
89 #include "dock_keyframes.h"
90 #include "dock_layers.h"
91 #include "dock_params.h"
92 #include "dock_metadata.h"
93 #include "dock_children.h"
94 #include "dock_info.h"
95 #include "dock_navigator.h"
96 #include "dock_layergroups.h"
97 #include "dock_timetrack.h"
98 #include "dock_curves.h"
100 #include "mod_palette/mod_palette.h"
101 #include "mod_mirror/mod_mirror.h"
103 #include <sys/stat.h>
109 #include "statemanager.h"
116 #define _WIN32_WINNT 0x0500
119 #include <gtkmm/accelmap.h>
120 #include <gtkmm/filechooser.h>
121 #include <gtkmm/filechooserdialog.h>
125 /* === U S I N G =========================================================== */
129 using namespace synfig;
130 using namespace studio;
132 /* === M A C R O S ========================================================= */
134 #ifndef SYNFIG_USER_APP_DIR
136 #define SYNFIG_USER_APP_DIR "Library/Synfig"
138 #define SYNFIG_USER_APP_DIR "Synfig"
143 #define DPM2DPI(x) (float(x)/39.3700787402f)
144 #define DPI2DPM(x) (float(x)*39.3700787402f)
150 # define IMAGE_DIR "share\\pixmaps"
155 # define IMAGE_DIR "/usr/local/share/pixmaps"
159 # define IMAGE_EXT "tif"
162 #include <synfigapp/main.h>
164 /* === S I G N A L S ======================================================= */
166 static sigc::signal<void> signal_present_all_;
168 App::signal_present_all() { return signal_present_all_; }
170 static sigc::signal<void> signal_recent_files_changed_;
172 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
174 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
175 sigc::signal<void,etl::loose_handle<CanvasView> >&
176 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
178 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
179 sigc::signal<void,etl::handle<Instance> >&
180 App::signal_instance_selected() { return signal_instance_selected_; }
182 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
183 sigc::signal<void,etl::handle<Instance> >&
184 App::signal_instance_created() { return signal_instance_created_; }
186 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
187 sigc::signal<void,etl::handle<Instance> >&
188 App::signal_instance_deleted() { return signal_instance_deleted_; }
190 /* === G L O B A L S ======================================================= */
192 static std::list<std::string> recent_files;
193 const std::list<std::string>& App::get_recent_files() { return recent_files; }
195 int App::Busy::count;
196 bool App::shutdown_in_progress;
198 synfig::Gamma App::gamma;
200 Glib::RefPtr<studio::UIManager> App::ui_manager_;
202 synfig::Distance::System App::distance_system;
204 studio::Dialog_Setup* App::dialog_setup;
206 etl::handle< studio::ModPalette > mod_palette_;
207 //studio::Dialog_Palette* App::dialog_palette;
209 std::list<etl::handle<Instance> > App::instance_list;
211 static etl::handle<synfigapp::UIInterface> ui_interface_;
212 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
214 etl::handle<Instance> App::selected_instance;
215 etl::handle<CanvasView> App::selected_canvas_view;
217 studio::Toolbox *studio::App::toolbox=NULL;
219 studio::AutoRecover *studio::App::auto_recover=NULL;
221 studio::IPC *ipc=NULL;
223 studio::DockManager* studio::App::dock_manager=0;
225 studio::DeviceTracker* studio::App::device_tracker=0;
227 studio::Dialog_Gradient* studio::App::dialog_gradient;
229 studio::Dialog_Color* studio::App::dialog_color;
231 Gtk::InputDialog* studio::App::dialog_input;
233 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
235 studio::Dock_History* dock_history;
236 studio::Dock_Canvases* dock_canvases;
237 studio::Dock_Keyframes* dock_keyframes;
238 studio::Dock_Layers* dock_layers;
239 studio::Dock_Params* dock_params;
240 studio::Dock_MetaData* dock_meta_data;
241 studio::Dock_Children* dock_children;
242 studio::Dock_Info* dock_info;
243 studio::Dock_LayerGroups* dock_layer_groups;
244 studio::Dock_Navigator* dock_navigator;
245 studio::Dock_Timetrack* dock_timetrack;
246 studio::Dock_Curves* dock_curves;
248 std::list< etl::handle< studio::Module > > module_list_;
250 bool studio::App::use_colorspace_gamma=true;
252 static int max_recent_files_=25;
253 int studio::App::get_max_recent_files() { return max_recent_files_; }
254 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
256 static synfig::String app_base_path_;
259 }; // END of namespace studio
260 studio::StateManager* state_manager;
265 class GlobalUIInterface : public synfigapp::UIInterface
269 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
274 true // use_separator
276 Gtk::Label label(message);
279 dialog.get_vbox()->pack_start(label);
280 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
281 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
283 dialog.set_default_response(dflt);
285 return (Response)dialog.run();
287 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
292 true // use_separator
294 Gtk::Label label(message);
297 dialog.get_vbox()->pack_start(label);
298 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
299 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
300 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
302 dialog.set_default_response(dflt);
304 return (Response)dialog.run();
306 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
311 true // use_separator
313 Gtk::Label label(message);
316 dialog.get_vbox()->pack_start(label);
317 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
318 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
320 dialog.set_default_response(dflt);
322 return (Response)dialog.run();
326 task(const std::string &task)
328 std::cerr<<task<<std::endl;
329 while(studio::App::events_pending())studio::App::iteration(false);
334 error(const std::string &err)
339 true // use_separator
341 Gtk::Label label(err);
344 dialog.get_vbox()->pack_start(label);
345 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
352 warning(const std::string &err)
354 std::cerr<<"warning: "<<err<<std::endl;
355 while(studio::App::events_pending())studio::App::iteration(false);
360 amount_complete(int current, int total)
362 while(studio::App::events_pending())studio::App::iteration(false);
367 /* === P R O C E D U R E S ================================================= */
369 typedef unsigned char U8;
370 typedef unsigned short U16;
371 typedef unsigned long U32;
381 static inline U32 hash_U32(U32 i)
383 i=i*1664525+1013904223;
384 i=i*1664525+1013904223;
385 i=i*1664525+1013904223;
390 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
391 #define endian_fix(x) (endian_fix_table[x])
393 #define endian_fix(x) (x)
396 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
399 unwound->element.serial=0;
400 unwound->element.checksum=0;
408 case '0': data=0; break;
409 case '1': data=1; break;
410 case '2': data=2; break;
411 case '3': data=3; break;
412 case '4': data=4; break;
413 case '5': data=5; break;
414 case '6': data=6; break;
415 case '7': data=7; break;
416 case '8': data=8; break;
417 case '9': data=9; break;
418 case 'a': case 'A': data=10; break;
419 case 'b': case 'B': data=11; break;
420 case 'c': case 'C': data=12; break;
421 case 'd': case 'D': data=13; break;
422 case 'e': case 'E': data=14; break;
423 case 'f': case 'F': data=15; break;
424 default: return 0; break;
427 unwound->element.checksum|=(((U32)data&3)<<bit);
428 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
433 int v_key_check(const char* key, U32* serial, U32 appid)
435 V_KeyUnwound unwound_key;
436 U32 appid_mask_a=hash_U32(appid);
437 U32 appid_mask_b=hash_U32(appid_mask_a);
439 if(!v_unwind_key(&unwound_key, key))
441 // Invalid characters in key
446 // Undo obfuscation pass
448 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
453 unwound_key.raw[endian_fix(i)]^=(next>>24);
457 unwound_key.element.serial^=appid_mask_a;
458 unwound_key.element.checksum^=appid_mask_b;
460 *serial=unwound_key.element.serial;
462 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
466 int check_license(String basedir)
468 #ifdef LICENSE_KEY_REQUIRED
473 license_file="/usr/local/etc/.synfiglicense";
475 license_file=basedir+"\\etc\\.synfiglicense";
479 key=Glib::file_get_contents(license_file);
480 } catch (Glib::FileError) { }
482 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
484 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
488 if(!App::dialog_entry(
489 _("Synfig Studio Authentication"),
490 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
493 throw String("No License");
496 FILE* file=fopen(license_file.c_str(),"w");
499 fprintf(file,"%s",key.c_str());
503 synfig::error("Unable to save license key!");
505 synfig::info("License Authenticated -- Serial #%05d",serial);
514 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
516 action_group_list.push_back(action_group);
517 Gtk::UIManager::insert_action_group(action_group, pos);
521 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
523 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
524 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
525 if(*iter==action_group)
527 action_group_list.erase(iter);
528 Gtk::UIManager::remove_action_group(action_group);
531 synfig::error("Unable to find action group");
535 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
537 ui_manager->insert_action_group(group,0);
540 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
541 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
544 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
547 if(*iter && (*iter)->get_name()!="menus")
549 synfig::info("Removing action group "+(*iter)->get_name());
550 ui_manager->remove_action_group(*iter);
554 ui_manager->insert_action_group(group,0);
557 for(;!prev_groups.empty();prev_groups.pop_front())
559 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
560 ui_manager->insert_action_group(prev_groups.front(),1);
565 class Preferences : public synfigapp::Settings
568 virtual bool get_value(const synfig::String& key, synfig::String& value)const
572 value=strprintf("%f %f %f %f",
573 App::gamma.get_gamma_r(),
574 App::gamma.get_gamma_g(),
575 App::gamma.get_gamma_b(),
576 App::gamma.get_black_level()
580 if(key=="time_format")
582 value=strprintf("%i",App::get_time_format());
585 if(key=="file_history.size")
587 value=strprintf("%i",App::get_max_recent_files());
590 if(key=="use_colorspace_gamma")
592 value=strprintf("%i",(int)App::use_colorspace_gamma);
595 if(key=="distance_system")
597 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
600 if(key=="auto_recover_backup_interval")
602 value=strprintf("%i",App::auto_recover->get_timeout());
606 return synfigapp::Settings::get_value(key,value);
609 virtual bool set_value(const synfig::String& key,const synfig::String& value)
615 strscanf(value,"%f %f %f %f",
622 App::gamma.set_all(r,g,b,blk);
626 if(key=="time_format")
628 int i(atoi(value.c_str()));
629 App::set_time_format(static_cast<synfig::Time::Format>(i));
632 if(key=="auto_recover_backup_interval")
634 int i(atoi(value.c_str()));
635 App::auto_recover->set_timeout(i);
638 if(key=="file_history.size")
640 int i(atoi(value.c_str()));
641 App::set_max_recent_files(i);
644 if(key=="use_colorspace_gamma")
646 int i(atoi(value.c_str()));
647 App::use_colorspace_gamma=i;
650 if(key=="distance_system")
652 App::distance_system=Distance::ident_system(value);;
656 return synfigapp::Settings::set_value(key,value);
659 virtual KeyList get_key_list()const
661 KeyList ret(synfigapp::Settings::get_key_list());
662 ret.push_back("gamma");
663 ret.push_back("time_format");
664 ret.push_back("distance_system");
665 ret.push_back("file_history.size");
666 ret.push_back("use_colorspace_gamma");
667 ret.push_back("auto_recover_backup_interval");
672 static ::Preferences _preferences;
677 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
679 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
681 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
683 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
684 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
685 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
686 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
687 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
688 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Show/Hide Ducks") );
689 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
690 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
691 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
692 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
693 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
694 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
696 // Add the synfigapp actions...
697 synfigapp::Action::Book::iterator iter;
698 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
700 actions_action_group->add(Gtk::Action::create(
701 "action-"+iter->second.name,
702 get_action_stock_id(iter->second),
703 iter->second.local_name,iter->second.local_name
707 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
708 #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); }
709 #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); }
711 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
712 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
713 DEFINE_ACTION("open", Gtk::Stock::OPEN);
714 DEFINE_ACTION("save", Gtk::Stock::SAVE);
715 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
716 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
717 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
718 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
719 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
720 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
721 DEFINE_ACTION("import", _("Import"));
722 DEFINE_ACTION("render", _("Render"));
723 DEFINE_ACTION("preview", _("Preview"));
724 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
725 DEFINE_ACTION("sound", _("Sound File"));
726 DEFINE_ACTION("options", _("Options"));
727 DEFINE_ACTION("close", _("Close"));
730 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
731 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
732 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
733 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
734 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
735 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
736 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
737 DEFINE_ACTION("properties", _("Properties"));
739 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
740 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
741 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
742 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
743 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
744 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
745 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
746 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
747 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
748 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
749 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
750 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
751 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
752 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
753 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
754 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
755 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
756 DEFINE_ACTION("play", _("Play"));
757 DEFINE_ACTION("pause", _("Pause"));
758 DEFINE_ACTION("stop", _("Stop"));
759 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
760 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
761 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
762 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
763 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
764 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
765 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
766 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
767 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
768 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
769 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
770 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
771 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
772 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
773 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
774 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
775 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
776 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
777 DEFINE_ACTION("seek-end", _("Seek to End"));
779 DEFINE_ACTION("action-group_add", _("Add group"));
781 DEFINE_ACTION("canvas-new", _("New Canvas"));
783 DEFINE_ACTION("amount-inc", _("Increase Amount"));
784 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
789 // Set up synfigapp actions
791 synfigapp::Action::Book::iterator iter;
793 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
795 Gtk::StockID stock_id;
797 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
799 //Gtk::Image* image(manage(new Gtk::Image()));
800 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
801 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
802 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
803 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
804 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
805 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
806 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
807 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
808 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
809 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
811 actions_action_group->add(Gtk::Action::create(
812 "action-"+iter->second.name,
814 iter->second.local_name,iter->second.local_name
822 Glib::ustring ui_info =
824 " <popup name='menu-toolbox' action='menu-toolbox'>"
825 " <menu action='menu-file'>"
828 " <popup name='menu-main' action='menu-main'>"
829 " <menu action='menu-file'>"
830 " <menuitem action='save' />"
831 " <menuitem action='save-as' />"
832 " <menuitem action='revert' />"
833 " <separator name='bleh01'/>"
834 " <menuitem action='cvs-add' />"
835 " <menuitem action='cvs-update' />"
836 " <menuitem action='cvs-commit' />"
837 " <menuitem action='cvs-revert' />"
838 " <separator name='bleh02'/>"
839 " <menuitem action='import' />"
840 " <separator name='bleh03'/>"
841 " <menuitem action='render' />"
842 " <menuitem action='preview' />"
843 " <menuitem action='sound' />"
844 " <separator name='bleh04'/>"
845 " <menuitem action='options' />"
846 " <menuitem action='close' />"
848 " <menu action='menu-edit'>"
849 " <menuitem action='undo'/>"
850 " <menuitem action='redo'/>"
851 " <separator name='bleh05'/>"
852 " <menuitem action='cut'/>"
853 " <menuitem action='copy'/>"
854 " <menuitem action='paste'/>"
855 " <separator name='bleh06'/>"
856 " <menuitem action='select-all-ducks'/>"
857 " <menuitem action='unselect-all-layers'/>"
858 " <separator name='bleh07'/>"
859 " <menuitem action='properties'/>"
861 " <menu action='menu-view'>"
862 " <menu action='menu-duck-mask'>"
863 " <menuitem action='mask-position-ducks' />"
864 " <menuitem action='mask-vertex-ducks' />"
865 " <menuitem action='mask-tangent-ducks' />"
866 " <menuitem action='mask-radius-ducks' />"
867 " <menuitem action='mask-width-ducks' />"
868 " <menuitem action='mask-angle-ducks' />"
870 " <menu action='menu-preview-quality'>"
871 " <menuitem action='quality-00' />"
872 " <menuitem action='quality-01' />"
873 " <menuitem action='quality-02' />"
874 " <menuitem action='quality-03' />"
875 " <menuitem action='quality-04' />"
876 " <menuitem action='quality-05' />"
877 " <menuitem action='quality-06' />"
878 " <menuitem action='quality-07' />"
879 " <menuitem action='quality-08' />"
880 " <menuitem action='quality-09' />"
881 " <menuitem action='quality-10' />"
883 " <separator name='bleh08'/>"
884 " <menuitem action='play'/>"
885 " <menuitem action='pause'/>"
886 " <menuitem action='stop'/>"
887 " <menuitem action='dialog-flipbook'/>"
888 " <separator name='bleh09'/>"
889 " <menuitem action='toggle-grid-show'/>"
890 " <menuitem action='toggle-grid-snap'/>"
891 " <menuitem action='toggle-guide-show'/>"
892 " <menuitem action='toggle-low-res'/>"
893 " <menuitem action='toggle-onion-skin'/>"
894 " <separator name='bleh10'/>"
895 " <menuitem action='canvas-zoom-in'/>"
896 " <menuitem action='canvas-zoom-out'/>"
897 " <menuitem action='canvas-zoom-fit'/>"
898 " <menuitem action='canvas-zoom-100'/>"
899 " <separator name='bleh11'/>"
900 " <menuitem action='time-zoom-in'/>"
901 " <menuitem action='time-zoom-out'/>"
902 " <separator name='bleh12'/>"
903 " <menuitem action='jump-next-keyframe'/>"
904 " <menuitem action='jump-prev-keyframe'/>"
905 " <menuitem action='seek-next-frame'/>"
906 " <menuitem action='seek-prev-frame'/>"
907 " <menuitem action='seek-next-second'/>"
908 " <menuitem action='seek-prev-second'/>"
909 " <menuitem action='seek-begin'/>"
910 " <menuitem action='seek-end'/>"
912 " <menu action='menu-canvas'>"
913 " <menuitem action='canvas-new'/>"
914 " <menuitem action='amount-inc'/>"
915 " <menuitem action='amount-dec'/>"
917 " <menu name='menu-state' action='menu-state'>"
919 " <menu action='menu-group'>"
920 " <menuitem action='action-group_add'/>"
922 " <menu action='menu-layer'>"
923 //" <menuitem action='cut'/>"
924 //" <menuitem action='copy'/>"
925 //" <menuitem action='paste'/>"
926 //" <separator name='bleh06'/>"
927 " <menu action='menu-layer-new'></menu>"
929 " <menu action='menu-keyframe'>"
930 " <menuitem action='keyframe-properties'/>"
937 " <menubar name='MenuBar'>"
938 " <menu action='MenuFile'>"
939 " <menuitem action='New'/>"
940 " <menuitem action='Open'/>"
942 " <menuitem action='Quit'/>"
944 " <menu action='MenuEdit'>"
945 " <menuitem action='Cut'/>"
946 " <menuitem action='Copy'/>"
947 " <menuitem action='Paste'/>"
950 " <toolbar name='ToolBar'>"
951 " <toolitem action='Open'/>"
952 " <toolitem action='Quit'/>"
958 actions_action_group->set_sensitive(false);
959 App::ui_manager()->set_add_tearoffs(true);
960 App::ui_manager()->insert_action_group(menus_action_group,1);
961 App::ui_manager()->insert_action_group(actions_action_group,1);
962 App::ui_manager()->add_ui_from_string(ui_info);
964 //App::ui_manager()->get_accel_group()->unlock();
966 catch(const Glib::Error& ex)
968 synfig::error("building menus and toolbars failed: " + ex.what());
971 // Add default keyboard accelerators
972 #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()); }
973 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
974 ACCEL("<Actions>//select-all-ducks","<Control>a");
975 ACCEL("<Actions>//unselect-all-layers","<Control>d");
976 ACCEL("<Actions>//render","F9");
977 ACCEL("<Actions>//preview","F11");
978 ACCEL("<Actions>//properties","F8");
979 ACCEL("<Actions>//options","F12");
980 ACCEL("<Actions>//import","<control>i");
981 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
982 ACCEL("<Actions>//toggle-grid-show","<Control>g");
983 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
984 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
985 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
986 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
987 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
988 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
989 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
990 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
993 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
994 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
996 ACCEL("<Actions>//quality-01","<Control>1");
997 ACCEL("<Actions>//quality-02","<Control>2");
998 ACCEL("<Actions>//quality-03","<Control>3");
999 ACCEL("<Actions>//quality-04","<Control>4");
1000 ACCEL("<Actions>//quality-05","<Control>5");
1001 ACCEL("<Actions>//quality-06","<Control>6");
1002 ACCEL("<Actions>//quality-07","<Control>7");
1003 ACCEL("<Actions>//quality-08","<Control>8");
1004 ACCEL("<Actions>//quality-09","<Control>9");
1005 ACCEL("<Actions>//quality-10","<Control>0");
1006 ACCEL("<Actions>//undo","<Control>z");
1007 ACCEL("<Actions>//redo","<Control>r");
1008 ACCEL("<Actions>//action-layer_remove","Delete");
1010 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1011 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1012 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1013 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1014 ACCEL("<Actions>//time-zoom-in","+");
1015 ACCEL("<Actions>//time-zoom-out","_");
1017 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1018 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1020 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1021 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1022 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1023 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1024 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1025 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1026 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1027 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1028 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1029 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1030 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1031 ACCEL("<Actions>//seek-begin","Home");
1032 ACCEL("<Actions>//seek-end","End");
1033 ACCEL("<Actions>//state-normal","<Mod1>a");
1034 ACCEL("<Actions>//state-rotate","<Mod1>s");
1035 ACCEL("<Actions>//state-scale","<Mod1>d");
1036 ACCEL("<Actions>//state-bline","<Mod1>b");
1037 ACCEL("<Actions>//state-fill","<Mod1>f");
1038 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1039 ACCEL("<Actions>//state-gradient","<Mod1>g");
1040 ACCEL("<Actions>//state-zoom","<Mod1>z");
1041 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1047 #define mkdir(x,y) mkdir(x)
1050 /* === M E T H O D S ======================================================= */
1052 App::App(int *argc, char ***argv):
1053 Gtk::Main(argc,argv),
1054 IconControler(etl::dirname((*argv)[0]))
1056 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1059 serial_=check_license(app_base_path_);
1062 ui_interface_=new GlobalUIInterface();
1066 Glib::thread_init();
1068 distance_system=Distance::SYSTEM_UNITS;
1070 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1073 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1077 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1085 if(!SYNFIG_CHECK_VERSION())
1087 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1088 dialog_error_blocking("SYNFIG Studio",
1089 "This copy of SYNFIG Studio was compiled against a\n"
1090 "different version of libsynfig than what is currently\n"
1091 "installed. Synfig Studio will now abort. Try downloading\n"
1092 "the latest version from the SYNFIG Development Website at\n"
1093 "http://dev.synfig.com/ "
1098 catch(synfig::SoftwareExpired)
1100 cerr<<"FATAL: Software Expired"<<endl;
1101 dialog_error_blocking("SYNFIG Studio",
1102 "This copy of SYNFIG Studio has expired.\n"
1103 "Please erase this copy, or download and\n"
1104 "install the latest copy from the SYNFIG\n"
1105 "Development Website at http://dev.synfig.com/ ."
1109 Glib::set_application_name(_("SYNFIG Studio"));
1112 about_window.set_can_self_destruct(false);
1113 about_window.show();
1115 shutdown_in_progress=false;
1116 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1117 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1119 // Initialize the Synfig library
1120 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1123 get_ui_interface()->error("Failed to initialize synfig!");
1127 // add the preferences to the settings
1128 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1132 studio_init_cb.task("Init UI Manager...");
1133 App::ui_manager_=studio::UIManager::create();
1136 studio_init_cb.task("Init Dock Manager...");
1137 dock_manager=new studio::DockManager();
1139 studio_init_cb.task("Init State Manager...");
1140 state_manager=new StateManager();
1142 studio_init_cb.task("Init Toolbox...");
1143 toolbox=new studio::Toolbox();
1145 studio_init_cb.task("Init Tool Options...");
1146 dialog_tool_options=new studio::Dialog_ToolOptions();
1147 dock_manager->register_dockable(*dialog_tool_options);
1149 studio_init_cb.task("Init History...");
1150 dock_history=new studio::Dock_History();
1151 dock_manager->register_dockable(*dock_history);
1153 studio_init_cb.task("Init Canvases...");
1154 dock_canvases=new studio::Dock_Canvases();
1155 dock_manager->register_dockable(*dock_canvases);
1157 studio_init_cb.task("Init Keyframes...");
1158 dock_keyframes=new studio::Dock_Keyframes();
1159 dock_manager->register_dockable(*dock_keyframes);
1161 studio_init_cb.task("Init Layers...");
1162 dock_layers=new studio::Dock_Layers();
1163 dock_manager->register_dockable(*dock_layers);
1165 studio_init_cb.task("Init Params...");
1166 dock_params=new studio::Dock_Params();
1167 dock_manager->register_dockable(*dock_params);
1169 studio_init_cb.task("Init MetaData...");
1170 dock_meta_data=new studio::Dock_MetaData();
1171 dock_manager->register_dockable(*dock_meta_data);
1173 studio_init_cb.task("Init Children...");
1174 dock_children=new studio::Dock_Children();
1175 dock_manager->register_dockable(*dock_children);
1177 studio_init_cb.task("Init Info...");
1178 dock_info = new studio::Dock_Info();
1179 dock_manager->register_dockable(*dock_info);
1181 studio_init_cb.task("Init Navigator...");
1182 dock_navigator = new studio::Dock_Navigator();
1183 dock_manager->register_dockable(*dock_navigator);
1185 studio_init_cb.task("Init Timetrack...");
1186 dock_timetrack = new studio::Dock_Timetrack();
1187 dock_manager->register_dockable(*dock_timetrack);
1189 studio_init_cb.task("Init Curve Editor...");
1190 dock_curves = new studio::Dock_Curves();
1191 dock_manager->register_dockable(*dock_curves);
1193 studio_init_cb.task("Init Layer Groups...");
1194 dock_layer_groups = new studio::Dock_LayerGroups();
1195 dock_manager->register_dockable(*dock_layer_groups);
1198 studio_init_cb.task("Init Color Dialog...");
1199 dialog_color=new studio::Dialog_Color();
1201 studio_init_cb.task("Init Gradient Dialog...");
1202 dialog_gradient=new studio::Dialog_Gradient();
1204 studio_init_cb.task("Init DeviceTracker...");
1205 device_tracker=new studio::DeviceTracker();
1207 studio_init_cb.task("Init Tools...");
1208 state_manager->add_state(&state_normal);
1209 state_manager->add_state(&state_smooth_move);
1210 state_manager->add_state(&state_scale);
1211 state_manager->add_state(&state_rotate);
1213 state_manager->add_state(&state_bline);
1216 state_manager->add_state(&state_circle);
1217 state_manager->add_state(&state_rectangle);
1219 state_manager->add_state(&state_gradient);
1220 state_manager->add_state(&state_eyedrop);
1221 state_manager->add_state(&state_fill);
1223 state_manager->add_state(&state_zoom);
1226 // Disabled this tool because it should be
1227 // considered deprecated. Use the bline tool instead.
1228 state_manager->add_state(&state_polygon);
1230 // These tools are disabled for now,
1231 // because they tend to confuse users.
1232 state_manager->add_state(&state_draw);
1233 state_manager->add_state(&state_sketch);
1234 state_manager->add_state(&state_width);
1237 studio_init_cb.task("Init ModPalette...");
1238 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1240 studio_init_cb.task("Init ModMirror...");
1241 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1244 studio_init_cb.task("Init Setup Dialog...");
1245 dialog_setup=new studio::Dialog_Setup();
1247 studio_init_cb.task("Init Input Dialog...");
1248 dialog_input=new Gtk::InputDialog();
1250 studio_init_cb.task("Init auto recovery...");
1251 auto_recover=new AutoRecover();
1253 studio_init_cb.amount_complete(9250,10000);
1254 studio_init_cb.task("Loading Settings...");
1256 studio_init_cb.task("Checking auto-recover...");
1258 studio_init_cb.amount_complete(9900,10000);
1260 if(auto_recover->recovery_needed())
1262 about_window.hide();
1264 get_ui_interface()->yes_no(
1266 "SYNFIG Studio seems to have crashed\n"
1267 "before you could save all your files.\n"
1268 "Would you like to re-open those files\n"
1269 "and recover your unsaved changes?"
1270 )==synfigapp::UIInterface::RESPONSE_YES
1273 if(!auto_recover->recover())
1275 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1278 get_ui_interface()->error(
1279 _("SYNFIG Studio has attempted to recover\n"
1280 "from a previous crash. The files that it has\n"
1281 "recovered are NOT YET SAVED. It would be a good\n"
1282 "idea to review them and save them now.")
1285 about_window.show();
1288 // Look for any files given on the command line,
1289 // and load them if found.
1290 for(;*argc>=1;(*argc)--)
1291 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1293 studio_init_cb.task("Loading files...");
1294 about_window.hide();
1295 open((*argv)[*argc]);
1296 about_window.show();
1299 studio_init_cb.task("Done.");
1300 studio_init_cb.amount_complete(10000,10000);
1306 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1310 StateManager* App::get_state_manager() { return state_manager; }
1314 shutdown_in_progress=true;
1318 synfigapp::Main::settings().remove_domain("pref");
1320 selected_instance=0;
1322 // Unload all of the modules
1323 for(;!module_list_.empty();module_list_.pop_back());
1325 delete state_manager;
1329 delete auto_recover;
1333 // studio::App::iteration(false);
1337 // studio::App::iteration(false);
1339 // studio::App::iteration(false);
1341 delete dialog_setup;
1343 delete dialog_gradient;
1345 delete dialog_color;
1347 delete dialog_input;
1349 delete dock_manager;
1351 instance_list.clear();
1353 // studio::App::iteration(false);
1357 App::get_user_app_directory()
1359 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1363 App::get_config_file(const synfig::String& file)
1365 return Glib::build_filename(get_user_app_directory(),file);
1369 App::add_recent_file(const std::string &file_name)
1371 std::string filename(file_name);
1373 assert(!filename.empty());
1375 if(filename.empty())
1378 // Toss out any "hidden" files
1379 if(basename(filename)[0]=='.')
1382 // If we aren't an absolute path, turn outselves into one
1383 if(!is_absolute_path(filename))
1384 filename=absolute_path(filename);
1386 list<string>::iterator iter;
1387 // Check to see if the file is already on the list.
1388 // If it is, then remove it from the list
1389 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1392 recent_files.erase(iter);
1397 // Push the filename to the front of the list
1398 recent_files.push_front(filename);
1400 // Clean out the files at the end of the list.
1401 while(recent_files.size()>(unsigned)get_max_recent_files())
1402 recent_files.pop_back();
1404 signal_recent_files_changed_();
1409 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1412 App::get_time_format()
1414 return _App_time_format;
1418 App::set_time_format(synfig::Time::Format x)
1425 App::save_settings()
1430 std::string filename=get_config_file("accelrc");
1431 Gtk::AccelMap::save(filename);
1434 std::string filename=get_config_file("recentfiles");
1436 std::ofstream file(filename.c_str());
1440 synfig::warning("Unable to save %s",filename.c_str());
1444 list<string>::reverse_iterator iter;
1446 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1450 std::string filename=get_config_file("settings");
1451 synfigapp::Main::settings().save_to_file(filename);
1455 synfig::warning("Caught exception when attempting to save settings.");
1460 App::load_settings()
1465 std::string filename=get_config_file("accelrc");
1466 Gtk::AccelMap::load(filename);
1469 std::string filename=get_config_file("recentfiles");
1471 std::ifstream file(filename.c_str());
1475 std::string recent_file;
1476 getline(file,recent_file);
1477 if(!recent_file.empty())
1478 add_recent_file(recent_file);
1481 std::string filename=get_config_file("settings");
1482 if(!synfigapp::Main::settings().load_from_file(filename))
1484 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1485 //if(!synfigapp::Main::settings().load_from_file(filename))
1487 gamma.set_gamma(1.0/2.2);
1488 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1489 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1490 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1491 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1492 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1493 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1494 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1495 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1496 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1497 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1498 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1499 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1500 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1507 synfig::warning("Caught exception when attempting to load settings.");
1512 App::shutdown_request(GdkEventAny*)
1516 //return !shutdown_in_progress;
1522 if(shutdown_in_progress)return;
1525 get_ui_interface()->task("Quit Request");
1528 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1532 std::list<etl::handle<Instance> >::iterator iter;
1533 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1535 if(!(*iter)->safe_close())
1539 if((*iter)->synfigapp::Instance::get_action_count())
1541 handle<synfigapp::UIInterface> uim;
1542 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1544 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1545 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1547 case synfigapp::UIInterface::RESPONSE_NO:
1549 case synfigapp::UIInterface::RESPONSE_YES:
1552 case synfigapp::UIInterface::RESPONSE_CANCEL:
1561 if((*iter)->synfigapp::Instance::is_modified())
1563 handle<synfigapp::UIInterface> uim;
1564 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1566 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() );
1567 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1569 case synfigapp::UIInterface::RESPONSE_NO:
1571 case synfigapp::UIInterface::RESPONSE_YES:
1572 (*iter)->dialog_cvs_commit();
1574 case synfigapp::UIInterface::RESPONSE_CANCEL:
1583 // This next line causes things to crash for some reason
1587 shutdown_in_progress=true;
1589 instance_list.clear();
1591 while(studio::App::events_pending())studio::App::iteration(false);
1594 auto_recover->normal_shutdown();
1596 get_ui_interface()->task("Quit Request sent");
1602 dialog_setup->refresh();
1603 dialog_setup->show();
1606 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1607 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1610 //#define USE_WIN32_FILE_DIALOGS 1
1613 #ifdef USE_WIN32_FILE_DIALOGS
1614 static OPENFILENAME ofn={};
1618 #include <gdk/gdkwin32.h>
1622 App::dialog_open_file(const std::string &title, std::string &filename)
1624 #ifdef USE_WIN32_FILE_DIALOGS
1625 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1627 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1628 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1629 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1631 ofn.lStructSize=sizeof(OPENFILENAME);
1632 ofn.hwndOwner = hWnd;
1633 ofn.hInstance = hInstance;
1634 ofn.lpstrFilter = szFilter;
1635 // ofn.lpstrCustomFilter=NULL;
1636 // ofn.nMaxCustFilter=0;
1637 // ofn.nFilterIndex=0;
1638 // ofn.lpstrFile=NULL;
1639 ofn.nMaxFile=MAX_PATH;
1640 // ofn.lpstrFileTitle=NULL;
1641 // ofn.lpstrInitialDir=NULL;
1642 // ofn.lpstrTitle=NULL;
1643 ofn.Flags=OFN_HIDEREADONLY;
1644 // ofn.nFileOffset=0;
1645 // ofn.nFileExtension=0;
1646 ofn.lpstrDefExt=TEXT("sif");
1647 // ofn.lCustData = 0l;
1649 // ofn.lpTemplateName=NULL;
1651 CHAR szFilename[MAX_PATH];
1653 strcpy(szFilename,filename.c_str());
1654 strcpy(szTitle,title.c_str());
1656 ofn.lpstrFile=szFilename;
1657 ofn.lpstrFileTitle=szTitle;
1659 if(GetOpenFileName(&ofn))
1661 filename=szFilename;
1667 synfig::String prev_path;
1668 if(!_preferences.get_value("curr_path",prev_path))
1671 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1672 dialog->set_current_folder(prev_path);
1673 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1674 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1675 if(!filename.empty())
1676 dialog->set_filename(filename);
1677 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1678 filename=dialog->get_filename();
1690 GtkWidget *fileselection;
1691 fileselection = gtk_file_selection_new(title.c_str());
1694 if(basename(filename)==filename)
1696 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1699 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1701 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1703 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1704 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1706 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1707 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1709 gtk_widget_show(fileselection);
1717 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1718 _preferences.set_value("curr_path",dirname(filename));
1722 gtk_widget_destroy(fileselection);
1725 gtk_widget_destroy(fileselection);
1732 App::dialog_save_file(const std::string &title, std::string &filename)
1734 #ifdef USE_WIN32_FILE_DIALOGS
1735 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1737 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1738 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1739 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1741 ofn.lStructSize=sizeof(OPENFILENAME);
1742 ofn.hwndOwner = hWnd;
1743 ofn.hInstance = hInstance;
1744 ofn.lpstrFilter = szFilter;
1745 // ofn.lpstrCustomFilter=NULL;
1746 // ofn.nMaxCustFilter=0;
1747 // ofn.nFilterIndex=0;
1748 // ofn.lpstrFile=NULL;
1749 ofn.nMaxFile=MAX_PATH;
1750 // ofn.lpstrFileTitle=NULL;
1751 // ofn.lpstrInitialDir=NULL;
1752 // ofn.lpstrTitle=NULL;
1753 ofn.Flags=OFN_OVERWRITEPROMPT;
1754 // ofn.nFileOffset=0;
1755 // ofn.nFileExtension=0;
1756 ofn.lpstrDefExt=TEXT("sif");
1757 // ofn.lCustData = 0l;
1759 // ofn.lpTemplateName=NULL;
1761 CHAR szFilename[MAX_PATH];
1763 strcpy(szFilename,filename.c_str());
1764 strcpy(szTitle,title.c_str());
1766 ofn.lpstrFile=szFilename;
1767 ofn.lpstrFileTitle=szTitle;
1769 if(GetSaveFileName(&ofn))
1771 filename=szFilename;
1776 synfig::String prev_path;
1777 if(!_preferences.get_value("curr_path",prev_path))
1780 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1781 dialog->set_current_folder(prev_path);
1782 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1783 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1784 if(!filename.empty())
1785 dialog->set_filename(filename);
1786 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1787 filename=dialog->get_filename();
1793 // return dialog_open_file(title, filename);
1798 App::dialog_saveas_file(const std::string &title, std::string &filename)
1800 #if USE_WIN32_FILE_DIALOGS
1801 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1803 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1804 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1805 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1807 ofn.lStructSize=sizeof(OPENFILENAME);
1808 ofn.hwndOwner = hWnd;
1809 ofn.hInstance = hInstance;
1810 ofn.lpstrFilter = szFilter;
1811 // ofn.lpstrCustomFilter=NULL;
1812 // ofn.nMaxCustFilter=0;
1813 // ofn.nFilterIndex=0;
1814 // ofn.lpstrFile=NULL;
1815 ofn.nMaxFile=MAX_PATH;
1816 // ofn.lpstrFileTitle=NULL;
1817 // ofn.lpstrInitialDir=NULL;
1818 // ofn.lpstrTitle=NULL;
1819 ofn.Flags=OFN_OVERWRITEPROMPT;
1820 // ofn.nFileOffset=0;
1821 // ofn.nFileExtension=0;
1822 ofn.lpstrDefExt=TEXT("sif");
1823 // ofn.lCustData = 0l;
1825 // ofn.lpTemplateName=NULL;
1827 CHAR szFilename[MAX_PATH];
1829 strcpy(szFilename,filename.c_str());
1830 strcpy(szTitle,title.c_str());
1832 ofn.lpstrFile=szFilename;
1833 ofn.lpstrFileTitle=szTitle;
1835 if(GetSaveFileName(&ofn))
1837 filename=szFilename;
1842 synfig::String prev_path;
1843 if(!_preferences.get_value("curr_path",prev_path))
1846 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1847 dialog->set_current_folder(prev_path);
1848 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1849 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1850 if(!filename.empty())
1851 dialog->set_filename(filename);
1852 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1853 filename=dialog->get_filename();
1859 // return dialog_open_file(title, filename);
1864 App::dialog_error_blocking(const std::string &title, const std::string &message)
1869 true // use_separator
1871 Gtk::Label label(message);
1874 dialog.get_vbox()->pack_start(label);
1875 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1881 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1886 true // use_separator
1888 Gtk::Label label(message);
1891 dialog.get_vbox()->pack_start(label);
1892 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1898 App::dialog_yes_no(const std::string &title, const std::string &message)
1903 true // use_separator
1905 Gtk::Label label(message);
1908 dialog.get_vbox()->pack_start(label);
1909 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1910 dialog.add_button(Gtk::StockID("gtk-no"),0);
1912 return dialog.run();
1916 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1921 true // use_separator
1923 Gtk::Label label(message);
1926 dialog.get_vbox()->pack_start(label);
1927 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1928 dialog.add_button(Gtk::StockID("gtk-no"),0);
1929 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1931 return dialog.run();
1935 App::dialog_not_implemented()
1938 "Feature not available", // Title
1940 true // use_separator
1942 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1945 dialog.get_vbox()->pack_start(label);
1946 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1952 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1957 true // use_separator
1959 Gtk::Label label(message);
1961 dialog.get_vbox()->pack_start(label);
1964 entry.set_text(text);
1966 entry.set_activates_default(true);
1967 dialog.get_vbox()->pack_start(entry);
1969 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1970 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1971 dialog.set_default_response(Gtk::RESPONSE_OK);
1972 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1975 if(dialog.run()!=Gtk::RESPONSE_OK)
1978 text=entry.get_text();
1987 App::open(std::string filename)
1989 return open_as(filename,filename);
1993 App::open_as(std::string filename,std::string as)
1996 char long_name[1024];
1997 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2003 OneMoment one_moment;
2005 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2006 if(canvas && get_instance(canvas))
2008 get_instance(canvas)->find_canvas_view(canvas)->present();
2009 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2012 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2014 add_recent_file(as);
2016 handle<Instance> instance(Instance::create(canvas));
2019 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2023 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)")))
2024 instance->dialog_cvs_update();
2028 dialog_error_blocking(_("Error"), x);
2033 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2037 _preferences.set_value("curr_path",dirname(as));
2046 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2047 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2049 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2051 canvas->rend_desc().set_frame_rate(24.0);
2052 canvas->rend_desc().set_time_start(0.0);
2053 canvas->rend_desc().set_time_end(00.0);
2054 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2055 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2056 canvas->rend_desc().set_tl(Vector(-4,2.25));
2057 canvas->rend_desc().set_br(Vector(4,-2.25));
2058 canvas->rend_desc().set_w(480);
2059 canvas->rend_desc().set_h(270);
2060 canvas->rend_desc().set_antialias(1);
2061 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2062 canvas->set_file_name(file_name);
2064 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2070 string filename="*.sif";
2072 while(dialog_open_file("Open", filename))
2074 // If the filename still has wildcards, then we should
2075 // continue looking for the file we want
2076 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2082 get_ui_interface()->error(_("Unable to open file"));
2087 App::set_selected_instance(etl::loose_handle<Instance> instance)
2089 /* if(get_selected_instance()==instance)
2091 selected_instance=instance;
2092 signal_instance_selected()(instance);
2098 selected_instance=instance;
2099 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2103 instance->focus(instance->get_canvas());
2106 set_selected_canvas_view(0);
2108 signal_instance_selected()(instance);
2112 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2114 selected_canvas_view=canvas_view;
2115 signal_canvas_view_focus()(selected_canvas_view);
2118 selected_instance=canvas_view->get_instance();
2119 signal_instance_selected()(canvas_view->get_instance());
2122 if(get_selected_canvas_view()==canvas_view)
2124 signal_canvas_view_focus()(selected_canvas_view);
2125 signal_instance_selected()(canvas_view->get_instance());
2128 selected_canvas_view=canvas_view;
2129 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2130 set_selected_instance(canvas_view->get_instance());
2131 signal_canvas_view_focus()(selected_canvas_view);
2135 etl::loose_handle<Instance>
2136 App::get_instance(Canvas::Handle canvas)
2138 if(!canvas) return 0;
2139 canvas=canvas->get_root();
2141 std::list<etl::handle<Instance> >::iterator iter;
2142 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2144 if((*iter)->get_canvas()==canvas)
2153 (new class About())->show();
2159 if(selected_instance)
2160 selected_instance->undo();
2166 if(selected_instance)
2167 selected_instance->redo();
2171 studio::App::get_base_path()
2173 return app_base_path_;