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 ======================================================= */
36 #ifdef HAVE_SYS_ERRNO_H
37 #include <sys/errno.h>
39 #include <gtkmm/fileselection.h>
40 #include <gtkmm/dialog.h>
41 #include <gtkmm/label.h>
42 #include <gtkmm/stock.h>
43 #include <gtkmm/stockitem.h>
44 #include <gtkmm/iconsource.h>
45 #include <gtkmm/inputdialog.h>
46 #include <gtkmm/accelmap.h>
47 #include <gtkmm/uimanager.h>
51 #include <synfig/loadcanvas.h>
56 #include "canvasview.h"
57 #include "dialog_setup.h"
58 #include "dialog_gradient.h"
59 #include "dialog_color.h"
62 #include "onemoment.h"
64 #include "dockmanager.h"
66 #include "state_eyedrop.h"
67 #include "state_normal.h"
68 #include "state_draw.h"
69 #include "state_fill.h"
70 #include "state_bline.h"
71 #include "state_polygon.h"
72 #include "state_sketch.h"
73 #include "state_gradient.h"
74 #include "state_circle.h"
75 #include "state_rectangle.h"
76 #include "state_smoothmove.h"
77 #include "state_scale.h"
78 #include "state_width.h"
79 #include "state_rotate.h"
80 #include "state_zoom.h"
82 #include "devicetracker.h"
83 #include "dialog_tooloptions.h"
85 #include "autorecover.h"
87 #include <synfigapp/settings.h>
88 #include "dock_history.h"
89 #include "dock_canvases.h"
90 #include "dock_keyframes.h"
91 #include "dock_layers.h"
92 #include "dock_params.h"
93 #include "dock_metadata.h"
94 #include "dock_children.h"
95 #include "dock_info.h"
96 #include "dock_navigator.h"
97 #include "dock_layergroups.h"
98 #include "dock_timetrack.h"
99 #include "dock_curves.h"
101 #include "mod_palette/mod_palette.h"
102 #include "mod_mirror/mod_mirror.h"
104 #include <sys/stat.h>
110 #include "statemanager.h"
117 #define _WIN32_WINNT 0x0500
120 #include <gtkmm/accelmap.h>
121 #include <gtkmm/filechooser.h>
122 #include <gtkmm/filechooserdialog.h>
126 /* === U S I N G =========================================================== */
130 using namespace synfig;
131 using namespace studio;
133 /* === M A C R O S ========================================================= */
135 #ifndef SYNFIG_USER_APP_DIR
137 #define SYNFIG_USER_APP_DIR "Library/Synfig"
139 #define SYNFIG_USER_APP_DIR "Synfig"
144 #define DPM2DPI(x) (float(x)/39.3700787402f)
145 #define DPI2DPM(x) (float(x)*39.3700787402f)
151 # define IMAGE_DIR "share\\pixmaps"
156 # define IMAGE_DIR "/usr/local/share/pixmaps"
160 # define IMAGE_EXT "tif"
163 #include <synfigapp/main.h>
165 /* === S I G N A L S ======================================================= */
167 static sigc::signal<void> signal_present_all_;
169 App::signal_present_all() { return signal_present_all_; }
171 static sigc::signal<void> signal_recent_files_changed_;
173 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
175 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
176 sigc::signal<void,etl::loose_handle<CanvasView> >&
177 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
179 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
180 sigc::signal<void,etl::handle<Instance> >&
181 App::signal_instance_selected() { return signal_instance_selected_; }
183 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
184 sigc::signal<void,etl::handle<Instance> >&
185 App::signal_instance_created() { return signal_instance_created_; }
187 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
188 sigc::signal<void,etl::handle<Instance> >&
189 App::signal_instance_deleted() { return signal_instance_deleted_; }
191 /* === G L O B A L S ======================================================= */
193 static std::list<std::string> recent_files;
194 const std::list<std::string>& App::get_recent_files() { return recent_files; }
196 int App::Busy::count;
197 bool App::shutdown_in_progress;
199 synfig::Gamma App::gamma;
201 Glib::RefPtr<studio::UIManager> App::ui_manager_;
203 synfig::Distance::System App::distance_system;
205 studio::Dialog_Setup* App::dialog_setup;
207 etl::handle< studio::ModPalette > mod_palette_;
208 //studio::Dialog_Palette* App::dialog_palette;
210 std::list<etl::handle<Instance> > App::instance_list;
212 static etl::handle<synfigapp::UIInterface> ui_interface_;
213 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
215 etl::handle<Instance> App::selected_instance;
216 etl::handle<CanvasView> App::selected_canvas_view;
218 studio::Toolbox *studio::App::toolbox=NULL;
220 studio::AutoRecover *studio::App::auto_recover=NULL;
222 studio::IPC *ipc=NULL;
224 studio::DockManager* studio::App::dock_manager=0;
226 studio::DeviceTracker* studio::App::device_tracker=0;
228 studio::Dialog_Gradient* studio::App::dialog_gradient;
230 studio::Dialog_Color* studio::App::dialog_color;
232 Gtk::InputDialog* studio::App::dialog_input;
234 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
236 studio::Dock_History* dock_history;
237 studio::Dock_Canvases* dock_canvases;
238 studio::Dock_Keyframes* dock_keyframes;
239 studio::Dock_Layers* dock_layers;
240 studio::Dock_Params* dock_params;
241 studio::Dock_MetaData* dock_meta_data;
242 studio::Dock_Children* dock_children;
243 studio::Dock_Info* dock_info;
244 studio::Dock_LayerGroups* dock_layer_groups;
245 studio::Dock_Navigator* dock_navigator;
246 studio::Dock_Timetrack* dock_timetrack;
247 studio::Dock_Curves* dock_curves;
249 std::list< etl::handle< studio::Module > > module_list_;
251 bool studio::App::use_colorspace_gamma=true;
253 static int max_recent_files_=25;
254 int studio::App::get_max_recent_files() { return max_recent_files_; }
255 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
257 static synfig::String app_base_path_;
260 }; // END of namespace studio
261 studio::StateManager* state_manager;
266 class GlobalUIInterface : public synfigapp::UIInterface
270 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
275 true // use_separator
277 Gtk::Label label(message);
280 dialog.get_vbox()->pack_start(label);
281 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
282 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
284 dialog.set_default_response(dflt);
286 return (Response)dialog.run();
288 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
293 true // use_separator
295 Gtk::Label label(message);
298 dialog.get_vbox()->pack_start(label);
299 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
300 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
301 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
303 dialog.set_default_response(dflt);
305 return (Response)dialog.run();
307 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
312 true // use_separator
314 Gtk::Label label(message);
317 dialog.get_vbox()->pack_start(label);
318 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
319 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
321 dialog.set_default_response(dflt);
323 return (Response)dialog.run();
327 task(const std::string &task)
329 std::cerr<<task<<std::endl;
330 while(studio::App::events_pending())studio::App::iteration(false);
335 error(const std::string &err)
340 true // use_separator
342 Gtk::Label label(err);
345 dialog.get_vbox()->pack_start(label);
346 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
353 warning(const std::string &err)
355 std::cerr<<"warning: "<<err<<std::endl;
356 while(studio::App::events_pending())studio::App::iteration(false);
361 amount_complete(int current, int total)
363 while(studio::App::events_pending())studio::App::iteration(false);
368 /* === P R O C E D U R E S ================================================= */
370 typedef unsigned char U8;
371 typedef unsigned short U16;
372 typedef unsigned long U32;
382 static inline U32 hash_U32(U32 i)
384 i=i*1664525+1013904223;
385 i=i*1664525+1013904223;
386 i=i*1664525+1013904223;
391 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
392 #define endian_fix(x) (endian_fix_table[x])
394 #define endian_fix(x) (x)
397 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
400 unwound->element.serial=0;
401 unwound->element.checksum=0;
409 case '0': data=0; break;
410 case '1': data=1; break;
411 case '2': data=2; break;
412 case '3': data=3; break;
413 case '4': data=4; break;
414 case '5': data=5; break;
415 case '6': data=6; break;
416 case '7': data=7; break;
417 case '8': data=8; break;
418 case '9': data=9; break;
419 case 'a': case 'A': data=10; break;
420 case 'b': case 'B': data=11; break;
421 case 'c': case 'C': data=12; break;
422 case 'd': case 'D': data=13; break;
423 case 'e': case 'E': data=14; break;
424 case 'f': case 'F': data=15; break;
425 default: return 0; break;
428 unwound->element.checksum|=(((U32)data&3)<<bit);
429 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
434 int v_key_check(const char* key, U32* serial, U32 appid)
436 V_KeyUnwound unwound_key;
437 U32 appid_mask_a=hash_U32(appid);
438 U32 appid_mask_b=hash_U32(appid_mask_a);
440 if(!v_unwind_key(&unwound_key, key))
442 // Invalid characters in key
447 // Undo obfuscation pass
449 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
454 unwound_key.raw[endian_fix(i)]^=(next>>24);
458 unwound_key.element.serial^=appid_mask_a;
459 unwound_key.element.checksum^=appid_mask_b;
461 *serial=unwound_key.element.serial;
463 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
467 int check_license(String basedir)
469 #ifdef LICENSE_KEY_REQUIRED
474 license_file="/usr/local/etc/.synfiglicense";
476 license_file=basedir+"\\etc\\.synfiglicense";
480 key=Glib::file_get_contents(license_file);
481 } catch (Glib::FileError) { }
483 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
485 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
489 if(!App::dialog_entry(
490 _("Synfig Studio Authentication"),
491 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
494 throw String("No License");
497 FILE* file=fopen(license_file.c_str(),"w");
500 fprintf(file,"%s",key.c_str());
504 synfig::error("Unable to save license key!");
506 synfig::info("License Authenticated -- Serial #%05d",serial);
515 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
517 action_group_list.push_back(action_group);
518 Gtk::UIManager::insert_action_group(action_group, pos);
522 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
524 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
525 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
526 if(*iter==action_group)
528 action_group_list.erase(iter);
529 Gtk::UIManager::remove_action_group(action_group);
532 synfig::error("Unable to find action group");
536 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
538 ui_manager->insert_action_group(group,0);
541 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
542 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
545 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
548 if(*iter && (*iter)->get_name()!="menus")
550 synfig::info("Removing action group "+(*iter)->get_name());
551 ui_manager->remove_action_group(*iter);
555 ui_manager->insert_action_group(group,0);
558 for(;!prev_groups.empty();prev_groups.pop_front())
560 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
561 ui_manager->insert_action_group(prev_groups.front(),1);
566 class Preferences : public synfigapp::Settings
569 virtual bool get_value(const synfig::String& key, synfig::String& value)const
573 value=strprintf("%f %f %f %f",
574 App::gamma.get_gamma_r(),
575 App::gamma.get_gamma_g(),
576 App::gamma.get_gamma_b(),
577 App::gamma.get_black_level()
581 if(key=="time_format")
583 value=strprintf("%i",App::get_time_format());
586 if(key=="file_history.size")
588 value=strprintf("%i",App::get_max_recent_files());
591 if(key=="use_colorspace_gamma")
593 value=strprintf("%i",(int)App::use_colorspace_gamma);
596 if(key=="distance_system")
598 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
601 if(key=="auto_recover_backup_interval")
603 value=strprintf("%i",App::auto_recover->get_timeout());
607 return synfigapp::Settings::get_value(key,value);
610 virtual bool set_value(const synfig::String& key,const synfig::String& value)
616 strscanf(value,"%f %f %f %f",
623 App::gamma.set_all(r,g,b,blk);
627 if(key=="time_format")
629 int i(atoi(value.c_str()));
630 App::set_time_format(static_cast<synfig::Time::Format>(i));
633 if(key=="auto_recover_backup_interval")
635 int i(atoi(value.c_str()));
636 App::auto_recover->set_timeout(i);
639 if(key=="file_history.size")
641 int i(atoi(value.c_str()));
642 App::set_max_recent_files(i);
645 if(key=="use_colorspace_gamma")
647 int i(atoi(value.c_str()));
648 App::use_colorspace_gamma=i;
651 if(key=="distance_system")
653 App::distance_system=Distance::ident_system(value);;
657 return synfigapp::Settings::set_value(key,value);
660 virtual KeyList get_key_list()const
662 KeyList ret(synfigapp::Settings::get_key_list());
663 ret.push_back("gamma");
664 ret.push_back("time_format");
665 ret.push_back("distance_system");
666 ret.push_back("file_history.size");
667 ret.push_back("use_colorspace_gamma");
668 ret.push_back("auto_recover_backup_interval");
673 static ::Preferences _preferences;
678 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
680 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
682 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
684 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
685 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
686 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
687 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
688 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
689 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Show/Hide Ducks") );
690 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
691 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
692 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
693 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
694 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
695 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
697 // Add the synfigapp actions...
698 synfigapp::Action::Book::iterator iter;
699 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
701 actions_action_group->add(Gtk::Action::create(
702 "action-"+iter->second.name,
703 get_action_stock_id(iter->second),
704 iter->second.local_name,iter->second.local_name
708 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
709 #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); }
710 #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); }
712 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
713 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
714 DEFINE_ACTION("open", Gtk::Stock::OPEN);
715 DEFINE_ACTION("save", Gtk::Stock::SAVE);
716 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
717 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
718 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
719 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
720 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
721 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
722 DEFINE_ACTION("import", _("Import"));
723 DEFINE_ACTION("render", _("Render"));
724 DEFINE_ACTION("preview", _("Preview"));
725 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
726 DEFINE_ACTION("sound", _("Sound File"));
727 DEFINE_ACTION("options", _("Options"));
728 DEFINE_ACTION("close", _("Close"));
731 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
732 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
733 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
734 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
735 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
736 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
737 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
738 DEFINE_ACTION("properties", _("Properties"));
740 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
741 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
742 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
743 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
744 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
745 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
746 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
747 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
748 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
749 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
750 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
751 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
752 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
753 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
754 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
755 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
756 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
757 DEFINE_ACTION("play", _("Play"));
758 DEFINE_ACTION("pause", _("Pause"));
759 DEFINE_ACTION("stop", _("Stop"));
760 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
761 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
762 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
763 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
764 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
765 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
766 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
767 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
768 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
769 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
770 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
771 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
772 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
773 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
774 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
775 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
776 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
777 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
778 DEFINE_ACTION("seek-end", _("Seek to End"));
780 DEFINE_ACTION("action-group_add", _("Add group"));
782 DEFINE_ACTION("canvas-new", _("New Canvas"));
784 DEFINE_ACTION("amount-inc", _("Increase Amount"));
785 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
790 // Set up synfigapp actions
792 synfigapp::Action::Book::iterator iter;
794 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
796 Gtk::StockID stock_id;
798 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
800 //Gtk::Image* image(manage(new Gtk::Image()));
801 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
802 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
803 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
804 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
805 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
806 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
807 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
808 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
809 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
810 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
812 actions_action_group->add(Gtk::Action::create(
813 "action-"+iter->second.name,
815 iter->second.local_name,iter->second.local_name
823 Glib::ustring ui_info =
825 " <popup name='menu-toolbox' action='menu-toolbox'>"
826 " <menu action='menu-file'>"
829 " <popup name='menu-main' action='menu-main'>"
830 " <menu action='menu-file'>"
831 " <menuitem action='save' />"
832 " <menuitem action='save-as' />"
833 " <menuitem action='revert' />"
834 " <separator name='bleh01'/>"
835 " <menuitem action='cvs-add' />"
836 " <menuitem action='cvs-update' />"
837 " <menuitem action='cvs-commit' />"
838 " <menuitem action='cvs-revert' />"
839 " <separator name='bleh02'/>"
840 " <menuitem action='import' />"
841 " <separator name='bleh03'/>"
842 " <menuitem action='render' />"
843 " <menuitem action='preview' />"
844 " <menuitem action='sound' />"
845 " <separator name='bleh04'/>"
846 " <menuitem action='options' />"
847 " <menuitem action='close' />"
849 " <menu action='menu-edit'>"
850 " <menuitem action='undo'/>"
851 " <menuitem action='redo'/>"
852 " <separator name='bleh05'/>"
853 " <menuitem action='cut'/>"
854 " <menuitem action='copy'/>"
855 " <menuitem action='paste'/>"
856 " <separator name='bleh06'/>"
857 " <menuitem action='select-all-ducks'/>"
858 " <menuitem action='unselect-all-layers'/>"
859 " <separator name='bleh07'/>"
860 " <menuitem action='properties'/>"
862 " <menu action='menu-view'>"
863 " <menu action='menu-duck-mask'>"
864 " <menuitem action='mask-position-ducks' />"
865 " <menuitem action='mask-vertex-ducks' />"
866 " <menuitem action='mask-tangent-ducks' />"
867 " <menuitem action='mask-radius-ducks' />"
868 " <menuitem action='mask-width-ducks' />"
869 " <menuitem action='mask-angle-ducks' />"
871 " <menu action='menu-preview-quality'>"
872 " <menuitem action='quality-00' />"
873 " <menuitem action='quality-01' />"
874 " <menuitem action='quality-02' />"
875 " <menuitem action='quality-03' />"
876 " <menuitem action='quality-04' />"
877 " <menuitem action='quality-05' />"
878 " <menuitem action='quality-06' />"
879 " <menuitem action='quality-07' />"
880 " <menuitem action='quality-08' />"
881 " <menuitem action='quality-09' />"
882 " <menuitem action='quality-10' />"
884 " <separator name='bleh08'/>"
885 " <menuitem action='play'/>"
886 " <menuitem action='pause'/>"
887 " <menuitem action='stop'/>"
888 " <menuitem action='dialog-flipbook'/>"
889 " <separator name='bleh09'/>"
890 " <menuitem action='toggle-grid-show'/>"
891 " <menuitem action='toggle-grid-snap'/>"
892 " <menuitem action='toggle-guide-show'/>"
893 " <menuitem action='toggle-low-res'/>"
894 " <menuitem action='toggle-onion-skin'/>"
895 " <separator name='bleh10'/>"
896 " <menuitem action='canvas-zoom-in'/>"
897 " <menuitem action='canvas-zoom-out'/>"
898 " <menuitem action='canvas-zoom-fit'/>"
899 " <menuitem action='canvas-zoom-100'/>"
900 " <separator name='bleh11'/>"
901 " <menuitem action='time-zoom-in'/>"
902 " <menuitem action='time-zoom-out'/>"
903 " <separator name='bleh12'/>"
904 " <menuitem action='jump-next-keyframe'/>"
905 " <menuitem action='jump-prev-keyframe'/>"
906 " <menuitem action='seek-next-frame'/>"
907 " <menuitem action='seek-prev-frame'/>"
908 " <menuitem action='seek-next-second'/>"
909 " <menuitem action='seek-prev-second'/>"
910 " <menuitem action='seek-begin'/>"
911 " <menuitem action='seek-end'/>"
913 " <menu action='menu-canvas'>"
914 " <menuitem action='canvas-new'/>"
915 " <menuitem action='amount-inc'/>"
916 " <menuitem action='amount-dec'/>"
918 " <menu name='menu-state' action='menu-state'>"
920 " <menu action='menu-group'>"
921 " <menuitem action='action-group_add'/>"
923 " <menu action='menu-layer'>"
924 //" <menuitem action='cut'/>"
925 //" <menuitem action='copy'/>"
926 //" <menuitem action='paste'/>"
927 //" <separator name='bleh06'/>"
928 " <menu action='menu-layer-new'></menu>"
930 " <menu action='menu-keyframe'>"
931 " <menuitem action='keyframe-properties'/>"
938 " <menubar name='MenuBar'>"
939 " <menu action='MenuFile'>"
940 " <menuitem action='New'/>"
941 " <menuitem action='Open'/>"
943 " <menuitem action='Quit'/>"
945 " <menu action='MenuEdit'>"
946 " <menuitem action='Cut'/>"
947 " <menuitem action='Copy'/>"
948 " <menuitem action='Paste'/>"
951 " <toolbar name='ToolBar'>"
952 " <toolitem action='Open'/>"
953 " <toolitem action='Quit'/>"
959 actions_action_group->set_sensitive(false);
960 App::ui_manager()->set_add_tearoffs(true);
961 App::ui_manager()->insert_action_group(menus_action_group,1);
962 App::ui_manager()->insert_action_group(actions_action_group,1);
963 App::ui_manager()->add_ui_from_string(ui_info);
965 //App::ui_manager()->get_accel_group()->unlock();
967 catch(const Glib::Error& ex)
969 synfig::error("building menus and toolbars failed: " + ex.what());
972 // Add default keyboard accelerators
973 #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()); }
974 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
975 ACCEL("<Actions>//select-all-ducks","<Control>a");
976 ACCEL("<Actions>//unselect-all-layers","<Control>d");
977 ACCEL("<Actions>//render","F9");
978 ACCEL("<Actions>//preview","F11");
979 ACCEL("<Actions>//properties","F8");
980 ACCEL("<Actions>//options","F12");
981 ACCEL("<Actions>//import","<control>i");
982 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
983 ACCEL("<Actions>//toggle-grid-show","<Control>g");
984 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
985 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
986 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
987 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
988 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
989 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
990 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
991 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
994 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
995 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
997 ACCEL("<Actions>//quality-01","<Control>1");
998 ACCEL("<Actions>//quality-02","<Control>2");
999 ACCEL("<Actions>//quality-03","<Control>3");
1000 ACCEL("<Actions>//quality-04","<Control>4");
1001 ACCEL("<Actions>//quality-05","<Control>5");
1002 ACCEL("<Actions>//quality-06","<Control>6");
1003 ACCEL("<Actions>//quality-07","<Control>7");
1004 ACCEL("<Actions>//quality-08","<Control>8");
1005 ACCEL("<Actions>//quality-09","<Control>9");
1006 ACCEL("<Actions>//quality-10","<Control>0");
1007 ACCEL("<Actions>//undo","<Control>z");
1008 ACCEL("<Actions>//redo","<Control>r");
1009 ACCEL("<Actions>//action-layer_remove","Delete");
1011 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1012 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1013 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1014 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1015 ACCEL("<Actions>//time-zoom-in","+");
1016 ACCEL("<Actions>//time-zoom-out","_");
1018 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1019 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1021 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1022 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1023 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1024 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1025 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1026 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1027 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1028 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1029 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1030 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1031 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1032 ACCEL("<Actions>//seek-begin","Home");
1033 ACCEL("<Actions>//seek-end","End");
1034 ACCEL("<Actions>//state-normal","<Mod1>a");
1035 ACCEL("<Actions>//state-rotate","<Mod1>s");
1036 ACCEL("<Actions>//state-scale","<Mod1>d");
1037 ACCEL("<Actions>//state-bline","<Mod1>b");
1038 ACCEL("<Actions>//state-fill","<Mod1>f");
1039 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1040 ACCEL("<Actions>//state-gradient","<Mod1>g");
1041 ACCEL("<Actions>//state-zoom","<Mod1>z");
1042 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1048 #define mkdir(x,y) mkdir(x)
1051 /* === M E T H O D S ======================================================= */
1053 App::App(int *argc, char ***argv):
1054 Gtk::Main(argc,argv),
1055 IconControler(etl::dirname((*argv)[0]))
1057 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1060 serial_=check_license(app_base_path_);
1063 ui_interface_=new GlobalUIInterface();
1067 Glib::thread_init();
1069 distance_system=Distance::SYSTEM_UNITS;
1071 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1074 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1078 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1086 if(!SYNFIG_CHECK_VERSION())
1088 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1089 dialog_error_blocking("SYNFIG Studio",
1090 "This copy of SYNFIG Studio was compiled against a\n"
1091 "different version of libsynfig than what is currently\n"
1092 "installed. Synfig Studio will now abort. Try downloading\n"
1093 "the latest version from the SYNFIG Development Website at\n"
1094 "http://dev.synfig.com/ "
1099 catch(synfig::SoftwareExpired)
1101 cerr<<"FATAL: Software Expired"<<endl;
1102 dialog_error_blocking("SYNFIG Studio",
1103 "This copy of SYNFIG Studio has expired.\n"
1104 "Please erase this copy, or download and\n"
1105 "install the latest copy from the SYNFIG\n"
1106 "Development Website at http://dev.synfig.com/ ."
1110 Glib::set_application_name(_("SYNFIG Studio"));
1113 about_window.set_can_self_destruct(false);
1114 about_window.show();
1116 shutdown_in_progress=false;
1117 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1118 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1120 // Initialize the Synfig library
1121 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1124 get_ui_interface()->error("Failed to initialize synfig!");
1128 // add the preferences to the settings
1129 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1133 studio_init_cb.task("Init UI Manager...");
1134 App::ui_manager_=studio::UIManager::create();
1137 studio_init_cb.task("Init Dock Manager...");
1138 dock_manager=new studio::DockManager();
1140 studio_init_cb.task("Init State Manager...");
1141 state_manager=new StateManager();
1143 studio_init_cb.task("Init Toolbox...");
1144 toolbox=new studio::Toolbox();
1146 studio_init_cb.task("Init Tool Options...");
1147 dialog_tool_options=new studio::Dialog_ToolOptions();
1148 dock_manager->register_dockable(*dialog_tool_options);
1150 studio_init_cb.task("Init History...");
1151 dock_history=new studio::Dock_History();
1152 dock_manager->register_dockable(*dock_history);
1154 studio_init_cb.task("Init Canvases...");
1155 dock_canvases=new studio::Dock_Canvases();
1156 dock_manager->register_dockable(*dock_canvases);
1158 studio_init_cb.task("Init Keyframes...");
1159 dock_keyframes=new studio::Dock_Keyframes();
1160 dock_manager->register_dockable(*dock_keyframes);
1162 studio_init_cb.task("Init Layers...");
1163 dock_layers=new studio::Dock_Layers();
1164 dock_manager->register_dockable(*dock_layers);
1166 studio_init_cb.task("Init Params...");
1167 dock_params=new studio::Dock_Params();
1168 dock_manager->register_dockable(*dock_params);
1170 studio_init_cb.task("Init MetaData...");
1171 dock_meta_data=new studio::Dock_MetaData();
1172 dock_manager->register_dockable(*dock_meta_data);
1174 studio_init_cb.task("Init Children...");
1175 dock_children=new studio::Dock_Children();
1176 dock_manager->register_dockable(*dock_children);
1178 studio_init_cb.task("Init Info...");
1179 dock_info = new studio::Dock_Info();
1180 dock_manager->register_dockable(*dock_info);
1182 studio_init_cb.task("Init Navigator...");
1183 dock_navigator = new studio::Dock_Navigator();
1184 dock_manager->register_dockable(*dock_navigator);
1186 studio_init_cb.task("Init Timetrack...");
1187 dock_timetrack = new studio::Dock_Timetrack();
1188 dock_manager->register_dockable(*dock_timetrack);
1190 studio_init_cb.task("Init Curve Editor...");
1191 dock_curves = new studio::Dock_Curves();
1192 dock_manager->register_dockable(*dock_curves);
1194 studio_init_cb.task("Init Layer Groups...");
1195 dock_layer_groups = new studio::Dock_LayerGroups();
1196 dock_manager->register_dockable(*dock_layer_groups);
1199 studio_init_cb.task("Init Color Dialog...");
1200 dialog_color=new studio::Dialog_Color();
1202 studio_init_cb.task("Init Gradient Dialog...");
1203 dialog_gradient=new studio::Dialog_Gradient();
1205 studio_init_cb.task("Init DeviceTracker...");
1206 device_tracker=new studio::DeviceTracker();
1208 studio_init_cb.task("Init Tools...");
1209 state_manager->add_state(&state_normal);
1210 state_manager->add_state(&state_smooth_move);
1211 state_manager->add_state(&state_scale);
1212 state_manager->add_state(&state_rotate);
1214 state_manager->add_state(&state_bline);
1217 state_manager->add_state(&state_circle);
1218 state_manager->add_state(&state_rectangle);
1220 state_manager->add_state(&state_gradient);
1221 state_manager->add_state(&state_eyedrop);
1222 state_manager->add_state(&state_fill);
1224 state_manager->add_state(&state_zoom);
1227 // Disabled this tool because it should be
1228 // considered deprecated. Use the bline tool instead.
1229 state_manager->add_state(&state_polygon);
1231 // These tools are disabled for now,
1232 // because they tend to confuse users.
1233 state_manager->add_state(&state_draw);
1234 state_manager->add_state(&state_sketch);
1235 state_manager->add_state(&state_width);
1238 studio_init_cb.task("Init ModPalette...");
1239 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1241 studio_init_cb.task("Init ModMirror...");
1242 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1245 studio_init_cb.task("Init Setup Dialog...");
1246 dialog_setup=new studio::Dialog_Setup();
1248 studio_init_cb.task("Init Input Dialog...");
1249 dialog_input=new Gtk::InputDialog();
1251 studio_init_cb.task("Init auto recovery...");
1252 auto_recover=new AutoRecover();
1254 studio_init_cb.amount_complete(9250,10000);
1255 studio_init_cb.task("Loading Settings...");
1257 studio_init_cb.task("Checking auto-recover...");
1259 studio_init_cb.amount_complete(9900,10000);
1261 if(auto_recover->recovery_needed())
1263 about_window.hide();
1265 get_ui_interface()->yes_no(
1267 "SYNFIG Studio seems to have crashed\n"
1268 "before you could save all your files.\n"
1269 "Would you like to re-open those files\n"
1270 "and recover your unsaved changes?"
1271 )==synfigapp::UIInterface::RESPONSE_YES
1274 if(!auto_recover->recover())
1276 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1279 get_ui_interface()->error(
1280 _("SYNFIG Studio has attempted to recover\n"
1281 "from a previous crash. The files that it has\n"
1282 "recovered are NOT YET SAVED. It would be a good\n"
1283 "idea to review them and save them now.")
1286 about_window.show();
1289 // Look for any files given on the command line,
1290 // and load them if found.
1291 for(;*argc>=1;(*argc)--)
1292 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1294 studio_init_cb.task("Loading files...");
1295 about_window.hide();
1296 open((*argv)[*argc]);
1297 about_window.show();
1300 studio_init_cb.task("Done.");
1301 studio_init_cb.amount_complete(10000,10000);
1307 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1311 StateManager* App::get_state_manager() { return state_manager; }
1315 shutdown_in_progress=true;
1319 synfigapp::Main::settings().remove_domain("pref");
1321 selected_instance=0;
1323 // Unload all of the modules
1324 for(;!module_list_.empty();module_list_.pop_back());
1326 delete state_manager;
1330 delete auto_recover;
1334 // studio::App::iteration(false);
1338 // studio::App::iteration(false);
1340 // studio::App::iteration(false);
1342 delete dialog_setup;
1344 delete dialog_gradient;
1346 delete dialog_color;
1348 delete dialog_input;
1350 delete dock_manager;
1352 instance_list.clear();
1354 // studio::App::iteration(false);
1358 App::get_user_app_directory()
1360 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1364 App::get_config_file(const synfig::String& file)
1366 return Glib::build_filename(get_user_app_directory(),file);
1370 App::add_recent_file(const std::string &file_name)
1372 std::string filename(file_name);
1374 assert(!filename.empty());
1376 if(filename.empty())
1379 // Toss out any "hidden" files
1380 if(basename(filename)[0]=='.')
1383 // If we aren't an absolute path, turn outselves into one
1384 if(!is_absolute_path(filename))
1385 filename=absolute_path(filename);
1387 list<string>::iterator iter;
1388 // Check to see if the file is already on the list.
1389 // If it is, then remove it from the list
1390 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1393 recent_files.erase(iter);
1398 // Push the filename to the front of the list
1399 recent_files.push_front(filename);
1401 // Clean out the files at the end of the list.
1402 while(recent_files.size()>(unsigned)get_max_recent_files())
1403 recent_files.pop_back();
1405 signal_recent_files_changed_();
1410 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1413 App::get_time_format()
1415 return _App_time_format;
1419 App::set_time_format(synfig::Time::Format x)
1426 App::save_settings()
1431 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1432 setlocale(LC_NUMERIC, "C");
1434 std::string filename=get_config_file("accelrc");
1435 Gtk::AccelMap::save(filename);
1438 std::string filename=get_config_file("recentfiles");
1440 std::ofstream file(filename.c_str());
1444 synfig::warning("Unable to save %s",filename.c_str());
1448 list<string>::reverse_iterator iter;
1450 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1454 std::string filename=get_config_file("settings");
1455 synfigapp::Main::settings().save_to_file(filename);
1456 setlocale(LC_NUMERIC,old_locale);
1460 synfig::warning("Caught exception when attempting to save settings.");
1465 App::load_settings()
1470 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1471 setlocale(LC_NUMERIC, "C");
1473 std::string filename=get_config_file("accelrc");
1474 Gtk::AccelMap::load(filename);
1477 std::string filename=get_config_file("recentfiles");
1479 std::ifstream file(filename.c_str());
1483 std::string recent_file;
1484 getline(file,recent_file);
1485 if(!recent_file.empty())
1486 add_recent_file(recent_file);
1489 std::string filename=get_config_file("settings");
1490 if(!synfigapp::Main::settings().load_from_file(filename))
1492 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1493 //if(!synfigapp::Main::settings().load_from_file(filename))
1495 gamma.set_gamma(1.0/2.2);
1496 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1497 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1498 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1499 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1500 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1501 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1502 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1503 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1504 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1505 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1506 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1507 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1508 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1511 setlocale(LC_NUMERIC,old_locale);
1515 synfig::warning("Caught exception when attempting to load settings.");
1520 App::shutdown_request(GdkEventAny*)
1524 //return !shutdown_in_progress;
1530 if(shutdown_in_progress)return;
1533 get_ui_interface()->task("Quit Request");
1536 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1540 std::list<etl::handle<Instance> >::iterator iter;
1541 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1543 if(!(*iter)->safe_close())
1547 if((*iter)->synfigapp::Instance::get_action_count())
1549 handle<synfigapp::UIInterface> uim;
1550 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1552 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1553 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1555 case synfigapp::UIInterface::RESPONSE_NO:
1557 case synfigapp::UIInterface::RESPONSE_YES:
1560 case synfigapp::UIInterface::RESPONSE_CANCEL:
1569 if((*iter)->synfigapp::Instance::is_modified())
1571 handle<synfigapp::UIInterface> uim;
1572 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1574 string str=strprintf(_("%s has changes not yet on the CVS repository.\nWould you like to commit these changes?"),(*iter)->get_file_name().c_str() );
1575 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1577 case synfigapp::UIInterface::RESPONSE_NO:
1579 case synfigapp::UIInterface::RESPONSE_YES:
1580 (*iter)->dialog_cvs_commit();
1582 case synfigapp::UIInterface::RESPONSE_CANCEL:
1591 // This next line causes things to crash for some reason
1595 shutdown_in_progress=true;
1597 instance_list.clear();
1599 while(studio::App::events_pending())studio::App::iteration(false);
1602 auto_recover->normal_shutdown();
1604 get_ui_interface()->task("Quit Request sent");
1610 dialog_setup->refresh();
1611 dialog_setup->show();
1614 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1615 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1618 //#define USE_WIN32_FILE_DIALOGS 1
1621 #ifdef USE_WIN32_FILE_DIALOGS
1622 static OPENFILENAME ofn={};
1626 #include <gdk/gdkwin32.h>
1630 App::dialog_open_file(const std::string &title, std::string &filename)
1632 #ifdef USE_WIN32_FILE_DIALOGS
1633 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1635 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1636 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1637 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1639 ofn.lStructSize=sizeof(OPENFILENAME);
1640 ofn.hwndOwner = hWnd;
1641 ofn.hInstance = hInstance;
1642 ofn.lpstrFilter = szFilter;
1643 // ofn.lpstrCustomFilter=NULL;
1644 // ofn.nMaxCustFilter=0;
1645 // ofn.nFilterIndex=0;
1646 // ofn.lpstrFile=NULL;
1647 ofn.nMaxFile=MAX_PATH;
1648 // ofn.lpstrFileTitle=NULL;
1649 // ofn.lpstrInitialDir=NULL;
1650 // ofn.lpstrTitle=NULL;
1651 ofn.Flags=OFN_HIDEREADONLY;
1652 // ofn.nFileOffset=0;
1653 // ofn.nFileExtension=0;
1654 ofn.lpstrDefExt=TEXT("sif");
1655 // ofn.lCustData = 0l;
1657 // ofn.lpTemplateName=NULL;
1659 CHAR szFilename[MAX_PATH];
1661 strcpy(szFilename,filename.c_str());
1662 strcpy(szTitle,title.c_str());
1664 ofn.lpstrFile=szFilename;
1665 ofn.lpstrFileTitle=szTitle;
1667 if(GetOpenFileName(&ofn))
1669 filename=szFilename;
1675 synfig::String prev_path;
1676 if(!_preferences.get_value("curr_path",prev_path))
1679 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1680 dialog->set_current_folder(prev_path);
1681 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1682 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1683 if(!filename.empty())
1684 dialog->set_filename(filename);
1685 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1686 filename=dialog->get_filename();
1698 GtkWidget *fileselection;
1699 fileselection = gtk_file_selection_new(title.c_str());
1702 if(basename(filename)==filename)
1704 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1707 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1709 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1711 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1712 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1714 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1715 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1717 gtk_widget_show(fileselection);
1725 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1726 _preferences.set_value("curr_path",dirname(filename));
1730 gtk_widget_destroy(fileselection);
1733 gtk_widget_destroy(fileselection);
1740 App::dialog_save_file(const std::string &title, std::string &filename)
1742 #ifdef USE_WIN32_FILE_DIALOGS
1743 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1745 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1746 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1747 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1749 ofn.lStructSize=sizeof(OPENFILENAME);
1750 ofn.hwndOwner = hWnd;
1751 ofn.hInstance = hInstance;
1752 ofn.lpstrFilter = szFilter;
1753 // ofn.lpstrCustomFilter=NULL;
1754 // ofn.nMaxCustFilter=0;
1755 // ofn.nFilterIndex=0;
1756 // ofn.lpstrFile=NULL;
1757 ofn.nMaxFile=MAX_PATH;
1758 // ofn.lpstrFileTitle=NULL;
1759 // ofn.lpstrInitialDir=NULL;
1760 // ofn.lpstrTitle=NULL;
1761 ofn.Flags=OFN_OVERWRITEPROMPT;
1762 // ofn.nFileOffset=0;
1763 // ofn.nFileExtension=0;
1764 ofn.lpstrDefExt=TEXT("sif");
1765 // ofn.lCustData = 0l;
1767 // ofn.lpTemplateName=NULL;
1769 CHAR szFilename[MAX_PATH];
1771 strcpy(szFilename,filename.c_str());
1772 strcpy(szTitle,title.c_str());
1774 ofn.lpstrFile=szFilename;
1775 ofn.lpstrFileTitle=szTitle;
1777 if(GetSaveFileName(&ofn))
1779 filename=szFilename;
1784 synfig::String prev_path;
1785 if(!_preferences.get_value("curr_path",prev_path))
1788 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1789 dialog->set_current_folder(prev_path);
1790 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1791 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1792 if(!filename.empty())
1793 dialog->set_filename(filename);
1794 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1795 filename=dialog->get_filename();
1801 // return dialog_open_file(title, filename);
1806 App::dialog_saveas_file(const std::string &title, std::string &filename)
1808 #if USE_WIN32_FILE_DIALOGS
1809 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1811 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1812 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1813 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1815 ofn.lStructSize=sizeof(OPENFILENAME);
1816 ofn.hwndOwner = hWnd;
1817 ofn.hInstance = hInstance;
1818 ofn.lpstrFilter = szFilter;
1819 // ofn.lpstrCustomFilter=NULL;
1820 // ofn.nMaxCustFilter=0;
1821 // ofn.nFilterIndex=0;
1822 // ofn.lpstrFile=NULL;
1823 ofn.nMaxFile=MAX_PATH;
1824 // ofn.lpstrFileTitle=NULL;
1825 // ofn.lpstrInitialDir=NULL;
1826 // ofn.lpstrTitle=NULL;
1827 ofn.Flags=OFN_OVERWRITEPROMPT;
1828 // ofn.nFileOffset=0;
1829 // ofn.nFileExtension=0;
1830 ofn.lpstrDefExt=TEXT("sif");
1831 // ofn.lCustData = 0l;
1833 // ofn.lpTemplateName=NULL;
1835 CHAR szFilename[MAX_PATH];
1837 strcpy(szFilename,filename.c_str());
1838 strcpy(szTitle,title.c_str());
1840 ofn.lpstrFile=szFilename;
1841 ofn.lpstrFileTitle=szTitle;
1843 if(GetSaveFileName(&ofn))
1845 filename=szFilename;
1850 synfig::String prev_path;
1851 if(!_preferences.get_value("curr_path",prev_path))
1854 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1855 dialog->set_current_folder(prev_path);
1856 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1857 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1858 if(!filename.empty())
1859 dialog->set_filename(filename);
1860 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1861 filename=dialog->get_filename();
1867 // return dialog_open_file(title, filename);
1872 App::dialog_error_blocking(const std::string &title, const std::string &message)
1877 true // use_separator
1879 Gtk::Label label(message);
1882 dialog.get_vbox()->pack_start(label);
1883 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1889 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1894 true // use_separator
1896 Gtk::Label label(message);
1899 dialog.get_vbox()->pack_start(label);
1900 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1906 App::dialog_yes_no(const std::string &title, const std::string &message)
1911 true // use_separator
1913 Gtk::Label label(message);
1916 dialog.get_vbox()->pack_start(label);
1917 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1918 dialog.add_button(Gtk::StockID("gtk-no"),0);
1920 return dialog.run();
1924 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1929 true // use_separator
1931 Gtk::Label label(message);
1934 dialog.get_vbox()->pack_start(label);
1935 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1936 dialog.add_button(Gtk::StockID("gtk-no"),0);
1937 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1939 return dialog.run();
1943 App::dialog_not_implemented()
1946 "Feature not available", // Title
1948 true // use_separator
1950 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1953 dialog.get_vbox()->pack_start(label);
1954 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1960 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1965 true // use_separator
1967 Gtk::Label label(message);
1969 dialog.get_vbox()->pack_start(label);
1972 entry.set_text(text);
1974 entry.set_activates_default(true);
1975 dialog.get_vbox()->pack_start(entry);
1977 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1978 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1979 dialog.set_default_response(Gtk::RESPONSE_OK);
1980 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1983 if(dialog.run()!=Gtk::RESPONSE_OK)
1986 text=entry.get_text();
1995 App::open(std::string filename)
1997 return open_as(filename,filename);
2001 App::open_as(std::string filename,std::string as)
2004 char long_name[1024];
2005 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2011 OneMoment one_moment;
2013 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2014 if(canvas && get_instance(canvas))
2016 get_instance(canvas)->find_canvas_view(canvas)->present();
2017 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2020 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2022 add_recent_file(as);
2024 handle<Instance> instance(Instance::create(canvas));
2027 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2031 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)")))
2032 instance->dialog_cvs_update();
2036 dialog_error_blocking(_("Error"), x);
2041 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2045 _preferences.set_value("curr_path",dirname(as));
2054 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2055 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2057 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2059 canvas->rend_desc().set_frame_rate(24.0);
2060 canvas->rend_desc().set_time_start(0.0);
2061 canvas->rend_desc().set_time_end(00.0);
2062 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2063 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2064 canvas->rend_desc().set_tl(Vector(-4,2.25));
2065 canvas->rend_desc().set_br(Vector(4,-2.25));
2066 canvas->rend_desc().set_w(480);
2067 canvas->rend_desc().set_h(270);
2068 canvas->rend_desc().set_antialias(1);
2069 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2070 canvas->set_file_name(file_name);
2072 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2078 string filename="*.sif";
2080 while(dialog_open_file("Open", filename))
2082 // If the filename still has wildcards, then we should
2083 // continue looking for the file we want
2084 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2090 get_ui_interface()->error(_("Unable to open file"));
2095 App::set_selected_instance(etl::loose_handle<Instance> instance)
2097 /* if(get_selected_instance()==instance)
2099 selected_instance=instance;
2100 signal_instance_selected()(instance);
2106 selected_instance=instance;
2107 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2111 instance->focus(instance->get_canvas());
2114 set_selected_canvas_view(0);
2116 signal_instance_selected()(instance);
2120 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2122 selected_canvas_view=canvas_view;
2123 signal_canvas_view_focus()(selected_canvas_view);
2126 selected_instance=canvas_view->get_instance();
2127 signal_instance_selected()(canvas_view->get_instance());
2130 if(get_selected_canvas_view()==canvas_view)
2132 signal_canvas_view_focus()(selected_canvas_view);
2133 signal_instance_selected()(canvas_view->get_instance());
2136 selected_canvas_view=canvas_view;
2137 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2138 set_selected_instance(canvas_view->get_instance());
2139 signal_canvas_view_focus()(selected_canvas_view);
2143 etl::loose_handle<Instance>
2144 App::get_instance(Canvas::Handle canvas)
2146 if(!canvas) return 0;
2147 canvas=canvas->get_root();
2149 std::list<etl::handle<Instance> >::iterator iter;
2150 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2152 if((*iter)->get_canvas()==canvas)
2161 (new class About())->show();
2167 if(selected_instance)
2168 selected_instance->undo();
2174 if(selected_instance)
2175 selected_instance->redo();
2179 studio::App::get_base_path()
2181 return app_base_path_;