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>
122 /* === U S I N G =========================================================== */
126 using namespace synfig;
127 using namespace studio;
129 /* === M A C R O S ========================================================= */
132 #define DPM2DPI(x) (float(x)/39.3700787402f)
133 #define DPI2DPM(x) (float(x)*39.3700787402f)
139 # define IMAGE_DIR "share\\pixmaps"
144 # define IMAGE_DIR "/usr/local/share/pixmaps"
148 # define IMAGE_EXT "tif"
151 #include <synfigapp/main.h>
153 /* === S I G N A L S ======================================================= */
155 static sigc::signal<void> signal_present_all_;
157 App::signal_present_all() { return signal_present_all_; }
159 static sigc::signal<void> signal_recent_files_changed_;
161 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
163 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
164 sigc::signal<void,etl::loose_handle<CanvasView> >&
165 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
167 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
168 sigc::signal<void,etl::handle<Instance> >&
169 App::signal_instance_selected() { return signal_instance_selected_; }
171 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
172 sigc::signal<void,etl::handle<Instance> >&
173 App::signal_instance_created() { return signal_instance_created_; }
175 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
176 sigc::signal<void,etl::handle<Instance> >&
177 App::signal_instance_deleted() { return signal_instance_deleted_; }
179 /* === G L O B A L S ======================================================= */
181 static std::list<std::string> recent_files;
182 const std::list<std::string>& App::get_recent_files() { return recent_files; }
184 int App::Busy::count;
185 bool App::shutdown_in_progress;
187 synfig::Gamma App::gamma;
189 Glib::RefPtr<studio::UIManager> App::ui_manager_;
191 synfig::Distance::System App::distance_system;
193 studio::Dialog_Setup* App::dialog_setup;
195 etl::handle< studio::ModPalette > mod_palette_;
196 //studio::Dialog_Palette* App::dialog_palette;
198 std::list<etl::handle<Instance> > App::instance_list;
200 static etl::handle<synfigapp::UIInterface> ui_interface_;
201 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
203 etl::handle<Instance> App::selected_instance;
204 etl::handle<CanvasView> App::selected_canvas_view;
206 studio::Toolbox *studio::App::toolbox=NULL;
208 studio::AutoRecover *studio::App::auto_recover=NULL;
210 studio::IPC *ipc=NULL;
212 studio::DockManager* studio::App::dock_manager=0;
214 studio::DeviceTracker* studio::App::device_tracker=0;
216 studio::Dialog_Gradient* studio::App::dialog_gradient;
218 studio::Dialog_Color* studio::App::dialog_color;
220 Gtk::InputDialog* studio::App::dialog_input;
222 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
224 studio::Dock_History* dock_history;
225 studio::Dock_Canvases* dock_canvases;
226 studio::Dock_Keyframes* dock_keyframes;
227 studio::Dock_Layers* dock_layers;
228 studio::Dock_Params* dock_params;
229 studio::Dock_MetaData* dock_meta_data;
230 studio::Dock_Children* dock_children;
231 studio::Dock_Info* dock_info;
232 studio::Dock_LayerGroups* dock_layer_groups;
233 studio::Dock_Navigator* dock_navigator;
234 studio::Dock_Timetrack* dock_timetrack;
235 studio::Dock_Curves* dock_curves;
237 std::list< etl::handle< studio::Module > > module_list_;
239 bool studio::App::use_colorspace_gamma=true;
241 static int max_recent_files_=25;
242 int studio::App::get_max_recent_files() { return max_recent_files_; }
243 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
245 static synfig::String app_base_path_;
248 }; // END of namespace studio
249 studio::StateManager* state_manager;
254 class GlobalUIInterface : public synfigapp::UIInterface
258 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
263 true // use_separator
265 Gtk::Label label(message);
268 dialog.get_vbox()->pack_start(label);
269 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
270 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
272 dialog.set_default_response(dflt);
274 return (Response)dialog.run();
276 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
281 true // use_separator
283 Gtk::Label label(message);
286 dialog.get_vbox()->pack_start(label);
287 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
288 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
289 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
291 dialog.set_default_response(dflt);
293 return (Response)dialog.run();
295 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
300 true // use_separator
302 Gtk::Label label(message);
305 dialog.get_vbox()->pack_start(label);
306 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
307 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
309 dialog.set_default_response(dflt);
311 return (Response)dialog.run();
315 task(const std::string &task)
317 std::cerr<<task<<std::endl;
318 while(studio::App::events_pending())studio::App::iteration(false);
323 error(const std::string &err)
328 true // use_separator
330 Gtk::Label label(err);
333 dialog.get_vbox()->pack_start(label);
334 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
341 warning(const std::string &err)
343 std::cerr<<"warning: "<<err<<std::endl;
344 while(studio::App::events_pending())studio::App::iteration(false);
349 amount_complete(int current, int total)
351 while(studio::App::events_pending())studio::App::iteration(false);
356 /* === P R O C E D U R E S ================================================= */
358 typedef unsigned char U8;
359 typedef unsigned short U16;
360 typedef unsigned long U32;
370 static inline U32 hash_U32(U32 i)
372 i=i*1664525+1013904223;
373 i=i*1664525+1013904223;
374 i=i*1664525+1013904223;
379 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
380 #define endian_fix(x) (endian_fix_table[x])
382 #define endian_fix(x) (x)
385 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
388 unwound->element.serial=0;
389 unwound->element.checksum=0;
397 case '0': data=0; break;
398 case '1': data=1; break;
399 case '2': data=2; break;
400 case '3': data=3; break;
401 case '4': data=4; break;
402 case '5': data=5; break;
403 case '6': data=6; break;
404 case '7': data=7; break;
405 case '8': data=8; break;
406 case '9': data=9; break;
407 case 'a': case 'A': data=10; break;
408 case 'b': case 'B': data=11; break;
409 case 'c': case 'C': data=12; break;
410 case 'd': case 'D': data=13; break;
411 case 'e': case 'E': data=14; break;
412 case 'f': case 'F': data=15; break;
413 default: return 0; break;
416 unwound->element.checksum|=(((U32)data&3)<<bit);
417 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
422 int v_key_check(const char* key, U32* serial, U32 appid)
424 V_KeyUnwound unwound_key;
425 U32 appid_mask_a=hash_U32(appid);
426 U32 appid_mask_b=hash_U32(appid_mask_a);
428 if(!v_unwind_key(&unwound_key, key))
430 // Invalid characters in key
435 // Undo obfuscation pass
437 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
442 unwound_key.raw[endian_fix(i)]^=(next>>24);
446 unwound_key.element.serial^=appid_mask_a;
447 unwound_key.element.checksum^=appid_mask_b;
449 *serial=unwound_key.element.serial;
451 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
455 int check_license(String basedir)
457 #ifdef LICENSE_KEY_REQUIRED
462 license_file="/usr/local/etc/.synfiglicense";
464 license_file=basedir+"\\etc\\.synfiglicense";
468 key=Glib::file_get_contents(license_file);
469 } catch (Glib::FileError) { }
471 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
473 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
477 if(!App::dialog_entry(
478 _("Synfig Studio Authentication"),
479 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
482 throw String("No License");
485 FILE* file=fopen(license_file.c_str(),"w");
488 fprintf(file,"%s",key.c_str());
492 synfig::error("Unable to save license key!");
494 synfig::info("License Authenticated -- Serial #%05d",serial);
503 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
505 action_group_list.push_back(action_group);
506 Gtk::UIManager::insert_action_group(action_group, pos);
510 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
512 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
513 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
514 if(*iter==action_group)
516 action_group_list.erase(iter);
517 Gtk::UIManager::remove_action_group(action_group);
520 synfig::error("Unable to find action group");
524 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
526 ui_manager->insert_action_group(group,0);
529 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
530 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
533 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
536 if(*iter && (*iter)->get_name()!="menus")
538 synfig::info("Removing action group "+(*iter)->get_name());
539 ui_manager->remove_action_group(*iter);
543 ui_manager->insert_action_group(group,0);
546 for(;!prev_groups.empty();prev_groups.pop_front())
548 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
549 ui_manager->insert_action_group(prev_groups.front(),1);
554 class Preferences : public synfigapp::Settings
557 virtual bool get_value(const synfig::String& key, synfig::String& value)const
561 value=strprintf("%f %f %f %f",
562 App::gamma.get_gamma_r(),
563 App::gamma.get_gamma_g(),
564 App::gamma.get_gamma_b(),
565 App::gamma.get_black_level()
569 if(key=="time_format")
571 value=strprintf("%i",App::get_time_format());
574 if(key=="file_history.size")
576 value=strprintf("%i",App::get_max_recent_files());
579 if(key=="use_colorspace_gamma")
581 value=strprintf("%i",(int)App::use_colorspace_gamma);
584 if(key=="distance_system")
586 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
589 if(key=="auto_recover_backup_interval")
591 value=strprintf("%i",App::auto_recover->get_timeout());
595 return synfigapp::Settings::get_value(key,value);
598 virtual bool set_value(const synfig::String& key,const synfig::String& value)
604 strscanf(value,"%f %f %f %f",
611 App::gamma.set_all(r,g,b,blk);
615 if(key=="time_format")
617 int i(atoi(value.c_str()));
618 App::set_time_format(static_cast<synfig::Time::Format>(i));
621 if(key=="auto_recover_backup_interval")
623 int i(atoi(value.c_str()));
624 App::auto_recover->set_timeout(i);
627 if(key=="file_history.size")
629 int i(atoi(value.c_str()));
630 App::set_max_recent_files(i);
633 if(key=="use_colorspace_gamma")
635 int i(atoi(value.c_str()));
636 App::use_colorspace_gamma=i;
639 if(key=="distance_system")
641 App::distance_system=Distance::ident_system(value);;
645 return synfigapp::Settings::set_value(key,value);
648 virtual KeyList get_key_list()const
650 KeyList ret(synfigapp::Settings::get_key_list());
651 ret.push_back("gamma");
652 ret.push_back("time_format");
653 ret.push_back("distance_system");
654 ret.push_back("file_history.size");
655 ret.push_back("use_colorspace_gamma");
656 ret.push_back("auto_recover_backup_interval");
661 static Preferences _preferences;
666 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
668 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
670 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
672 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
673 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
674 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
675 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
676 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
677 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
678 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
679 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
680 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
681 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
682 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
683 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
685 // Add the synfigapp actions...
686 synfigapp::Action::Book::iterator iter;
687 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
689 actions_action_group->add(Gtk::Action::create(
690 "action-"+iter->second.name,
691 get_action_stock_id(iter->second),
692 iter->second.local_name,iter->second.local_name
696 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
697 #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); }
698 #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); }
700 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
701 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
702 DEFINE_ACTION("open", Gtk::Stock::OPEN);
703 DEFINE_ACTION("save", Gtk::Stock::SAVE);
704 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
705 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
706 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
707 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
708 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
709 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
710 DEFINE_ACTION("import", _("Import"));
711 DEFINE_ACTION("render", _("Render"));
712 DEFINE_ACTION("preview", _("Preview"));
713 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
714 DEFINE_ACTION("sound", _("Sound File"));
715 DEFINE_ACTION("options", _("Options"));
716 DEFINE_ACTION("close", _("Close"));
719 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
720 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
721 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
722 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
723 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
724 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
725 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
726 DEFINE_ACTION("properties", _("Properties"));
728 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
729 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
730 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
731 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
732 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
733 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
734 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
735 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
736 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
737 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
738 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
739 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
740 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
741 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
742 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
743 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
744 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
745 DEFINE_ACTION("play", _("Play"));
746 DEFINE_ACTION("pause", _("Pause"));
747 DEFINE_ACTION("stop", _("Stop"));
748 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
749 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
750 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
751 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
752 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
753 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
754 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
755 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
756 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
757 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
758 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
759 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
760 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
761 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
762 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
763 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
764 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
765 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
766 DEFINE_ACTION("seek-end", _("Seek to End"));
768 DEFINE_ACTION("action-group_add", _("Add group"));
770 DEFINE_ACTION("canvas-new", _("New Canvas"));
772 DEFINE_ACTION("amount-inc", _("Increase Amount"));
773 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
778 // Set up synfigapp actions
780 synfigapp::Action::Book::iterator iter;
782 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
784 Gtk::StockID stock_id;
786 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
788 //Gtk::Image* image(manage(new Gtk::Image()));
789 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
790 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
791 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
792 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
793 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
794 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
795 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
796 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
797 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
798 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
800 actions_action_group->add(Gtk::Action::create(
801 "action-"+iter->second.name,
803 iter->second.local_name,iter->second.local_name
811 Glib::ustring ui_info =
813 " <popup name='menu-toolbox' action='menu-toolbox'>"
814 " <menu action='menu-file'>"
817 " <popup name='menu-main' action='menu-main'>"
818 " <menu action='menu-file'>"
819 " <menuitem action='save' />"
820 " <menuitem action='save-as' />"
821 " <menuitem action='revert' />"
822 " <separator name='bleh01'/>"
823 " <menuitem action='cvs-add' />"
824 " <menuitem action='cvs-update' />"
825 " <menuitem action='cvs-commit' />"
826 " <menuitem action='cvs-revert' />"
827 " <separator name='bleh02'/>"
828 " <menuitem action='import' />"
829 " <separator name='bleh03'/>"
830 " <menuitem action='render' />"
831 " <menuitem action='preview' />"
832 " <menuitem action='sound' />"
833 " <separator name='bleh04'/>"
834 " <menuitem action='options' />"
835 " <menuitem action='close' />"
837 " <menu action='menu-edit'>"
838 " <menuitem action='undo'/>"
839 " <menuitem action='redo'/>"
840 " <separator name='bleh05'/>"
841 " <menuitem action='cut'/>"
842 " <menuitem action='copy'/>"
843 " <menuitem action='paste'/>"
844 " <separator name='bleh06'/>"
845 " <menuitem action='select-all-ducks'/>"
846 " <menuitem action='unselect-all-layers'/>"
847 " <separator name='bleh07'/>"
848 " <menuitem action='properties'/>"
850 " <menu action='menu-view'>"
851 " <menu action='menu-duck-mask'>"
852 " <menuitem action='mask-position-ducks' />"
853 " <menuitem action='mask-vertex-ducks' />"
854 " <menuitem action='mask-tangent-ducks' />"
855 " <menuitem action='mask-radius-ducks' />"
856 " <menuitem action='mask-width-ducks' />"
857 " <menuitem action='mask-angle-ducks' />"
859 " <menu action='menu-preview-quality'>"
860 " <menuitem action='quality-00' />"
861 " <menuitem action='quality-01' />"
862 " <menuitem action='quality-02' />"
863 " <menuitem action='quality-03' />"
864 " <menuitem action='quality-04' />"
865 " <menuitem action='quality-05' />"
866 " <menuitem action='quality-06' />"
867 " <menuitem action='quality-07' />"
868 " <menuitem action='quality-08' />"
869 " <menuitem action='quality-09' />"
870 " <menuitem action='quality-10' />"
872 " <separator name='bleh08'/>"
873 " <menuitem action='play'/>"
874 " <menuitem action='pause'/>"
875 " <menuitem action='stop'/>"
876 " <menuitem action='dialog-flipbook'/>"
877 " <separator name='bleh09'/>"
878 " <menuitem action='toggle-grid-show'/>"
879 " <menuitem action='toggle-grid-snap'/>"
880 " <menuitem action='toggle-guide-show'/>"
881 " <menuitem action='toggle-low-res'/>"
882 " <menuitem action='toggle-onion-skin'/>"
883 " <separator name='bleh10'/>"
884 " <menuitem action='canvas-zoom-in'/>"
885 " <menuitem action='canvas-zoom-out'/>"
886 " <menuitem action='canvas-zoom-fit'/>"
887 " <menuitem action='canvas-zoom-100'/>"
888 " <separator name='bleh11'/>"
889 " <menuitem action='time-zoom-in'/>"
890 " <menuitem action='time-zoom-out'/>"
891 " <separator name='bleh12'/>"
892 " <menuitem action='jump-next-keyframe'/>"
893 " <menuitem action='jump-prev-keyframe'/>"
894 " <menuitem action='seek-next-frame'/>"
895 " <menuitem action='seek-prev-frame'/>"
896 " <menuitem action='seek-next-second'/>"
897 " <menuitem action='seek-prev-second'/>"
898 " <menuitem action='seek-begin'/>"
899 " <menuitem action='seek-end'/>"
901 " <menu action='menu-canvas'>"
902 " <menuitem action='canvas-new'/>"
903 " <menuitem action='amount-inc'/>"
904 " <menuitem action='amount-dec'/>"
906 " <menu name='menu-state' action='menu-state'>"
908 " <menu action='menu-group'>"
909 " <menuitem action='action-group_add'/>"
911 " <menu action='menu-layer'>"
912 //" <menuitem action='cut'/>"
913 //" <menuitem action='copy'/>"
914 //" <menuitem action='paste'/>"
915 //" <separator name='bleh06'/>"
916 " <menu action='menu-layer-new'></menu>"
918 " <menu action='menu-keyframe'>"
919 " <menuitem action='keyframe-properties'/>"
926 " <menubar name='MenuBar'>"
927 " <menu action='MenuFile'>"
928 " <menuitem action='New'/>"
929 " <menuitem action='Open'/>"
931 " <menuitem action='Quit'/>"
933 " <menu action='MenuEdit'>"
934 " <menuitem action='Cut'/>"
935 " <menuitem action='Copy'/>"
936 " <menuitem action='Paste'/>"
939 " <toolbar name='ToolBar'>"
940 " <toolitem action='Open'/>"
941 " <toolitem action='Quit'/>"
947 actions_action_group->set_sensitive(false);
948 App::ui_manager()->set_add_tearoffs(true);
949 App::ui_manager()->insert_action_group(menus_action_group,1);
950 App::ui_manager()->insert_action_group(actions_action_group,1);
951 App::ui_manager()->add_ui_from_string(ui_info);
953 //App::ui_manager()->get_accel_group()->unlock();
955 catch(const Glib::Error& ex)
957 synfig::error("building menus and toolbars failed: " + ex.what());
960 // Add default keyboard accelerators
961 #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()); }
962 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
963 ACCEL("<Actions>//select-all-ducks","<Control>a");
964 ACCEL("<Actions>//unselect-all-layers","<Control>d");
965 ACCEL("<Actions>//render","F9");
966 ACCEL("<Actions>//preview","F11");
967 ACCEL("<Actions>//properties","F8");
968 ACCEL("<Actions>//options","F12");
969 ACCEL("<Actions>//import","<control>i");
970 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
971 ACCEL("<Actions>//toggle-grid-show","<Control>g");
972 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
973 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
974 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
975 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
976 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
977 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
978 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
979 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
982 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
983 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
985 ACCEL("<Actions>//quality-01","<Control>1");
986 ACCEL("<Actions>//quality-02","<Control>2");
987 ACCEL("<Actions>//quality-03","<Control>3");
988 ACCEL("<Actions>//quality-04","<Control>4");
989 ACCEL("<Actions>//quality-05","<Control>5");
990 ACCEL("<Actions>//quality-06","<Control>6");
991 ACCEL("<Actions>//quality-07","<Control>7");
992 ACCEL("<Actions>//quality-08","<Control>8");
993 ACCEL("<Actions>//quality-09","<Control>9");
994 ACCEL("<Actions>//quality-10","<Control>0");
995 ACCEL("<Actions>//undo","<Control>z");
996 ACCEL("<Actions>//redo","<Control>r");
997 ACCEL("<Actions>//action-layer_remove","Delete");
999 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1000 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1001 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1002 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1003 ACCEL("<Actions>//time-zoom-in","+");
1004 ACCEL("<Actions>//time-zoom-out","_");
1006 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1007 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1009 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1010 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1011 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1012 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1013 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1014 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1015 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1016 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1017 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1018 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1019 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1020 ACCEL("<Actions>//seek-begin","Home");
1021 ACCEL("<Actions>//seek-end","End");
1022 ACCEL("<Actions>//state-normal","<Mod1>a");
1023 ACCEL("<Actions>//state-rotate","<Mod1>s");
1024 ACCEL("<Actions>//state-scale","<Mod1>d");
1025 ACCEL("<Actions>//state-bline","<Mod1>b");
1026 ACCEL("<Actions>//state-fill","<Mod1>f");
1027 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1028 ACCEL("<Actions>//state-gradient","<Mod1>g");
1029 ACCEL("<Actions>//state-zoom","<Mod1>z");
1030 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1036 #define mkdir(x,y) mkdir(x)
1039 /* === M E T H O D S ======================================================= */
1041 App::App(int *argc, char ***argv):
1042 Gtk::Main(argc,argv),
1043 IconControler(etl::dirname((*argv)[0]))
1045 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1048 serial_=check_license(app_base_path_);
1051 ui_interface_=new GlobalUIInterface();
1055 Glib::thread_init();
1057 distance_system=Distance::SYSTEM_UNITS;
1059 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1062 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1066 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1074 if(!SYNFIG_CHECK_VERSION())
1076 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1077 dialog_error_blocking("SYNFIG Studio",
1078 "This copy of SYNFIG Studio was compiled against a\n"
1079 "different version of libsynfig than what is currently\n"
1080 "installed. Synfig Studio will now abort. Try downloading\n"
1081 "the latest version from the SYNFIG Development Website at\n"
1082 "http://dev.synfig.com/ "
1087 catch(synfig::SoftwareExpired)
1089 cerr<<"FATAL: Software Expired"<<endl;
1090 dialog_error_blocking("SYNFIG Studio",
1091 "This copy of SYNFIG Studio has expired.\n"
1092 "Please erase this copy, or download and\n"
1093 "install the latest copy from the SYNFIG\n"
1094 "Development Website at http://dev.synfig.com/ ."
1098 Glib::set_application_name(_("SYNFIG Studio"));
1101 about_window.set_can_self_destruct(false);
1102 about_window.show();
1104 shutdown_in_progress=false;
1105 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1106 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1108 // Initialize the Synfig library
1109 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1112 get_ui_interface()->error("Failed to initialize synfig!");
1116 // add the preferences to the settings
1117 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1121 studio_init_cb.task("Init UI Manager...");
1122 App::ui_manager_=studio::UIManager::create();
1125 studio_init_cb.task("Init Dock Manager...");
1126 dock_manager=new studio::DockManager();
1128 studio_init_cb.task("Init State Manager...");
1129 state_manager=new StateManager();
1131 studio_init_cb.task("Init Toolbox...");
1132 toolbox=new studio::Toolbox();
1134 studio_init_cb.task("Init Tool Options...");
1135 dialog_tool_options=new studio::Dialog_ToolOptions();
1136 dock_manager->register_dockable(*dialog_tool_options);
1138 studio_init_cb.task("Init History...");
1139 dock_history=new studio::Dock_History();
1140 dock_manager->register_dockable(*dock_history);
1142 studio_init_cb.task("Init Canvases...");
1143 dock_canvases=new studio::Dock_Canvases();
1144 dock_manager->register_dockable(*dock_canvases);
1146 studio_init_cb.task("Init Keyframes...");
1147 dock_keyframes=new studio::Dock_Keyframes();
1148 dock_manager->register_dockable(*dock_keyframes);
1150 studio_init_cb.task("Init Layers...");
1151 dock_layers=new studio::Dock_Layers();
1152 dock_manager->register_dockable(*dock_layers);
1154 studio_init_cb.task("Init Params...");
1155 dock_params=new studio::Dock_Params();
1156 dock_manager->register_dockable(*dock_params);
1158 studio_init_cb.task("Init MetaData...");
1159 dock_meta_data=new studio::Dock_MetaData();
1160 dock_manager->register_dockable(*dock_meta_data);
1162 studio_init_cb.task("Init Children...");
1163 dock_children=new studio::Dock_Children();
1164 dock_manager->register_dockable(*dock_children);
1166 studio_init_cb.task("Init Info...");
1167 dock_info = new studio::Dock_Info();
1168 dock_manager->register_dockable(*dock_info);
1170 studio_init_cb.task("Init Navigator...");
1171 dock_navigator = new studio::Dock_Navigator();
1172 dock_manager->register_dockable(*dock_navigator);
1174 studio_init_cb.task("Init Timetrack...");
1175 dock_timetrack = new studio::Dock_Timetrack();
1176 dock_manager->register_dockable(*dock_timetrack);
1178 studio_init_cb.task("Init Curve Editor...");
1179 dock_curves = new studio::Dock_Curves();
1180 dock_manager->register_dockable(*dock_curves);
1182 studio_init_cb.task("Init Layer Groups...");
1183 dock_layer_groups = new studio::Dock_LayerGroups();
1184 dock_manager->register_dockable(*dock_layer_groups);
1187 studio_init_cb.task("Init Color Dialog...");
1188 dialog_color=new studio::Dialog_Color();
1190 studio_init_cb.task("Init Gradient Dialog...");
1191 dialog_gradient=new studio::Dialog_Gradient();
1193 studio_init_cb.task("Init DeviceTracker...");
1194 device_tracker=new studio::DeviceTracker();
1196 studio_init_cb.task("Init Tools...");
1197 state_manager->add_state(&state_normal);
1198 state_manager->add_state(&state_smooth_move);
1199 state_manager->add_state(&state_scale);
1200 state_manager->add_state(&state_rotate);
1202 state_manager->add_state(&state_bline);
1203 state_manager->add_state(&state_polygon);
1204 state_manager->add_state(&state_circle);
1205 state_manager->add_state(&state_rectangle);
1207 state_manager->add_state(&state_draw);
1208 state_manager->add_state(&state_sketch);
1210 state_manager->add_state(&state_eyedrop);
1211 state_manager->add_state(&state_fill);
1213 state_manager->add_state(&state_width);
1214 state_manager->add_state(&state_gradient);
1216 state_manager->add_state(&state_zoom);
1218 studio_init_cb.task("Init ModPalette...");
1219 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1221 studio_init_cb.task("Init ModMirror...");
1222 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1225 studio_init_cb.task("Init Setup Dialog...");
1226 dialog_setup=new studio::Dialog_Setup();
1228 studio_init_cb.task("Init Input Dialog...");
1229 dialog_input=new Gtk::InputDialog();
1231 studio_init_cb.task("Init auto recovery...");
1232 auto_recover=new AutoRecover();
1234 studio_init_cb.amount_complete(9250,10000);
1235 studio_init_cb.task("Loading Settings...");
1237 studio_init_cb.task("Checking auto-recover...");
1239 studio_init_cb.amount_complete(9900,10000);
1241 if(auto_recover->recovery_needed())
1243 about_window.hide();
1245 get_ui_interface()->yes_no(
1247 "SYNFIG Studio seems to have crashed\n"
1248 "before you could save all your files.\n"
1249 "Would you like to re-open those files\n"
1250 "and recover your unsaved changes?"
1251 )==synfigapp::UIInterface::RESPONSE_YES
1254 if(!auto_recover->recover())
1256 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1259 get_ui_interface()->error(
1260 _("SYNFIG Studio has attempted to recover\n"
1261 "from a previous crash. The files that it has\n"
1262 "recovered are NOT YET SAVED. It would be a good\n"
1263 "idea to review them and save them now.")
1266 about_window.show();
1269 // Look for any files given on the command line,
1270 // and load them if found.
1271 for(;*argc>=1;(*argc)--)
1272 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1274 studio_init_cb.task("Loading files...");
1275 about_window.hide();
1276 open((*argv)[*argc]);
1277 about_window.show();
1280 studio_init_cb.task("Done.");
1281 studio_init_cb.amount_complete(10000,10000);
1287 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1291 StateManager* App::get_state_manager() { return state_manager; }
1295 shutdown_in_progress=true;
1299 synfigapp::Main::settings().remove_domain("pref");
1301 selected_instance=0;
1303 // Unload all of the modules
1304 for(;!module_list_.empty();module_list_.pop_back());
1306 delete state_manager;
1310 delete auto_recover;
1314 // studio::App::iteration(false);
1318 // studio::App::iteration(false);
1320 // studio::App::iteration(false);
1322 delete dialog_setup;
1324 delete dialog_gradient;
1326 delete dialog_color;
1328 delete dialog_input;
1330 delete dock_manager;
1332 instance_list.clear();
1334 // studio::App::iteration(false);
1338 App::get_user_app_directory()
1341 return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
1343 return Glib::build_filename(Glib::get_home_dir(),"Synfig");
1348 App::get_config_file(const synfig::String& file)
1350 return Glib::build_filename(get_user_app_directory(),file);
1354 App::add_recent_file(const std::string &file_name)
1356 std::string filename(file_name);
1358 assert(!filename.empty());
1360 if(filename.empty())
1363 // Toss out any "hidden" files
1364 if(basename(filename)[0]=='.')
1367 // If we aren't an absolute path, turn outselves into one
1368 if(!is_absolute_path(filename))
1369 filename=absolute_path(filename);
1371 list<string>::iterator iter;
1372 // Check to see if the file is already on the list.
1373 // If it is, then remove it from the list
1374 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1377 recent_files.erase(iter);
1382 // Push the filename to the front of the list
1383 recent_files.push_front(filename);
1385 // Clean out the files at the end of the list.
1386 while(recent_files.size()>(unsigned)get_max_recent_files())
1387 recent_files.pop_back();
1389 signal_recent_files_changed_();
1394 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1397 App::get_time_format()
1399 return _App_time_format;
1403 App::set_time_format(synfig::Time::Format x)
1410 App::save_settings()
1415 std::string filename=get_config_file("accelrc");
1416 Gtk::AccelMap::save(filename);
1419 std::string filename=get_config_file("recentfiles");
1421 std::ofstream file(filename.c_str());
1425 synfig::warning("Unable to save %s",filename.c_str());
1429 list<string>::reverse_iterator iter;
1431 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1435 std::string filename=get_config_file("settings");
1436 synfigapp::Main::settings().save_to_file(filename);
1440 synfig::warning("Caught exception when attempting to save settings.");
1445 App::load_settings()
1450 std::string filename=get_config_file("accelrc");
1451 Gtk::AccelMap::load(filename);
1454 std::string filename=get_config_file("recentfiles");
1456 std::ifstream file(filename.c_str());
1460 std::string recent_file;
1461 getline(file,recent_file);
1462 if(!recent_file.empty())
1463 add_recent_file(recent_file);
1466 std::string filename=get_config_file("settings");
1467 if(!synfigapp::Main::settings().load_from_file(filename))
1469 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1470 //if(!synfigapp::Main::settings().load_from_file(filename))
1472 gamma.set_gamma(1.0/2.2);
1473 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1474 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1475 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1476 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1477 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1478 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1479 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1480 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1481 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1482 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1483 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1484 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1485 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1492 synfig::warning("Caught exception when attempting to load settings.");
1497 App::shutdown_request(GdkEventAny*)
1501 //return !shutdown_in_progress;
1507 if(shutdown_in_progress)return;
1510 get_ui_interface()->task("Quit Request");
1513 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1517 std::list<etl::handle<Instance> >::iterator iter;
1518 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1520 if(!(*iter)->safe_close())
1524 if((*iter)->synfigapp::Instance::get_action_count())
1526 handle<synfigapp::UIInterface> uim;
1527 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1529 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1530 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1532 case synfigapp::UIInterface::RESPONSE_NO:
1534 case synfigapp::UIInterface::RESPONSE_YES:
1537 case synfigapp::UIInterface::RESPONSE_CANCEL:
1546 if((*iter)->synfigapp::Instance::is_modified())
1548 handle<synfigapp::UIInterface> uim;
1549 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1551 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() );
1552 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1554 case synfigapp::UIInterface::RESPONSE_NO:
1556 case synfigapp::UIInterface::RESPONSE_YES:
1557 (*iter)->dialog_cvs_commit();
1559 case synfigapp::UIInterface::RESPONSE_CANCEL:
1568 // This next line causes things to crash for some reason
1572 shutdown_in_progress=true;
1574 instance_list.clear();
1576 while(studio::App::events_pending())studio::App::iteration(false);
1579 auto_recover->normal_shutdown();
1581 get_ui_interface()->task("Quit Request sent");
1587 dialog_setup->refresh();
1588 dialog_setup->show();
1591 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1592 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1595 //#define USE_WIN32_FILE_DIALOGS 1
1598 #ifdef USE_WIN32_FILE_DIALOGS
1599 static OPENFILENAME ofn={};
1603 #include <gdk/gdkwin32.h>
1607 App::dialog_open_file(const std::string &title, std::string &filename)
1609 #ifdef USE_WIN32_FILE_DIALOGS
1610 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1612 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1613 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1614 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1616 ofn.lStructSize=sizeof(OPENFILENAME);
1617 ofn.hwndOwner = hWnd;
1618 ofn.hInstance = hInstance;
1619 ofn.lpstrFilter = szFilter;
1620 // ofn.lpstrCustomFilter=NULL;
1621 // ofn.nMaxCustFilter=0;
1622 // ofn.nFilterIndex=0;
1623 // ofn.lpstrFile=NULL;
1624 ofn.nMaxFile=MAX_PATH;
1625 // ofn.lpstrFileTitle=NULL;
1626 // ofn.lpstrInitialDir=NULL;
1627 // ofn.lpstrTitle=NULL;
1628 ofn.Flags=OFN_HIDEREADONLY;
1629 // ofn.nFileOffset=0;
1630 // ofn.nFileExtension=0;
1631 ofn.lpstrDefExt=TEXT("sif");
1632 // ofn.lCustData = 0l;
1634 // ofn.lpTemplateName=NULL;
1636 CHAR szFilename[MAX_PATH];
1638 strcpy(szFilename,filename.c_str());
1639 strcpy(szTitle,title.c_str());
1641 ofn.lpstrFile=szFilename;
1642 ofn.lpstrFileTitle=szTitle;
1644 if(GetOpenFileName(&ofn))
1646 filename=szFilename;
1652 synfig::String prev_path;
1653 if(!_preferences.get_value("curr_path",prev_path))
1660 GtkWidget *fileselection;
1661 fileselection = gtk_file_selection_new(title.c_str());
1664 if(basename(filename)==filename)
1666 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1669 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1671 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1673 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1674 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1676 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1677 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1679 gtk_widget_show(fileselection);
1687 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1688 _preferences.set_value("curr_path",dirname(filename));
1692 gtk_widget_destroy(fileselection);
1695 gtk_widget_destroy(fileselection);
1701 App::dialog_save_file(const std::string &title, std::string &filename)
1703 #ifdef USE_WIN32_FILE_DIALOGS
1704 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1706 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1707 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1708 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1710 ofn.lStructSize=sizeof(OPENFILENAME);
1711 ofn.hwndOwner = hWnd;
1712 ofn.hInstance = hInstance;
1713 ofn.lpstrFilter = szFilter;
1714 // ofn.lpstrCustomFilter=NULL;
1715 // ofn.nMaxCustFilter=0;
1716 // ofn.nFilterIndex=0;
1717 // ofn.lpstrFile=NULL;
1718 ofn.nMaxFile=MAX_PATH;
1719 // ofn.lpstrFileTitle=NULL;
1720 // ofn.lpstrInitialDir=NULL;
1721 // ofn.lpstrTitle=NULL;
1722 ofn.Flags=OFN_OVERWRITEPROMPT;
1723 // ofn.nFileOffset=0;
1724 // ofn.nFileExtension=0;
1725 ofn.lpstrDefExt=TEXT("sif");
1726 // ofn.lCustData = 0l;
1728 // ofn.lpTemplateName=NULL;
1730 CHAR szFilename[MAX_PATH];
1732 strcpy(szFilename,filename.c_str());
1733 strcpy(szTitle,title.c_str());
1735 ofn.lpstrFile=szFilename;
1736 ofn.lpstrFileTitle=szTitle;
1738 if(GetSaveFileName(&ofn))
1740 filename=szFilename;
1745 return dialog_open_file(title, filename);
1750 App::dialog_saveas_file(const std::string &title, std::string &filename)
1752 #if USE_WIN32_FILE_DIALOGS
1753 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1755 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1756 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1757 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1759 ofn.lStructSize=sizeof(OPENFILENAME);
1760 ofn.hwndOwner = hWnd;
1761 ofn.hInstance = hInstance;
1762 ofn.lpstrFilter = szFilter;
1763 // ofn.lpstrCustomFilter=NULL;
1764 // ofn.nMaxCustFilter=0;
1765 // ofn.nFilterIndex=0;
1766 // ofn.lpstrFile=NULL;
1767 ofn.nMaxFile=MAX_PATH;
1768 // ofn.lpstrFileTitle=NULL;
1769 // ofn.lpstrInitialDir=NULL;
1770 // ofn.lpstrTitle=NULL;
1771 ofn.Flags=OFN_OVERWRITEPROMPT;
1772 // ofn.nFileOffset=0;
1773 // ofn.nFileExtension=0;
1774 ofn.lpstrDefExt=TEXT("sif");
1775 // ofn.lCustData = 0l;
1777 // ofn.lpTemplateName=NULL;
1779 CHAR szFilename[MAX_PATH];
1781 strcpy(szFilename,filename.c_str());
1782 strcpy(szTitle,title.c_str());
1784 ofn.lpstrFile=szFilename;
1785 ofn.lpstrFileTitle=szTitle;
1787 if(GetSaveFileName(&ofn))
1789 filename=szFilename;
1794 return dialog_open_file(title, filename);
1799 App::dialog_error_blocking(const std::string &title, const std::string &message)
1804 true // use_separator
1806 Gtk::Label label(message);
1809 dialog.get_vbox()->pack_start(label);
1810 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1816 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1821 true // use_separator
1823 Gtk::Label label(message);
1826 dialog.get_vbox()->pack_start(label);
1827 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1833 App::dialog_yes_no(const std::string &title, const std::string &message)
1838 true // use_separator
1840 Gtk::Label label(message);
1843 dialog.get_vbox()->pack_start(label);
1844 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1845 dialog.add_button(Gtk::StockID("gtk-no"),0);
1847 return dialog.run();
1851 App::dialog_yes_no_cancel(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-yes"),1);
1863 dialog.add_button(Gtk::StockID("gtk-no"),0);
1864 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1866 return dialog.run();
1870 App::dialog_not_implemented()
1873 "Feature not available", // Title
1875 true // use_separator
1877 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1880 dialog.get_vbox()->pack_start(label);
1881 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1887 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1892 true // use_separator
1894 Gtk::Label label(message);
1896 dialog.get_vbox()->pack_start(label);
1899 entry.set_text(text);
1901 entry.set_activates_default(true);
1902 dialog.get_vbox()->pack_start(entry);
1904 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1905 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1906 dialog.set_default_response(Gtk::RESPONSE_OK);
1907 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1910 if(dialog.run()!=Gtk::RESPONSE_OK)
1913 text=entry.get_text();
1922 App::open(std::string filename)
1924 return open_as(filename,filename);
1928 App::open_as(std::string filename,std::string as)
1932 OneMoment one_moment;
1934 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1935 if(canvas && get_instance(canvas))
1937 get_instance(canvas)->find_canvas_view(canvas)->present();
1938 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1941 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1943 add_recent_file(as);
1945 handle<Instance> instance(Instance::create(canvas));
1948 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1952 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)")))
1953 instance->dialog_cvs_update();
1957 dialog_error_blocking(_("Error"), x);
1962 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1966 _preferences.set_value("curr_path",dirname(as));
1975 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1976 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
1978 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
1980 canvas->rend_desc().set_frame_rate(24.0);
1981 canvas->rend_desc().set_time_start(0.0);
1982 canvas->rend_desc().set_time_end(00.0);
1983 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1984 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1985 canvas->rend_desc().set_tl(Vector(-4,2.25));
1986 canvas->rend_desc().set_br(Vector(4,-2.25));
1987 canvas->rend_desc().set_w(480);
1988 canvas->rend_desc().set_h(270);
1989 canvas->rend_desc().set_antialias(1);
1990 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1991 canvas->set_file_name(file_name);
1993 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
1999 string filename="*.sif";
2001 while(dialog_open_file("Open", filename))
2003 // If the filename still has wildcards, then we should
2004 // continue looking for the file we want
2005 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2011 get_ui_interface()->error(_("Unable to open file"));
2016 App::set_selected_instance(etl::loose_handle<Instance> instance)
2018 /* if(get_selected_instance()==instance)
2020 selected_instance=instance;
2021 signal_instance_selected()(instance);
2027 selected_instance=instance;
2028 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2032 instance->focus(instance->get_canvas());
2035 set_selected_canvas_view(0);
2037 signal_instance_selected()(instance);
2041 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2043 selected_canvas_view=canvas_view;
2044 signal_canvas_view_focus()(selected_canvas_view);
2047 selected_instance=canvas_view->get_instance();
2048 signal_instance_selected()(canvas_view->get_instance());
2051 if(get_selected_canvas_view()==canvas_view)
2053 signal_canvas_view_focus()(selected_canvas_view);
2054 signal_instance_selected()(canvas_view->get_instance());
2057 selected_canvas_view=canvas_view;
2058 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2059 set_selected_instance(canvas_view->get_instance());
2060 signal_canvas_view_focus()(selected_canvas_view);
2064 etl::loose_handle<Instance>
2065 App::get_instance(Canvas::Handle canvas)
2067 if(!canvas) return 0;
2068 canvas=canvas->get_root();
2070 std::list<etl::handle<Instance> >::iterator iter;
2071 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2073 if((*iter)->get_canvas()==canvas)
2082 (new class About())->show();
2088 if(selected_instance)
2089 selected_instance->undo();
2095 if(selected_instance)
2096 selected_instance->redo();
2100 studio::App::get_base_path()
2102 return app_base_path_;