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"
118 #include <gtkmm/accelmap.h>
119 #include <gtkmm/filechooser.h>
120 #include <gtkmm/filechooserdialog.h>
124 /* === U S I N G =========================================================== */
128 using namespace synfig;
129 using namespace studio;
131 /* === M A C R O S ========================================================= */
134 #define DPM2DPI(x) (float(x)/39.3700787402f)
135 #define DPI2DPM(x) (float(x)*39.3700787402f)
141 # define IMAGE_DIR "share\\pixmaps"
146 # define IMAGE_DIR "/usr/local/share/pixmaps"
150 # define IMAGE_EXT "tif"
153 #include <synfigapp/main.h>
155 /* === S I G N A L S ======================================================= */
157 static sigc::signal<void> signal_present_all_;
159 App::signal_present_all() { return signal_present_all_; }
161 static sigc::signal<void> signal_recent_files_changed_;
163 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
165 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
166 sigc::signal<void,etl::loose_handle<CanvasView> >&
167 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
169 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
170 sigc::signal<void,etl::handle<Instance> >&
171 App::signal_instance_selected() { return signal_instance_selected_; }
173 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
174 sigc::signal<void,etl::handle<Instance> >&
175 App::signal_instance_created() { return signal_instance_created_; }
177 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
178 sigc::signal<void,etl::handle<Instance> >&
179 App::signal_instance_deleted() { return signal_instance_deleted_; }
181 /* === G L O B A L S ======================================================= */
183 static std::list<std::string> recent_files;
184 const std::list<std::string>& App::get_recent_files() { return recent_files; }
186 int App::Busy::count;
187 bool App::shutdown_in_progress;
189 synfig::Gamma App::gamma;
191 Glib::RefPtr<studio::UIManager> App::ui_manager_;
193 synfig::Distance::System App::distance_system;
195 studio::Dialog_Setup* App::dialog_setup;
197 etl::handle< studio::ModPalette > mod_palette_;
198 //studio::Dialog_Palette* App::dialog_palette;
200 std::list<etl::handle<Instance> > App::instance_list;
202 static etl::handle<synfigapp::UIInterface> ui_interface_;
203 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
205 etl::handle<Instance> App::selected_instance;
206 etl::handle<CanvasView> App::selected_canvas_view;
208 studio::Toolbox *studio::App::toolbox=NULL;
210 studio::AutoRecover *studio::App::auto_recover=NULL;
212 studio::IPC *ipc=NULL;
214 studio::DockManager* studio::App::dock_manager=0;
216 studio::DeviceTracker* studio::App::device_tracker=0;
218 studio::Dialog_Gradient* studio::App::dialog_gradient;
220 studio::Dialog_Color* studio::App::dialog_color;
222 Gtk::InputDialog* studio::App::dialog_input;
224 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
226 studio::Dock_History* dock_history;
227 studio::Dock_Canvases* dock_canvases;
228 studio::Dock_Keyframes* dock_keyframes;
229 studio::Dock_Layers* dock_layers;
230 studio::Dock_Params* dock_params;
231 studio::Dock_MetaData* dock_meta_data;
232 studio::Dock_Children* dock_children;
233 studio::Dock_Info* dock_info;
234 studio::Dock_LayerGroups* dock_layer_groups;
235 studio::Dock_Navigator* dock_navigator;
236 studio::Dock_Timetrack* dock_timetrack;
237 studio::Dock_Curves* dock_curves;
239 std::list< etl::handle< studio::Module > > module_list_;
241 bool studio::App::use_colorspace_gamma=true;
243 static int max_recent_files_=25;
244 int studio::App::get_max_recent_files() { return max_recent_files_; }
245 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
247 static synfig::String app_base_path_;
250 }; // END of namespace studio
251 studio::StateManager* state_manager;
256 class GlobalUIInterface : public synfigapp::UIInterface
260 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
265 true // use_separator
267 Gtk::Label label(message);
270 dialog.get_vbox()->pack_start(label);
271 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
272 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
274 dialog.set_default_response(dflt);
276 return (Response)dialog.run();
278 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
283 true // use_separator
285 Gtk::Label label(message);
288 dialog.get_vbox()->pack_start(label);
289 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
290 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
291 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
293 dialog.set_default_response(dflt);
295 return (Response)dialog.run();
297 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
302 true // use_separator
304 Gtk::Label label(message);
307 dialog.get_vbox()->pack_start(label);
308 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
309 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
311 dialog.set_default_response(dflt);
313 return (Response)dialog.run();
317 task(const std::string &task)
319 std::cerr<<task<<std::endl;
320 while(studio::App::events_pending())studio::App::iteration(false);
325 error(const std::string &err)
330 true // use_separator
332 Gtk::Label label(err);
335 dialog.get_vbox()->pack_start(label);
336 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
343 warning(const std::string &err)
345 std::cerr<<"warning: "<<err<<std::endl;
346 while(studio::App::events_pending())studio::App::iteration(false);
351 amount_complete(int current, int total)
353 while(studio::App::events_pending())studio::App::iteration(false);
358 /* === P R O C E D U R E S ================================================= */
360 typedef unsigned char U8;
361 typedef unsigned short U16;
362 typedef unsigned long U32;
372 static inline U32 hash_U32(U32 i)
374 i=i*1664525+1013904223;
375 i=i*1664525+1013904223;
376 i=i*1664525+1013904223;
381 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
382 #define endian_fix(x) (endian_fix_table[x])
384 #define endian_fix(x) (x)
387 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
390 unwound->element.serial=0;
391 unwound->element.checksum=0;
399 case '0': data=0; break;
400 case '1': data=1; break;
401 case '2': data=2; break;
402 case '3': data=3; break;
403 case '4': data=4; break;
404 case '5': data=5; break;
405 case '6': data=6; break;
406 case '7': data=7; break;
407 case '8': data=8; break;
408 case '9': data=9; break;
409 case 'a': case 'A': data=10; break;
410 case 'b': case 'B': data=11; break;
411 case 'c': case 'C': data=12; break;
412 case 'd': case 'D': data=13; break;
413 case 'e': case 'E': data=14; break;
414 case 'f': case 'F': data=15; break;
415 default: return 0; break;
418 unwound->element.checksum|=(((U32)data&3)<<bit);
419 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
424 int v_key_check(const char* key, U32* serial, U32 appid)
426 V_KeyUnwound unwound_key;
427 U32 appid_mask_a=hash_U32(appid);
428 U32 appid_mask_b=hash_U32(appid_mask_a);
430 if(!v_unwind_key(&unwound_key, key))
432 // Invalid characters in key
437 // Undo obfuscation pass
439 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
444 unwound_key.raw[endian_fix(i)]^=(next>>24);
448 unwound_key.element.serial^=appid_mask_a;
449 unwound_key.element.checksum^=appid_mask_b;
451 *serial=unwound_key.element.serial;
453 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
457 int check_license(String basedir)
459 #ifdef LICENSE_KEY_REQUIRED
464 license_file="/usr/local/etc/.synfiglicense";
466 license_file=basedir+"\\etc\\.synfiglicense";
470 key=Glib::file_get_contents(license_file);
471 } catch (Glib::FileError) { }
473 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
475 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
479 if(!App::dialog_entry(
480 _("Synfig Studio Authentication"),
481 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
484 throw String("No License");
487 FILE* file=fopen(license_file.c_str(),"w");
490 fprintf(file,"%s",key.c_str());
494 synfig::error("Unable to save license key!");
496 synfig::info("License Authenticated -- Serial #%05d",serial);
505 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
507 action_group_list.push_back(action_group);
508 Gtk::UIManager::insert_action_group(action_group, pos);
512 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
514 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
515 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
516 if(*iter==action_group)
518 action_group_list.erase(iter);
519 Gtk::UIManager::remove_action_group(action_group);
522 synfig::error("Unable to find action group");
526 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
528 ui_manager->insert_action_group(group,0);
531 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
532 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
535 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
538 if(*iter && (*iter)->get_name()!="menus")
540 synfig::info("Removing action group "+(*iter)->get_name());
541 ui_manager->remove_action_group(*iter);
545 ui_manager->insert_action_group(group,0);
548 for(;!prev_groups.empty();prev_groups.pop_front())
550 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
551 ui_manager->insert_action_group(prev_groups.front(),1);
556 class Preferences : public synfigapp::Settings
559 virtual bool get_value(const synfig::String& key, synfig::String& value)const
563 value=strprintf("%f %f %f %f",
564 App::gamma.get_gamma_r(),
565 App::gamma.get_gamma_g(),
566 App::gamma.get_gamma_b(),
567 App::gamma.get_black_level()
571 if(key=="time_format")
573 value=strprintf("%i",App::get_time_format());
576 if(key=="file_history.size")
578 value=strprintf("%i",App::get_max_recent_files());
581 if(key=="use_colorspace_gamma")
583 value=strprintf("%i",(int)App::use_colorspace_gamma);
586 if(key=="distance_system")
588 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
591 if(key=="auto_recover_backup_interval")
593 value=strprintf("%i",App::auto_recover->get_timeout());
597 return synfigapp::Settings::get_value(key,value);
600 virtual bool set_value(const synfig::String& key,const synfig::String& value)
606 strscanf(value,"%f %f %f %f",
613 App::gamma.set_all(r,g,b,blk);
617 if(key=="time_format")
619 int i(atoi(value.c_str()));
620 App::set_time_format(static_cast<synfig::Time::Format>(i));
623 if(key=="auto_recover_backup_interval")
625 int i(atoi(value.c_str()));
626 App::auto_recover->set_timeout(i);
629 if(key=="file_history.size")
631 int i(atoi(value.c_str()));
632 App::set_max_recent_files(i);
635 if(key=="use_colorspace_gamma")
637 int i(atoi(value.c_str()));
638 App::use_colorspace_gamma=i;
641 if(key=="distance_system")
643 App::distance_system=Distance::ident_system(value);;
647 return synfigapp::Settings::set_value(key,value);
650 virtual KeyList get_key_list()const
652 KeyList ret(synfigapp::Settings::get_key_list());
653 ret.push_back("gamma");
654 ret.push_back("time_format");
655 ret.push_back("distance_system");
656 ret.push_back("file_history.size");
657 ret.push_back("use_colorspace_gamma");
658 ret.push_back("auto_recover_backup_interval");
663 static Preferences _preferences;
668 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
670 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
672 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
674 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
675 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
676 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
677 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
678 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
679 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
680 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
681 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
682 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
683 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
684 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
685 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
687 // Add the synfigapp actions...
688 synfigapp::Action::Book::iterator iter;
689 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
691 actions_action_group->add(Gtk::Action::create(
692 "action-"+iter->second.name,
693 get_action_stock_id(iter->second),
694 iter->second.local_name,iter->second.local_name
698 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
699 #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); }
700 #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); }
702 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
703 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
704 DEFINE_ACTION("open", Gtk::Stock::OPEN);
705 DEFINE_ACTION("save", Gtk::Stock::SAVE);
706 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
707 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
708 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
709 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
710 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
711 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
712 DEFINE_ACTION("import", _("Import"));
713 DEFINE_ACTION("render", _("Render"));
714 DEFINE_ACTION("preview", _("Preview"));
715 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
716 DEFINE_ACTION("sound", _("Sound File"));
717 DEFINE_ACTION("options", _("Options"));
718 DEFINE_ACTION("close", _("Close"));
721 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
722 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
723 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
724 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
725 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
726 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
727 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
728 DEFINE_ACTION("properties", _("Properties"));
730 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
731 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
732 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
733 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
734 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
735 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
736 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
737 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
738 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
739 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
740 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
741 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
742 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
743 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
744 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
745 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
746 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
747 DEFINE_ACTION("play", _("Play"));
748 DEFINE_ACTION("pause", _("Pause"));
749 DEFINE_ACTION("stop", _("Stop"));
750 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
751 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
752 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
753 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
754 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
755 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
756 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
757 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
758 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
759 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
760 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
761 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
762 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
763 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
764 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
765 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
766 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
767 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
768 DEFINE_ACTION("seek-end", _("Seek to End"));
770 DEFINE_ACTION("action-group_add", _("Add group"));
772 DEFINE_ACTION("canvas-new", _("New Canvas"));
774 DEFINE_ACTION("amount-inc", _("Increase Amount"));
775 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
780 // Set up synfigapp actions
782 synfigapp::Action::Book::iterator iter;
784 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
786 Gtk::StockID stock_id;
788 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
790 //Gtk::Image* image(manage(new Gtk::Image()));
791 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
792 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
793 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
794 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
795 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
796 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
797 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
798 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
799 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
800 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
802 actions_action_group->add(Gtk::Action::create(
803 "action-"+iter->second.name,
805 iter->second.local_name,iter->second.local_name
813 Glib::ustring ui_info =
815 " <popup name='menu-toolbox' action='menu-toolbox'>"
816 " <menu action='menu-file'>"
819 " <popup name='menu-main' action='menu-main'>"
820 " <menu action='menu-file'>"
821 " <menuitem action='save' />"
822 " <menuitem action='save-as' />"
823 " <menuitem action='revert' />"
824 " <separator name='bleh01'/>"
825 " <menuitem action='cvs-add' />"
826 " <menuitem action='cvs-update' />"
827 " <menuitem action='cvs-commit' />"
828 " <menuitem action='cvs-revert' />"
829 " <separator name='bleh02'/>"
830 " <menuitem action='import' />"
831 " <separator name='bleh03'/>"
832 " <menuitem action='render' />"
833 " <menuitem action='preview' />"
834 " <menuitem action='sound' />"
835 " <separator name='bleh04'/>"
836 " <menuitem action='options' />"
837 " <menuitem action='close' />"
839 " <menu action='menu-edit'>"
840 " <menuitem action='undo'/>"
841 " <menuitem action='redo'/>"
842 " <separator name='bleh05'/>"
843 " <menuitem action='cut'/>"
844 " <menuitem action='copy'/>"
845 " <menuitem action='paste'/>"
846 " <separator name='bleh06'/>"
847 " <menuitem action='select-all-ducks'/>"
848 " <menuitem action='unselect-all-layers'/>"
849 " <separator name='bleh07'/>"
850 " <menuitem action='properties'/>"
852 " <menu action='menu-view'>"
853 " <menu action='menu-duck-mask'>"
854 " <menuitem action='mask-position-ducks' />"
855 " <menuitem action='mask-vertex-ducks' />"
856 " <menuitem action='mask-tangent-ducks' />"
857 " <menuitem action='mask-radius-ducks' />"
858 " <menuitem action='mask-width-ducks' />"
859 " <menuitem action='mask-angle-ducks' />"
861 " <menu action='menu-preview-quality'>"
862 " <menuitem action='quality-00' />"
863 " <menuitem action='quality-01' />"
864 " <menuitem action='quality-02' />"
865 " <menuitem action='quality-03' />"
866 " <menuitem action='quality-04' />"
867 " <menuitem action='quality-05' />"
868 " <menuitem action='quality-06' />"
869 " <menuitem action='quality-07' />"
870 " <menuitem action='quality-08' />"
871 " <menuitem action='quality-09' />"
872 " <menuitem action='quality-10' />"
874 " <separator name='bleh08'/>"
875 " <menuitem action='play'/>"
876 " <menuitem action='pause'/>"
877 " <menuitem action='stop'/>"
878 " <menuitem action='dialog-flipbook'/>"
879 " <separator name='bleh09'/>"
880 " <menuitem action='toggle-grid-show'/>"
881 " <menuitem action='toggle-grid-snap'/>"
882 " <menuitem action='toggle-guide-show'/>"
883 " <menuitem action='toggle-low-res'/>"
884 " <menuitem action='toggle-onion-skin'/>"
885 " <separator name='bleh10'/>"
886 " <menuitem action='canvas-zoom-in'/>"
887 " <menuitem action='canvas-zoom-out'/>"
888 " <menuitem action='canvas-zoom-fit'/>"
889 " <menuitem action='canvas-zoom-100'/>"
890 " <separator name='bleh11'/>"
891 " <menuitem action='time-zoom-in'/>"
892 " <menuitem action='time-zoom-out'/>"
893 " <separator name='bleh12'/>"
894 " <menuitem action='jump-next-keyframe'/>"
895 " <menuitem action='jump-prev-keyframe'/>"
896 " <menuitem action='seek-next-frame'/>"
897 " <menuitem action='seek-prev-frame'/>"
898 " <menuitem action='seek-next-second'/>"
899 " <menuitem action='seek-prev-second'/>"
900 " <menuitem action='seek-begin'/>"
901 " <menuitem action='seek-end'/>"
903 " <menu action='menu-canvas'>"
904 " <menuitem action='canvas-new'/>"
905 " <menuitem action='amount-inc'/>"
906 " <menuitem action='amount-dec'/>"
908 " <menu name='menu-state' action='menu-state'>"
910 " <menu action='menu-group'>"
911 " <menuitem action='action-group_add'/>"
913 " <menu action='menu-layer'>"
914 //" <menuitem action='cut'/>"
915 //" <menuitem action='copy'/>"
916 //" <menuitem action='paste'/>"
917 //" <separator name='bleh06'/>"
918 " <menu action='menu-layer-new'></menu>"
920 " <menu action='menu-keyframe'>"
921 " <menuitem action='keyframe-properties'/>"
928 " <menubar name='MenuBar'>"
929 " <menu action='MenuFile'>"
930 " <menuitem action='New'/>"
931 " <menuitem action='Open'/>"
933 " <menuitem action='Quit'/>"
935 " <menu action='MenuEdit'>"
936 " <menuitem action='Cut'/>"
937 " <menuitem action='Copy'/>"
938 " <menuitem action='Paste'/>"
941 " <toolbar name='ToolBar'>"
942 " <toolitem action='Open'/>"
943 " <toolitem action='Quit'/>"
949 actions_action_group->set_sensitive(false);
950 App::ui_manager()->set_add_tearoffs(true);
951 App::ui_manager()->insert_action_group(menus_action_group,1);
952 App::ui_manager()->insert_action_group(actions_action_group,1);
953 App::ui_manager()->add_ui_from_string(ui_info);
955 //App::ui_manager()->get_accel_group()->unlock();
957 catch(const Glib::Error& ex)
959 synfig::error("building menus and toolbars failed: " + ex.what());
962 // Add default keyboard accelerators
963 #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()); }
964 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
965 ACCEL("<Actions>//select-all-ducks","<Control>a");
966 ACCEL("<Actions>//unselect-all-layers","<Control>d");
967 ACCEL("<Actions>//render","F9");
968 ACCEL("<Actions>//preview","F11");
969 ACCEL("<Actions>//properties","F8");
970 ACCEL("<Actions>//options","F12");
971 ACCEL("<Actions>//import","<control>i");
972 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
973 ACCEL("<Actions>//toggle-grid-show","<Control>g");
974 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
975 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
976 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
977 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
978 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
979 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
980 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
981 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
984 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
985 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
987 ACCEL("<Actions>//quality-01","<Control>1");
988 ACCEL("<Actions>//quality-02","<Control>2");
989 ACCEL("<Actions>//quality-03","<Control>3");
990 ACCEL("<Actions>//quality-04","<Control>4");
991 ACCEL("<Actions>//quality-05","<Control>5");
992 ACCEL("<Actions>//quality-06","<Control>6");
993 ACCEL("<Actions>//quality-07","<Control>7");
994 ACCEL("<Actions>//quality-08","<Control>8");
995 ACCEL("<Actions>//quality-09","<Control>9");
996 ACCEL("<Actions>//quality-10","<Control>0");
997 ACCEL("<Actions>//undo","<Control>z");
998 ACCEL("<Actions>//redo","<Control>r");
999 ACCEL("<Actions>//action-layer_remove","Delete");
1001 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1002 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1003 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1004 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1005 ACCEL("<Actions>//time-zoom-in","+");
1006 ACCEL("<Actions>//time-zoom-out","_");
1008 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1009 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1011 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1012 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1013 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1014 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1015 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1016 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1017 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1018 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1019 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1020 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1021 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1022 ACCEL("<Actions>//seek-begin","Home");
1023 ACCEL("<Actions>//seek-end","End");
1024 ACCEL("<Actions>//state-normal","<Mod1>a");
1025 ACCEL("<Actions>//state-rotate","<Mod1>s");
1026 ACCEL("<Actions>//state-scale","<Mod1>d");
1027 ACCEL("<Actions>//state-bline","<Mod1>b");
1028 ACCEL("<Actions>//state-fill","<Mod1>f");
1029 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1030 ACCEL("<Actions>//state-gradient","<Mod1>g");
1031 ACCEL("<Actions>//state-zoom","<Mod1>z");
1032 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1038 #define mkdir(x,y) mkdir(x)
1041 /* === M E T H O D S ======================================================= */
1043 App::App(int *argc, char ***argv):
1044 Gtk::Main(argc,argv),
1045 IconControler(etl::dirname((*argv)[0]))
1047 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1050 serial_=check_license(app_base_path_);
1053 ui_interface_=new GlobalUIInterface();
1057 Glib::thread_init();
1059 distance_system=Distance::SYSTEM_UNITS;
1061 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1064 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1068 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1076 if(!SYNFIG_CHECK_VERSION())
1078 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1079 dialog_error_blocking("SYNFIG Studio",
1080 "This copy of SYNFIG Studio was compiled against a\n"
1081 "different version of libsynfig than what is currently\n"
1082 "installed. Synfig Studio will now abort. Try downloading\n"
1083 "the latest version from the SYNFIG Development Website at\n"
1084 "http://dev.synfig.com/ "
1089 catch(synfig::SoftwareExpired)
1091 cerr<<"FATAL: Software Expired"<<endl;
1092 dialog_error_blocking("SYNFIG Studio",
1093 "This copy of SYNFIG Studio has expired.\n"
1094 "Please erase this copy, or download and\n"
1095 "install the latest copy from the SYNFIG\n"
1096 "Development Website at http://dev.synfig.com/ ."
1100 Glib::set_application_name(_("SYNFIG Studio"));
1103 about_window.set_can_self_destruct(false);
1104 about_window.show();
1106 shutdown_in_progress=false;
1107 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1108 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1110 // Initialize the Synfig library
1111 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1114 get_ui_interface()->error("Failed to initialize synfig!");
1118 // add the preferences to the settings
1119 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1123 studio_init_cb.task("Init UI Manager...");
1124 App::ui_manager_=studio::UIManager::create();
1127 studio_init_cb.task("Init Dock Manager...");
1128 dock_manager=new studio::DockManager();
1130 studio_init_cb.task("Init State Manager...");
1131 state_manager=new StateManager();
1133 studio_init_cb.task("Init Toolbox...");
1134 toolbox=new studio::Toolbox();
1136 studio_init_cb.task("Init Tool Options...");
1137 dialog_tool_options=new studio::Dialog_ToolOptions();
1138 dock_manager->register_dockable(*dialog_tool_options);
1140 studio_init_cb.task("Init History...");
1141 dock_history=new studio::Dock_History();
1142 dock_manager->register_dockable(*dock_history);
1144 studio_init_cb.task("Init Canvases...");
1145 dock_canvases=new studio::Dock_Canvases();
1146 dock_manager->register_dockable(*dock_canvases);
1148 studio_init_cb.task("Init Keyframes...");
1149 dock_keyframes=new studio::Dock_Keyframes();
1150 dock_manager->register_dockable(*dock_keyframes);
1152 studio_init_cb.task("Init Layers...");
1153 dock_layers=new studio::Dock_Layers();
1154 dock_manager->register_dockable(*dock_layers);
1156 studio_init_cb.task("Init Params...");
1157 dock_params=new studio::Dock_Params();
1158 dock_manager->register_dockable(*dock_params);
1160 studio_init_cb.task("Init MetaData...");
1161 dock_meta_data=new studio::Dock_MetaData();
1162 dock_manager->register_dockable(*dock_meta_data);
1164 studio_init_cb.task("Init Children...");
1165 dock_children=new studio::Dock_Children();
1166 dock_manager->register_dockable(*dock_children);
1168 studio_init_cb.task("Init Info...");
1169 dock_info = new studio::Dock_Info();
1170 dock_manager->register_dockable(*dock_info);
1172 studio_init_cb.task("Init Navigator...");
1173 dock_navigator = new studio::Dock_Navigator();
1174 dock_manager->register_dockable(*dock_navigator);
1176 studio_init_cb.task("Init Timetrack...");
1177 dock_timetrack = new studio::Dock_Timetrack();
1178 dock_manager->register_dockable(*dock_timetrack);
1180 studio_init_cb.task("Init Curve Editor...");
1181 dock_curves = new studio::Dock_Curves();
1182 dock_manager->register_dockable(*dock_curves);
1184 studio_init_cb.task("Init Layer Groups...");
1185 dock_layer_groups = new studio::Dock_LayerGroups();
1186 dock_manager->register_dockable(*dock_layer_groups);
1189 studio_init_cb.task("Init Color Dialog...");
1190 dialog_color=new studio::Dialog_Color();
1192 studio_init_cb.task("Init Gradient Dialog...");
1193 dialog_gradient=new studio::Dialog_Gradient();
1195 studio_init_cb.task("Init DeviceTracker...");
1196 device_tracker=new studio::DeviceTracker();
1198 studio_init_cb.task("Init Tools...");
1199 state_manager->add_state(&state_normal);
1200 state_manager->add_state(&state_smooth_move);
1201 state_manager->add_state(&state_scale);
1202 state_manager->add_state(&state_rotate);
1204 state_manager->add_state(&state_bline);
1205 state_manager->add_state(&state_polygon);
1206 state_manager->add_state(&state_circle);
1207 state_manager->add_state(&state_rectangle);
1209 state_manager->add_state(&state_draw);
1210 state_manager->add_state(&state_sketch);
1212 state_manager->add_state(&state_eyedrop);
1213 state_manager->add_state(&state_fill);
1215 state_manager->add_state(&state_width);
1216 state_manager->add_state(&state_gradient);
1218 state_manager->add_state(&state_zoom);
1220 studio_init_cb.task("Init ModPalette...");
1221 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1223 studio_init_cb.task("Init ModMirror...");
1224 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1227 studio_init_cb.task("Init Setup Dialog...");
1228 dialog_setup=new studio::Dialog_Setup();
1230 studio_init_cb.task("Init Input Dialog...");
1231 dialog_input=new Gtk::InputDialog();
1233 studio_init_cb.task("Init auto recovery...");
1234 auto_recover=new AutoRecover();
1236 studio_init_cb.amount_complete(9250,10000);
1237 studio_init_cb.task("Loading Settings...");
1239 studio_init_cb.task("Checking auto-recover...");
1241 studio_init_cb.amount_complete(9900,10000);
1243 if(auto_recover->recovery_needed())
1245 about_window.hide();
1247 get_ui_interface()->yes_no(
1249 "SYNFIG Studio seems to have crashed\n"
1250 "before you could save all your files.\n"
1251 "Would you like to re-open those files\n"
1252 "and recover your unsaved changes?"
1253 )==synfigapp::UIInterface::RESPONSE_YES
1256 if(!auto_recover->recover())
1258 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1261 get_ui_interface()->error(
1262 _("SYNFIG Studio has attempted to recover\n"
1263 "from a previous crash. The files that it has\n"
1264 "recovered are NOT YET SAVED. It would be a good\n"
1265 "idea to review them and save them now.")
1268 about_window.show();
1271 // Look for any files given on the command line,
1272 // and load them if found.
1273 for(;*argc>=1;(*argc)--)
1274 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1276 studio_init_cb.task("Loading files...");
1277 about_window.hide();
1278 open((*argv)[*argc]);
1279 about_window.show();
1282 studio_init_cb.task("Done.");
1283 studio_init_cb.amount_complete(10000,10000);
1289 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1293 StateManager* App::get_state_manager() { return state_manager; }
1297 shutdown_in_progress=true;
1301 synfigapp::Main::settings().remove_domain("pref");
1303 selected_instance=0;
1305 // Unload all of the modules
1306 for(;!module_list_.empty();module_list_.pop_back());
1308 delete state_manager;
1312 delete auto_recover;
1316 // studio::App::iteration(false);
1320 // studio::App::iteration(false);
1322 // studio::App::iteration(false);
1324 delete dialog_setup;
1326 delete dialog_gradient;
1328 delete dialog_color;
1330 delete dialog_input;
1332 delete dock_manager;
1334 instance_list.clear();
1336 // studio::App::iteration(false);
1340 App::get_user_app_directory()
1343 return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
1345 return Glib::build_filename(Glib::get_home_dir(),"Synfig");
1350 App::get_config_file(const synfig::String& file)
1352 return Glib::build_filename(get_user_app_directory(),file);
1356 App::add_recent_file(const std::string &file_name)
1358 std::string filename(file_name);
1360 assert(!filename.empty());
1362 if(filename.empty())
1365 // Toss out any "hidden" files
1366 if(basename(filename)[0]=='.')
1369 // If we aren't an absolute path, turn outselves into one
1370 if(!is_absolute_path(filename))
1371 filename=absolute_path(filename);
1373 list<string>::iterator iter;
1374 // Check to see if the file is already on the list.
1375 // If it is, then remove it from the list
1376 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1379 recent_files.erase(iter);
1384 // Push the filename to the front of the list
1385 recent_files.push_front(filename);
1387 // Clean out the files at the end of the list.
1388 while(recent_files.size()>(unsigned)get_max_recent_files())
1389 recent_files.pop_back();
1391 signal_recent_files_changed_();
1396 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1399 App::get_time_format()
1401 return _App_time_format;
1405 App::set_time_format(synfig::Time::Format x)
1412 App::save_settings()
1417 std::string filename=get_config_file("accelrc");
1418 Gtk::AccelMap::save(filename);
1421 std::string filename=get_config_file("recentfiles");
1423 std::ofstream file(filename.c_str());
1427 synfig::warning("Unable to save %s",filename.c_str());
1431 list<string>::reverse_iterator iter;
1433 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1437 std::string filename=get_config_file("settings");
1438 synfigapp::Main::settings().save_to_file(filename);
1442 synfig::warning("Caught exception when attempting to save settings.");
1447 App::load_settings()
1452 std::string filename=get_config_file("accelrc");
1453 Gtk::AccelMap::load(filename);
1456 std::string filename=get_config_file("recentfiles");
1458 std::ifstream file(filename.c_str());
1462 std::string recent_file;
1463 getline(file,recent_file);
1464 if(!recent_file.empty())
1465 add_recent_file(recent_file);
1468 std::string filename=get_config_file("settings");
1469 if(!synfigapp::Main::settings().load_from_file(filename))
1471 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1472 //if(!synfigapp::Main::settings().load_from_file(filename))
1474 gamma.set_gamma(1.0/2.2);
1475 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1476 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1477 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1478 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1479 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1480 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1481 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1482 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1483 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1484 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1485 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1486 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1487 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1494 synfig::warning("Caught exception when attempting to load settings.");
1499 App::shutdown_request(GdkEventAny*)
1503 //return !shutdown_in_progress;
1509 if(shutdown_in_progress)return;
1512 get_ui_interface()->task("Quit Request");
1515 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1519 std::list<etl::handle<Instance> >::iterator iter;
1520 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1522 if(!(*iter)->safe_close())
1526 if((*iter)->synfigapp::Instance::get_action_count())
1528 handle<synfigapp::UIInterface> uim;
1529 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1531 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1532 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1534 case synfigapp::UIInterface::RESPONSE_NO:
1536 case synfigapp::UIInterface::RESPONSE_YES:
1539 case synfigapp::UIInterface::RESPONSE_CANCEL:
1548 if((*iter)->synfigapp::Instance::is_modified())
1550 handle<synfigapp::UIInterface> uim;
1551 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1553 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() );
1554 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1556 case synfigapp::UIInterface::RESPONSE_NO:
1558 case synfigapp::UIInterface::RESPONSE_YES:
1559 (*iter)->dialog_cvs_commit();
1561 case synfigapp::UIInterface::RESPONSE_CANCEL:
1570 // This next line causes things to crash for some reason
1574 shutdown_in_progress=true;
1576 instance_list.clear();
1578 while(studio::App::events_pending())studio::App::iteration(false);
1581 auto_recover->normal_shutdown();
1583 get_ui_interface()->task("Quit Request sent");
1589 dialog_setup->refresh();
1590 dialog_setup->show();
1593 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1594 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1597 //#define USE_WIN32_FILE_DIALOGS 1
1600 #ifdef USE_WIN32_FILE_DIALOGS
1601 static OPENFILENAME ofn={};
1605 #include <gdk/gdkwin32.h>
1609 App::dialog_open_file(const std::string &title, std::string &filename)
1611 #ifdef USE_WIN32_FILE_DIALOGS
1612 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1614 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1615 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1616 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1618 ofn.lStructSize=sizeof(OPENFILENAME);
1619 ofn.hwndOwner = hWnd;
1620 ofn.hInstance = hInstance;
1621 ofn.lpstrFilter = szFilter;
1622 // ofn.lpstrCustomFilter=NULL;
1623 // ofn.nMaxCustFilter=0;
1624 // ofn.nFilterIndex=0;
1625 // ofn.lpstrFile=NULL;
1626 ofn.nMaxFile=MAX_PATH;
1627 // ofn.lpstrFileTitle=NULL;
1628 // ofn.lpstrInitialDir=NULL;
1629 // ofn.lpstrTitle=NULL;
1630 ofn.Flags=OFN_HIDEREADONLY;
1631 // ofn.nFileOffset=0;
1632 // ofn.nFileExtension=0;
1633 ofn.lpstrDefExt=TEXT("sif");
1634 // ofn.lCustData = 0l;
1636 // ofn.lpTemplateName=NULL;
1638 CHAR szFilename[MAX_PATH];
1640 strcpy(szFilename,filename.c_str());
1641 strcpy(szTitle,title.c_str());
1643 ofn.lpstrFile=szFilename;
1644 ofn.lpstrFileTitle=szTitle;
1646 if(GetOpenFileName(&ofn))
1648 filename=szFilename;
1654 synfig::String prev_path;
1655 if(!_preferences.get_value("curr_path",prev_path))
1658 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1659 dialog->set_current_folder(prev_path);
1660 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1661 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1662 if(!filename.empty())
1663 dialog->set_filename(filename);
1664 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1665 filename=dialog->get_filename();
1677 GtkWidget *fileselection;
1678 fileselection = gtk_file_selection_new(title.c_str());
1681 if(basename(filename)==filename)
1683 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1686 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1688 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1690 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1691 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1693 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1694 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1696 gtk_widget_show(fileselection);
1704 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1705 _preferences.set_value("curr_path",dirname(filename));
1709 gtk_widget_destroy(fileselection);
1712 gtk_widget_destroy(fileselection);
1719 App::dialog_save_file(const std::string &title, std::string &filename)
1721 #ifdef USE_WIN32_FILE_DIALOGS
1722 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1724 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1725 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1726 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1728 ofn.lStructSize=sizeof(OPENFILENAME);
1729 ofn.hwndOwner = hWnd;
1730 ofn.hInstance = hInstance;
1731 ofn.lpstrFilter = szFilter;
1732 // ofn.lpstrCustomFilter=NULL;
1733 // ofn.nMaxCustFilter=0;
1734 // ofn.nFilterIndex=0;
1735 // ofn.lpstrFile=NULL;
1736 ofn.nMaxFile=MAX_PATH;
1737 // ofn.lpstrFileTitle=NULL;
1738 // ofn.lpstrInitialDir=NULL;
1739 // ofn.lpstrTitle=NULL;
1740 ofn.Flags=OFN_OVERWRITEPROMPT;
1741 // ofn.nFileOffset=0;
1742 // ofn.nFileExtension=0;
1743 ofn.lpstrDefExt=TEXT("sif");
1744 // ofn.lCustData = 0l;
1746 // ofn.lpTemplateName=NULL;
1748 CHAR szFilename[MAX_PATH];
1750 strcpy(szFilename,filename.c_str());
1751 strcpy(szTitle,title.c_str());
1753 ofn.lpstrFile=szFilename;
1754 ofn.lpstrFileTitle=szTitle;
1756 if(GetSaveFileName(&ofn))
1758 filename=szFilename;
1763 synfig::String prev_path;
1764 if(!_preferences.get_value("curr_path",prev_path))
1767 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1768 dialog->set_current_folder(prev_path);
1769 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1770 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1771 if(!filename.empty())
1772 dialog->set_filename(filename);
1773 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1774 filename=dialog->get_filename();
1780 // return dialog_open_file(title, filename);
1785 App::dialog_saveas_file(const std::string &title, std::string &filename)
1787 #if USE_WIN32_FILE_DIALOGS
1788 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1790 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1791 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1792 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1794 ofn.lStructSize=sizeof(OPENFILENAME);
1795 ofn.hwndOwner = hWnd;
1796 ofn.hInstance = hInstance;
1797 ofn.lpstrFilter = szFilter;
1798 // ofn.lpstrCustomFilter=NULL;
1799 // ofn.nMaxCustFilter=0;
1800 // ofn.nFilterIndex=0;
1801 // ofn.lpstrFile=NULL;
1802 ofn.nMaxFile=MAX_PATH;
1803 // ofn.lpstrFileTitle=NULL;
1804 // ofn.lpstrInitialDir=NULL;
1805 // ofn.lpstrTitle=NULL;
1806 ofn.Flags=OFN_OVERWRITEPROMPT;
1807 // ofn.nFileOffset=0;
1808 // ofn.nFileExtension=0;
1809 ofn.lpstrDefExt=TEXT("sif");
1810 // ofn.lCustData = 0l;
1812 // ofn.lpTemplateName=NULL;
1814 CHAR szFilename[MAX_PATH];
1816 strcpy(szFilename,filename.c_str());
1817 strcpy(szTitle,title.c_str());
1819 ofn.lpstrFile=szFilename;
1820 ofn.lpstrFileTitle=szTitle;
1822 if(GetSaveFileName(&ofn))
1824 filename=szFilename;
1829 synfig::String prev_path;
1830 if(!_preferences.get_value("curr_path",prev_path))
1833 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1834 dialog->set_current_folder(prev_path);
1835 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1836 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1837 if(!filename.empty())
1838 dialog->set_filename(filename);
1839 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1840 filename=dialog->get_filename();
1846 // return dialog_open_file(title, filename);
1851 App::dialog_error_blocking(const std::string &title, const std::string &message)
1856 true // use_separator
1858 Gtk::Label label(message);
1861 dialog.get_vbox()->pack_start(label);
1862 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1868 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1873 true // use_separator
1875 Gtk::Label label(message);
1878 dialog.get_vbox()->pack_start(label);
1879 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1885 App::dialog_yes_no(const std::string &title, const std::string &message)
1890 true // use_separator
1892 Gtk::Label label(message);
1895 dialog.get_vbox()->pack_start(label);
1896 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1897 dialog.add_button(Gtk::StockID("gtk-no"),0);
1899 return dialog.run();
1903 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1908 true // use_separator
1910 Gtk::Label label(message);
1913 dialog.get_vbox()->pack_start(label);
1914 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1915 dialog.add_button(Gtk::StockID("gtk-no"),0);
1916 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1918 return dialog.run();
1922 App::dialog_not_implemented()
1925 "Feature not available", // Title
1927 true // use_separator
1929 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1932 dialog.get_vbox()->pack_start(label);
1933 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1939 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1944 true // use_separator
1946 Gtk::Label label(message);
1948 dialog.get_vbox()->pack_start(label);
1951 entry.set_text(text);
1953 entry.set_activates_default(true);
1954 dialog.get_vbox()->pack_start(entry);
1956 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1957 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1958 dialog.set_default_response(Gtk::RESPONSE_OK);
1959 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1962 if(dialog.run()!=Gtk::RESPONSE_OK)
1965 text=entry.get_text();
1974 App::open(std::string filename)
1976 return open_as(filename,filename);
1980 App::open_as(std::string filename,std::string as)
1983 char long_name[1024];
1984 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1990 OneMoment one_moment;
1992 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1993 if(canvas && get_instance(canvas))
1995 get_instance(canvas)->find_canvas_view(canvas)->present();
1996 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1999 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2001 add_recent_file(as);
2003 handle<Instance> instance(Instance::create(canvas));
2006 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2010 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)")))
2011 instance->dialog_cvs_update();
2015 dialog_error_blocking(_("Error"), x);
2020 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2024 _preferences.set_value("curr_path",dirname(as));
2033 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2034 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2036 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2038 canvas->rend_desc().set_frame_rate(24.0);
2039 canvas->rend_desc().set_time_start(0.0);
2040 canvas->rend_desc().set_time_end(00.0);
2041 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2042 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2043 canvas->rend_desc().set_tl(Vector(-4,2.25));
2044 canvas->rend_desc().set_br(Vector(4,-2.25));
2045 canvas->rend_desc().set_w(480);
2046 canvas->rend_desc().set_h(270);
2047 canvas->rend_desc().set_antialias(1);
2048 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2049 canvas->set_file_name(file_name);
2051 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2057 string filename="*.sif";
2059 while(dialog_open_file("Open", filename))
2061 // If the filename still has wildcards, then we should
2062 // continue looking for the file we want
2063 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2069 get_ui_interface()->error(_("Unable to open file"));
2074 App::set_selected_instance(etl::loose_handle<Instance> instance)
2076 /* if(get_selected_instance()==instance)
2078 selected_instance=instance;
2079 signal_instance_selected()(instance);
2085 selected_instance=instance;
2086 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2090 instance->focus(instance->get_canvas());
2093 set_selected_canvas_view(0);
2095 signal_instance_selected()(instance);
2099 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2101 selected_canvas_view=canvas_view;
2102 signal_canvas_view_focus()(selected_canvas_view);
2105 selected_instance=canvas_view->get_instance();
2106 signal_instance_selected()(canvas_view->get_instance());
2109 if(get_selected_canvas_view()==canvas_view)
2111 signal_canvas_view_focus()(selected_canvas_view);
2112 signal_instance_selected()(canvas_view->get_instance());
2115 selected_canvas_view=canvas_view;
2116 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2117 set_selected_instance(canvas_view->get_instance());
2118 signal_canvas_view_focus()(selected_canvas_view);
2122 etl::loose_handle<Instance>
2123 App::get_instance(Canvas::Handle canvas)
2125 if(!canvas) return 0;
2126 canvas=canvas->get_root();
2128 std::list<etl::handle<Instance> >::iterator iter;
2129 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2131 if((*iter)->get_canvas()==canvas)
2140 (new class About())->show();
2146 if(selected_instance)
2147 selected_instance->undo();
2153 if(selected_instance)
2154 selected_instance->redo();
2158 studio::App::get_base_path()
2160 return app_base_path_;