1 /* === S Y N F I G ========================================================= */
5 ** $Id: app.cpp,v 1.11 2005/03/24 21:47:28 darco Exp $
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
35 #ifdef HAVE_SYS_ERRNO_H
36 #include <sys/errno.h>
38 #include <gtkmm/fileselection.h>
39 #include <gtkmm/dialog.h>
40 #include <gtkmm/label.h>
41 #include <gtkmm/stock.h>
42 #include <gtkmm/stockitem.h>
43 #include <gtkmm/iconsource.h>
44 #include <gtkmm/inputdialog.h>
45 #include <gtkmm/accelmap.h>
46 #include <gtkmm/uimanager.h>
50 #include <synfig/loadcanvas.h>
55 #include "canvasview.h"
56 #include "dialog_setup.h"
57 #include "dialog_gradient.h"
58 #include "dialog_color.h"
61 #include "onemoment.h"
63 #include "dockmanager.h"
65 #include "state_eyedrop.h"
66 #include "state_normal.h"
67 #include "state_draw.h"
68 #include "state_fill.h"
69 #include "state_bline.h"
70 #include "state_polygon.h"
71 #include "state_sketch.h"
72 #include "state_gradient.h"
73 #include "state_circle.h"
74 #include "state_rectangle.h"
75 #include "state_smoothmove.h"
76 #include "state_scale.h"
77 #include "state_width.h"
78 #include "state_rotate.h"
79 #include "state_zoom.h"
81 #include "devicetracker.h"
82 #include "dialog_tooloptions.h"
84 #include "autorecover.h"
86 #include <synfigapp/settings.h>
87 #include "dock_history.h"
88 #include "dock_canvases.h"
89 #include "dock_keyframes.h"
90 #include "dock_layers.h"
91 #include "dock_params.h"
92 #include "dock_metadata.h"
93 #include "dock_children.h"
94 #include "dock_info.h"
95 #include "dock_navigator.h"
96 #include "dock_layergroups.h"
97 #include "dock_timetrack.h"
98 #include "dock_curves.h"
100 #include "mod_palette/mod_palette.h"
101 #include "mod_mirror/mod_mirror.h"
103 #include <sys/stat.h>
109 #include "statemanager.h"
116 #define _WIN32_WINNT 0x0500
119 #include <gtkmm/accelmap.h>
120 #include <gtkmm/filechooser.h>
121 #include <gtkmm/filechooserdialog.h>
125 /* === U S I N G =========================================================== */
129 using namespace synfig;
130 using namespace studio;
132 /* === M A C R O S ========================================================= */
135 #define DPM2DPI(x) (float(x)/39.3700787402f)
136 #define DPI2DPM(x) (float(x)*39.3700787402f)
142 # define IMAGE_DIR "share\\pixmaps"
147 # define IMAGE_DIR "/usr/local/share/pixmaps"
151 # define IMAGE_EXT "tif"
154 #include <synfigapp/main.h>
156 /* === S I G N A L S ======================================================= */
158 static sigc::signal<void> signal_present_all_;
160 App::signal_present_all() { return signal_present_all_; }
162 static sigc::signal<void> signal_recent_files_changed_;
164 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
166 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
167 sigc::signal<void,etl::loose_handle<CanvasView> >&
168 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
170 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
171 sigc::signal<void,etl::handle<Instance> >&
172 App::signal_instance_selected() { return signal_instance_selected_; }
174 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
175 sigc::signal<void,etl::handle<Instance> >&
176 App::signal_instance_created() { return signal_instance_created_; }
178 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
179 sigc::signal<void,etl::handle<Instance> >&
180 App::signal_instance_deleted() { return signal_instance_deleted_; }
182 /* === G L O B A L S ======================================================= */
184 static std::list<std::string> recent_files;
185 const std::list<std::string>& App::get_recent_files() { return recent_files; }
187 int App::Busy::count;
188 bool App::shutdown_in_progress;
190 synfig::Gamma App::gamma;
192 Glib::RefPtr<studio::UIManager> App::ui_manager_;
194 synfig::Distance::System App::distance_system;
196 studio::Dialog_Setup* App::dialog_setup;
198 etl::handle< studio::ModPalette > mod_palette_;
199 //studio::Dialog_Palette* App::dialog_palette;
201 std::list<etl::handle<Instance> > App::instance_list;
203 static etl::handle<synfigapp::UIInterface> ui_interface_;
204 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
206 etl::handle<Instance> App::selected_instance;
207 etl::handle<CanvasView> App::selected_canvas_view;
209 studio::Toolbox *studio::App::toolbox=NULL;
211 studio::AutoRecover *studio::App::auto_recover=NULL;
213 studio::IPC *ipc=NULL;
215 studio::DockManager* studio::App::dock_manager=0;
217 studio::DeviceTracker* studio::App::device_tracker=0;
219 studio::Dialog_Gradient* studio::App::dialog_gradient;
221 studio::Dialog_Color* studio::App::dialog_color;
223 Gtk::InputDialog* studio::App::dialog_input;
225 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
227 studio::Dock_History* dock_history;
228 studio::Dock_Canvases* dock_canvases;
229 studio::Dock_Keyframes* dock_keyframes;
230 studio::Dock_Layers* dock_layers;
231 studio::Dock_Params* dock_params;
232 studio::Dock_MetaData* dock_meta_data;
233 studio::Dock_Children* dock_children;
234 studio::Dock_Info* dock_info;
235 studio::Dock_LayerGroups* dock_layer_groups;
236 studio::Dock_Navigator* dock_navigator;
237 studio::Dock_Timetrack* dock_timetrack;
238 studio::Dock_Curves* dock_curves;
240 std::list< etl::handle< studio::Module > > module_list_;
242 bool studio::App::use_colorspace_gamma=true;
244 static int max_recent_files_=25;
245 int studio::App::get_max_recent_files() { return max_recent_files_; }
246 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
248 static synfig::String app_base_path_;
251 }; // END of namespace studio
252 studio::StateManager* state_manager;
257 class GlobalUIInterface : public synfigapp::UIInterface
261 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
266 true // use_separator
268 Gtk::Label label(message);
271 dialog.get_vbox()->pack_start(label);
272 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
273 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
275 dialog.set_default_response(dflt);
277 return (Response)dialog.run();
279 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
284 true // use_separator
286 Gtk::Label label(message);
289 dialog.get_vbox()->pack_start(label);
290 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
291 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
292 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
294 dialog.set_default_response(dflt);
296 return (Response)dialog.run();
298 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
303 true // use_separator
305 Gtk::Label label(message);
308 dialog.get_vbox()->pack_start(label);
309 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
310 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
312 dialog.set_default_response(dflt);
314 return (Response)dialog.run();
318 task(const std::string &task)
320 std::cerr<<task<<std::endl;
321 while(studio::App::events_pending())studio::App::iteration(false);
326 error(const std::string &err)
331 true // use_separator
333 Gtk::Label label(err);
336 dialog.get_vbox()->pack_start(label);
337 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
344 warning(const std::string &err)
346 std::cerr<<"warning: "<<err<<std::endl;
347 while(studio::App::events_pending())studio::App::iteration(false);
352 amount_complete(int current, int total)
354 while(studio::App::events_pending())studio::App::iteration(false);
359 /* === P R O C E D U R E S ================================================= */
361 typedef unsigned char U8;
362 typedef unsigned short U16;
363 typedef unsigned long U32;
373 static inline U32 hash_U32(U32 i)
375 i=i*1664525+1013904223;
376 i=i*1664525+1013904223;
377 i=i*1664525+1013904223;
382 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
383 #define endian_fix(x) (endian_fix_table[x])
385 #define endian_fix(x) (x)
388 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
391 unwound->element.serial=0;
392 unwound->element.checksum=0;
400 case '0': data=0; break;
401 case '1': data=1; break;
402 case '2': data=2; break;
403 case '3': data=3; break;
404 case '4': data=4; break;
405 case '5': data=5; break;
406 case '6': data=6; break;
407 case '7': data=7; break;
408 case '8': data=8; break;
409 case '9': data=9; break;
410 case 'a': case 'A': data=10; break;
411 case 'b': case 'B': data=11; break;
412 case 'c': case 'C': data=12; break;
413 case 'd': case 'D': data=13; break;
414 case 'e': case 'E': data=14; break;
415 case 'f': case 'F': data=15; break;
416 default: return 0; break;
419 unwound->element.checksum|=(((U32)data&3)<<bit);
420 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
425 int v_key_check(const char* key, U32* serial, U32 appid)
427 V_KeyUnwound unwound_key;
428 U32 appid_mask_a=hash_U32(appid);
429 U32 appid_mask_b=hash_U32(appid_mask_a);
431 if(!v_unwind_key(&unwound_key, key))
433 // Invalid characters in key
438 // Undo obfuscation pass
440 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
445 unwound_key.raw[endian_fix(i)]^=(next>>24);
449 unwound_key.element.serial^=appid_mask_a;
450 unwound_key.element.checksum^=appid_mask_b;
452 *serial=unwound_key.element.serial;
454 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
458 int check_license(String basedir)
460 #ifdef LICENSE_KEY_REQUIRED
465 license_file="/usr/local/etc/.synfiglicense";
467 license_file=basedir+"\\etc\\.synfiglicense";
471 key=Glib::file_get_contents(license_file);
472 } catch (Glib::FileError) { }
474 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
476 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
480 if(!App::dialog_entry(
481 _("Synfig Studio Authentication"),
482 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
485 throw String("No License");
488 FILE* file=fopen(license_file.c_str(),"w");
491 fprintf(file,"%s",key.c_str());
495 synfig::error("Unable to save license key!");
497 synfig::info("License Authenticated -- Serial #%05d",serial);
506 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
508 action_group_list.push_back(action_group);
509 Gtk::UIManager::insert_action_group(action_group, pos);
513 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
515 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
516 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
517 if(*iter==action_group)
519 action_group_list.erase(iter);
520 Gtk::UIManager::remove_action_group(action_group);
523 synfig::error("Unable to find action group");
527 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
529 ui_manager->insert_action_group(group,0);
532 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
533 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
536 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
539 if(*iter && (*iter)->get_name()!="menus")
541 synfig::info("Removing action group "+(*iter)->get_name());
542 ui_manager->remove_action_group(*iter);
546 ui_manager->insert_action_group(group,0);
549 for(;!prev_groups.empty();prev_groups.pop_front())
551 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
552 ui_manager->insert_action_group(prev_groups.front(),1);
557 class Preferences : public synfigapp::Settings
560 virtual bool get_value(const synfig::String& key, synfig::String& value)const
564 value=strprintf("%f %f %f %f",
565 App::gamma.get_gamma_r(),
566 App::gamma.get_gamma_g(),
567 App::gamma.get_gamma_b(),
568 App::gamma.get_black_level()
572 if(key=="time_format")
574 value=strprintf("%i",App::get_time_format());
577 if(key=="file_history.size")
579 value=strprintf("%i",App::get_max_recent_files());
582 if(key=="use_colorspace_gamma")
584 value=strprintf("%i",(int)App::use_colorspace_gamma);
587 if(key=="distance_system")
589 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
592 if(key=="auto_recover_backup_interval")
594 value=strprintf("%i",App::auto_recover->get_timeout());
598 return synfigapp::Settings::get_value(key,value);
601 virtual bool set_value(const synfig::String& key,const synfig::String& value)
607 strscanf(value,"%f %f %f %f",
614 App::gamma.set_all(r,g,b,blk);
618 if(key=="time_format")
620 int i(atoi(value.c_str()));
621 App::set_time_format(static_cast<synfig::Time::Format>(i));
624 if(key=="auto_recover_backup_interval")
626 int i(atoi(value.c_str()));
627 App::auto_recover->set_timeout(i);
630 if(key=="file_history.size")
632 int i(atoi(value.c_str()));
633 App::set_max_recent_files(i);
636 if(key=="use_colorspace_gamma")
638 int i(atoi(value.c_str()));
639 App::use_colorspace_gamma=i;
642 if(key=="distance_system")
644 App::distance_system=Distance::ident_system(value);;
648 return synfigapp::Settings::set_value(key,value);
651 virtual KeyList get_key_list()const
653 KeyList ret(synfigapp::Settings::get_key_list());
654 ret.push_back("gamma");
655 ret.push_back("time_format");
656 ret.push_back("distance_system");
657 ret.push_back("file_history.size");
658 ret.push_back("use_colorspace_gamma");
659 ret.push_back("auto_recover_backup_interval");
664 static ::Preferences _preferences;
669 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
671 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
673 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
675 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
676 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
677 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
678 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
679 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
680 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
681 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
682 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
683 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
684 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
685 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
686 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
688 // Add the synfigapp actions...
689 synfigapp::Action::Book::iterator iter;
690 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
692 actions_action_group->add(Gtk::Action::create(
693 "action-"+iter->second.name,
694 get_action_stock_id(iter->second),
695 iter->second.local_name,iter->second.local_name
699 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
700 #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); }
701 #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); }
703 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
704 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
705 DEFINE_ACTION("open", Gtk::Stock::OPEN);
706 DEFINE_ACTION("save", Gtk::Stock::SAVE);
707 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
708 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
709 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
710 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
711 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
712 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
713 DEFINE_ACTION("import", _("Import"));
714 DEFINE_ACTION("render", _("Render"));
715 DEFINE_ACTION("preview", _("Preview"));
716 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
717 DEFINE_ACTION("sound", _("Sound File"));
718 DEFINE_ACTION("options", _("Options"));
719 DEFINE_ACTION("close", _("Close"));
722 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
723 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
724 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
725 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
726 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
727 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
728 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
729 DEFINE_ACTION("properties", _("Properties"));
731 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
732 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
733 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
734 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
735 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
736 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
737 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
738 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
739 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
740 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
741 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
742 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
743 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
744 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
745 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
746 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
747 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
748 DEFINE_ACTION("play", _("Play"));
749 DEFINE_ACTION("pause", _("Pause"));
750 DEFINE_ACTION("stop", _("Stop"));
751 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
752 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
753 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
754 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
755 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
756 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
757 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
758 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
759 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
760 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
761 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
762 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
763 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
764 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
765 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
766 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
767 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
768 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
769 DEFINE_ACTION("seek-end", _("Seek to End"));
771 DEFINE_ACTION("action-group_add", _("Add group"));
773 DEFINE_ACTION("canvas-new", _("New Canvas"));
775 DEFINE_ACTION("amount-inc", _("Increase Amount"));
776 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
781 // Set up synfigapp actions
783 synfigapp::Action::Book::iterator iter;
785 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
787 Gtk::StockID stock_id;
789 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
791 //Gtk::Image* image(manage(new Gtk::Image()));
792 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
793 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
794 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
795 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
796 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
797 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
798 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
799 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
800 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
801 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
803 actions_action_group->add(Gtk::Action::create(
804 "action-"+iter->second.name,
806 iter->second.local_name,iter->second.local_name
814 Glib::ustring ui_info =
816 " <popup name='menu-toolbox' action='menu-toolbox'>"
817 " <menu action='menu-file'>"
820 " <popup name='menu-main' action='menu-main'>"
821 " <menu action='menu-file'>"
822 " <menuitem action='save' />"
823 " <menuitem action='save-as' />"
824 " <menuitem action='revert' />"
825 " <separator name='bleh01'/>"
826 " <menuitem action='cvs-add' />"
827 " <menuitem action='cvs-update' />"
828 " <menuitem action='cvs-commit' />"
829 " <menuitem action='cvs-revert' />"
830 " <separator name='bleh02'/>"
831 " <menuitem action='import' />"
832 " <separator name='bleh03'/>"
833 " <menuitem action='render' />"
834 " <menuitem action='preview' />"
835 " <menuitem action='sound' />"
836 " <separator name='bleh04'/>"
837 " <menuitem action='options' />"
838 " <menuitem action='close' />"
840 " <menu action='menu-edit'>"
841 " <menuitem action='undo'/>"
842 " <menuitem action='redo'/>"
843 " <separator name='bleh05'/>"
844 " <menuitem action='cut'/>"
845 " <menuitem action='copy'/>"
846 " <menuitem action='paste'/>"
847 " <separator name='bleh06'/>"
848 " <menuitem action='select-all-ducks'/>"
849 " <menuitem action='unselect-all-layers'/>"
850 " <separator name='bleh07'/>"
851 " <menuitem action='properties'/>"
853 " <menu action='menu-view'>"
854 " <menu action='menu-duck-mask'>"
855 " <menuitem action='mask-position-ducks' />"
856 " <menuitem action='mask-vertex-ducks' />"
857 " <menuitem action='mask-tangent-ducks' />"
858 " <menuitem action='mask-radius-ducks' />"
859 " <menuitem action='mask-width-ducks' />"
860 " <menuitem action='mask-angle-ducks' />"
862 " <menu action='menu-preview-quality'>"
863 " <menuitem action='quality-00' />"
864 " <menuitem action='quality-01' />"
865 " <menuitem action='quality-02' />"
866 " <menuitem action='quality-03' />"
867 " <menuitem action='quality-04' />"
868 " <menuitem action='quality-05' />"
869 " <menuitem action='quality-06' />"
870 " <menuitem action='quality-07' />"
871 " <menuitem action='quality-08' />"
872 " <menuitem action='quality-09' />"
873 " <menuitem action='quality-10' />"
875 " <separator name='bleh08'/>"
876 " <menuitem action='play'/>"
877 " <menuitem action='pause'/>"
878 " <menuitem action='stop'/>"
879 " <menuitem action='dialog-flipbook'/>"
880 " <separator name='bleh09'/>"
881 " <menuitem action='toggle-grid-show'/>"
882 " <menuitem action='toggle-grid-snap'/>"
883 " <menuitem action='toggle-guide-show'/>"
884 " <menuitem action='toggle-low-res'/>"
885 " <menuitem action='toggle-onion-skin'/>"
886 " <separator name='bleh10'/>"
887 " <menuitem action='canvas-zoom-in'/>"
888 " <menuitem action='canvas-zoom-out'/>"
889 " <menuitem action='canvas-zoom-fit'/>"
890 " <menuitem action='canvas-zoom-100'/>"
891 " <separator name='bleh11'/>"
892 " <menuitem action='time-zoom-in'/>"
893 " <menuitem action='time-zoom-out'/>"
894 " <separator name='bleh12'/>"
895 " <menuitem action='jump-next-keyframe'/>"
896 " <menuitem action='jump-prev-keyframe'/>"
897 " <menuitem action='seek-next-frame'/>"
898 " <menuitem action='seek-prev-frame'/>"
899 " <menuitem action='seek-next-second'/>"
900 " <menuitem action='seek-prev-second'/>"
901 " <menuitem action='seek-begin'/>"
902 " <menuitem action='seek-end'/>"
904 " <menu action='menu-canvas'>"
905 " <menuitem action='canvas-new'/>"
906 " <menuitem action='amount-inc'/>"
907 " <menuitem action='amount-dec'/>"
909 " <menu name='menu-state' action='menu-state'>"
911 " <menu action='menu-group'>"
912 " <menuitem action='action-group_add'/>"
914 " <menu action='menu-layer'>"
915 //" <menuitem action='cut'/>"
916 //" <menuitem action='copy'/>"
917 //" <menuitem action='paste'/>"
918 //" <separator name='bleh06'/>"
919 " <menu action='menu-layer-new'></menu>"
921 " <menu action='menu-keyframe'>"
922 " <menuitem action='keyframe-properties'/>"
929 " <menubar name='MenuBar'>"
930 " <menu action='MenuFile'>"
931 " <menuitem action='New'/>"
932 " <menuitem action='Open'/>"
934 " <menuitem action='Quit'/>"
936 " <menu action='MenuEdit'>"
937 " <menuitem action='Cut'/>"
938 " <menuitem action='Copy'/>"
939 " <menuitem action='Paste'/>"
942 " <toolbar name='ToolBar'>"
943 " <toolitem action='Open'/>"
944 " <toolitem action='Quit'/>"
950 actions_action_group->set_sensitive(false);
951 App::ui_manager()->set_add_tearoffs(true);
952 App::ui_manager()->insert_action_group(menus_action_group,1);
953 App::ui_manager()->insert_action_group(actions_action_group,1);
954 App::ui_manager()->add_ui_from_string(ui_info);
956 //App::ui_manager()->get_accel_group()->unlock();
958 catch(const Glib::Error& ex)
960 synfig::error("building menus and toolbars failed: " + ex.what());
963 // Add default keyboard accelerators
964 #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()); }
965 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
966 ACCEL("<Actions>//select-all-ducks","<Control>a");
967 ACCEL("<Actions>//unselect-all-layers","<Control>d");
968 ACCEL("<Actions>//render","F9");
969 ACCEL("<Actions>//preview","F11");
970 ACCEL("<Actions>//properties","F8");
971 ACCEL("<Actions>//options","F12");
972 ACCEL("<Actions>//import","<control>i");
973 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
974 ACCEL("<Actions>//toggle-grid-show","<Control>g");
975 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
976 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
977 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
978 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
979 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
980 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
981 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
982 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
985 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
986 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
988 ACCEL("<Actions>//quality-01","<Control>1");
989 ACCEL("<Actions>//quality-02","<Control>2");
990 ACCEL("<Actions>//quality-03","<Control>3");
991 ACCEL("<Actions>//quality-04","<Control>4");
992 ACCEL("<Actions>//quality-05","<Control>5");
993 ACCEL("<Actions>//quality-06","<Control>6");
994 ACCEL("<Actions>//quality-07","<Control>7");
995 ACCEL("<Actions>//quality-08","<Control>8");
996 ACCEL("<Actions>//quality-09","<Control>9");
997 ACCEL("<Actions>//quality-10","<Control>0");
998 ACCEL("<Actions>//undo","<Control>z");
999 ACCEL("<Actions>//redo","<Control>r");
1000 ACCEL("<Actions>//action-layer_remove","Delete");
1002 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1003 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1004 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1005 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1006 ACCEL("<Actions>//time-zoom-in","+");
1007 ACCEL("<Actions>//time-zoom-out","_");
1009 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1010 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1012 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1013 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1014 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1015 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1016 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1017 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1018 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1019 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1020 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1021 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1022 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1023 ACCEL("<Actions>//seek-begin","Home");
1024 ACCEL("<Actions>//seek-end","End");
1025 ACCEL("<Actions>//state-normal","<Mod1>a");
1026 ACCEL("<Actions>//state-rotate","<Mod1>s");
1027 ACCEL("<Actions>//state-scale","<Mod1>d");
1028 ACCEL("<Actions>//state-bline","<Mod1>b");
1029 ACCEL("<Actions>//state-fill","<Mod1>f");
1030 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1031 ACCEL("<Actions>//state-gradient","<Mod1>g");
1032 ACCEL("<Actions>//state-zoom","<Mod1>z");
1033 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1039 #define mkdir(x,y) mkdir(x)
1042 /* === M E T H O D S ======================================================= */
1044 App::App(int *argc, char ***argv):
1045 Gtk::Main(argc,argv),
1046 IconControler(etl::dirname((*argv)[0]))
1048 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1051 serial_=check_license(app_base_path_);
1054 ui_interface_=new GlobalUIInterface();
1058 Glib::thread_init();
1060 distance_system=Distance::SYSTEM_UNITS;
1062 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1065 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1069 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1077 if(!SYNFIG_CHECK_VERSION())
1079 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1080 dialog_error_blocking("SYNFIG Studio",
1081 "This copy of SYNFIG Studio was compiled against a\n"
1082 "different version of libsynfig than what is currently\n"
1083 "installed. Synfig Studio will now abort. Try downloading\n"
1084 "the latest version from the SYNFIG Development Website at\n"
1085 "http://dev.synfig.com/ "
1090 catch(synfig::SoftwareExpired)
1092 cerr<<"FATAL: Software Expired"<<endl;
1093 dialog_error_blocking("SYNFIG Studio",
1094 "This copy of SYNFIG Studio has expired.\n"
1095 "Please erase this copy, or download and\n"
1096 "install the latest copy from the SYNFIG\n"
1097 "Development Website at http://dev.synfig.com/ ."
1101 Glib::set_application_name(_("SYNFIG Studio"));
1104 about_window.set_can_self_destruct(false);
1105 about_window.show();
1107 shutdown_in_progress=false;
1108 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1109 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1111 // Initialize the Synfig library
1112 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1115 get_ui_interface()->error("Failed to initialize synfig!");
1119 // add the preferences to the settings
1120 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1124 studio_init_cb.task("Init UI Manager...");
1125 App::ui_manager_=studio::UIManager::create();
1128 studio_init_cb.task("Init Dock Manager...");
1129 dock_manager=new studio::DockManager();
1131 studio_init_cb.task("Init State Manager...");
1132 state_manager=new StateManager();
1134 studio_init_cb.task("Init Toolbox...");
1135 toolbox=new studio::Toolbox();
1137 studio_init_cb.task("Init Tool Options...");
1138 dialog_tool_options=new studio::Dialog_ToolOptions();
1139 dock_manager->register_dockable(*dialog_tool_options);
1141 studio_init_cb.task("Init History...");
1142 dock_history=new studio::Dock_History();
1143 dock_manager->register_dockable(*dock_history);
1145 studio_init_cb.task("Init Canvases...");
1146 dock_canvases=new studio::Dock_Canvases();
1147 dock_manager->register_dockable(*dock_canvases);
1149 studio_init_cb.task("Init Keyframes...");
1150 dock_keyframes=new studio::Dock_Keyframes();
1151 dock_manager->register_dockable(*dock_keyframes);
1153 studio_init_cb.task("Init Layers...");
1154 dock_layers=new studio::Dock_Layers();
1155 dock_manager->register_dockable(*dock_layers);
1157 studio_init_cb.task("Init Params...");
1158 dock_params=new studio::Dock_Params();
1159 dock_manager->register_dockable(*dock_params);
1161 studio_init_cb.task("Init MetaData...");
1162 dock_meta_data=new studio::Dock_MetaData();
1163 dock_manager->register_dockable(*dock_meta_data);
1165 studio_init_cb.task("Init Children...");
1166 dock_children=new studio::Dock_Children();
1167 dock_manager->register_dockable(*dock_children);
1169 studio_init_cb.task("Init Info...");
1170 dock_info = new studio::Dock_Info();
1171 dock_manager->register_dockable(*dock_info);
1173 studio_init_cb.task("Init Navigator...");
1174 dock_navigator = new studio::Dock_Navigator();
1175 dock_manager->register_dockable(*dock_navigator);
1177 studio_init_cb.task("Init Timetrack...");
1178 dock_timetrack = new studio::Dock_Timetrack();
1179 dock_manager->register_dockable(*dock_timetrack);
1181 studio_init_cb.task("Init Curve Editor...");
1182 dock_curves = new studio::Dock_Curves();
1183 dock_manager->register_dockable(*dock_curves);
1185 studio_init_cb.task("Init Layer Groups...");
1186 dock_layer_groups = new studio::Dock_LayerGroups();
1187 dock_manager->register_dockable(*dock_layer_groups);
1190 studio_init_cb.task("Init Color Dialog...");
1191 dialog_color=new studio::Dialog_Color();
1193 studio_init_cb.task("Init Gradient Dialog...");
1194 dialog_gradient=new studio::Dialog_Gradient();
1196 studio_init_cb.task("Init DeviceTracker...");
1197 device_tracker=new studio::DeviceTracker();
1199 studio_init_cb.task("Init Tools...");
1200 state_manager->add_state(&state_normal);
1201 state_manager->add_state(&state_smooth_move);
1202 state_manager->add_state(&state_scale);
1203 state_manager->add_state(&state_rotate);
1205 state_manager->add_state(&state_bline);
1206 state_manager->add_state(&state_polygon);
1207 state_manager->add_state(&state_circle);
1208 state_manager->add_state(&state_rectangle);
1210 state_manager->add_state(&state_draw);
1211 state_manager->add_state(&state_sketch);
1213 state_manager->add_state(&state_eyedrop);
1214 state_manager->add_state(&state_fill);
1216 state_manager->add_state(&state_width);
1217 state_manager->add_state(&state_gradient);
1219 state_manager->add_state(&state_zoom);
1221 studio_init_cb.task("Init ModPalette...");
1222 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1224 studio_init_cb.task("Init ModMirror...");
1225 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1228 studio_init_cb.task("Init Setup Dialog...");
1229 dialog_setup=new studio::Dialog_Setup();
1231 studio_init_cb.task("Init Input Dialog...");
1232 dialog_input=new Gtk::InputDialog();
1234 studio_init_cb.task("Init auto recovery...");
1235 auto_recover=new AutoRecover();
1237 studio_init_cb.amount_complete(9250,10000);
1238 studio_init_cb.task("Loading Settings...");
1240 studio_init_cb.task("Checking auto-recover...");
1242 studio_init_cb.amount_complete(9900,10000);
1244 if(auto_recover->recovery_needed())
1246 about_window.hide();
1248 get_ui_interface()->yes_no(
1250 "SYNFIG Studio seems to have crashed\n"
1251 "before you could save all your files.\n"
1252 "Would you like to re-open those files\n"
1253 "and recover your unsaved changes?"
1254 )==synfigapp::UIInterface::RESPONSE_YES
1257 if(!auto_recover->recover())
1259 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1262 get_ui_interface()->error(
1263 _("SYNFIG Studio has attempted to recover\n"
1264 "from a previous crash. The files that it has\n"
1265 "recovered are NOT YET SAVED. It would be a good\n"
1266 "idea to review them and save them now.")
1269 about_window.show();
1272 // Look for any files given on the command line,
1273 // and load them if found.
1274 for(;*argc>=1;(*argc)--)
1275 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1277 studio_init_cb.task("Loading files...");
1278 about_window.hide();
1279 open((*argv)[*argc]);
1280 about_window.show();
1283 studio_init_cb.task("Done.");
1284 studio_init_cb.amount_complete(10000,10000);
1290 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1294 StateManager* App::get_state_manager() { return state_manager; }
1298 shutdown_in_progress=true;
1302 synfigapp::Main::settings().remove_domain("pref");
1304 selected_instance=0;
1306 // Unload all of the modules
1307 for(;!module_list_.empty();module_list_.pop_back());
1309 delete state_manager;
1313 delete auto_recover;
1317 // studio::App::iteration(false);
1321 // studio::App::iteration(false);
1323 // studio::App::iteration(false);
1325 delete dialog_setup;
1327 delete dialog_gradient;
1329 delete dialog_color;
1331 delete dialog_input;
1333 delete dock_manager;
1335 instance_list.clear();
1337 // studio::App::iteration(false);
1341 App::get_user_app_directory()
1344 return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
1346 return Glib::build_filename(Glib::get_home_dir(),"Synfig");
1351 App::get_config_file(const synfig::String& file)
1353 return Glib::build_filename(get_user_app_directory(),file);
1357 App::add_recent_file(const std::string &file_name)
1359 std::string filename(file_name);
1361 assert(!filename.empty());
1363 if(filename.empty())
1366 // Toss out any "hidden" files
1367 if(basename(filename)[0]=='.')
1370 // If we aren't an absolute path, turn outselves into one
1371 if(!is_absolute_path(filename))
1372 filename=absolute_path(filename);
1374 list<string>::iterator iter;
1375 // Check to see if the file is already on the list.
1376 // If it is, then remove it from the list
1377 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1380 recent_files.erase(iter);
1385 // Push the filename to the front of the list
1386 recent_files.push_front(filename);
1388 // Clean out the files at the end of the list.
1389 while(recent_files.size()>(unsigned)get_max_recent_files())
1390 recent_files.pop_back();
1392 signal_recent_files_changed_();
1397 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1400 App::get_time_format()
1402 return _App_time_format;
1406 App::set_time_format(synfig::Time::Format x)
1413 App::save_settings()
1418 std::string filename=get_config_file("accelrc");
1419 Gtk::AccelMap::save(filename);
1422 std::string filename=get_config_file("recentfiles");
1424 std::ofstream file(filename.c_str());
1428 synfig::warning("Unable to save %s",filename.c_str());
1432 list<string>::reverse_iterator iter;
1434 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1438 std::string filename=get_config_file("settings");
1439 synfigapp::Main::settings().save_to_file(filename);
1443 synfig::warning("Caught exception when attempting to save settings.");
1448 App::load_settings()
1453 std::string filename=get_config_file("accelrc");
1454 Gtk::AccelMap::load(filename);
1457 std::string filename=get_config_file("recentfiles");
1459 std::ifstream file(filename.c_str());
1463 std::string recent_file;
1464 getline(file,recent_file);
1465 if(!recent_file.empty())
1466 add_recent_file(recent_file);
1469 std::string filename=get_config_file("settings");
1470 if(!synfigapp::Main::settings().load_from_file(filename))
1472 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1473 //if(!synfigapp::Main::settings().load_from_file(filename))
1475 gamma.set_gamma(1.0/2.2);
1476 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1477 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1478 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1479 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1480 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1481 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1482 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1483 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1484 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1485 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1486 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1487 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1488 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1495 synfig::warning("Caught exception when attempting to load settings.");
1500 App::shutdown_request(GdkEventAny*)
1504 //return !shutdown_in_progress;
1510 if(shutdown_in_progress)return;
1513 get_ui_interface()->task("Quit Request");
1516 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1520 std::list<etl::handle<Instance> >::iterator iter;
1521 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1523 if(!(*iter)->safe_close())
1527 if((*iter)->synfigapp::Instance::get_action_count())
1529 handle<synfigapp::UIInterface> uim;
1530 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1532 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1533 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1535 case synfigapp::UIInterface::RESPONSE_NO:
1537 case synfigapp::UIInterface::RESPONSE_YES:
1540 case synfigapp::UIInterface::RESPONSE_CANCEL:
1549 if((*iter)->synfigapp::Instance::is_modified())
1551 handle<synfigapp::UIInterface> uim;
1552 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1554 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() );
1555 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1557 case synfigapp::UIInterface::RESPONSE_NO:
1559 case synfigapp::UIInterface::RESPONSE_YES:
1560 (*iter)->dialog_cvs_commit();
1562 case synfigapp::UIInterface::RESPONSE_CANCEL:
1571 // This next line causes things to crash for some reason
1575 shutdown_in_progress=true;
1577 instance_list.clear();
1579 while(studio::App::events_pending())studio::App::iteration(false);
1582 auto_recover->normal_shutdown();
1584 get_ui_interface()->task("Quit Request sent");
1590 dialog_setup->refresh();
1591 dialog_setup->show();
1594 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1595 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1598 //#define USE_WIN32_FILE_DIALOGS 1
1601 #ifdef USE_WIN32_FILE_DIALOGS
1602 static OPENFILENAME ofn={};
1606 #include <gdk/gdkwin32.h>
1610 App::dialog_open_file(const std::string &title, std::string &filename)
1612 #ifdef USE_WIN32_FILE_DIALOGS
1613 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1615 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1616 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1617 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1619 ofn.lStructSize=sizeof(OPENFILENAME);
1620 ofn.hwndOwner = hWnd;
1621 ofn.hInstance = hInstance;
1622 ofn.lpstrFilter = szFilter;
1623 // ofn.lpstrCustomFilter=NULL;
1624 // ofn.nMaxCustFilter=0;
1625 // ofn.nFilterIndex=0;
1626 // ofn.lpstrFile=NULL;
1627 ofn.nMaxFile=MAX_PATH;
1628 // ofn.lpstrFileTitle=NULL;
1629 // ofn.lpstrInitialDir=NULL;
1630 // ofn.lpstrTitle=NULL;
1631 ofn.Flags=OFN_HIDEREADONLY;
1632 // ofn.nFileOffset=0;
1633 // ofn.nFileExtension=0;
1634 ofn.lpstrDefExt=TEXT("sif");
1635 // ofn.lCustData = 0l;
1637 // ofn.lpTemplateName=NULL;
1639 CHAR szFilename[MAX_PATH];
1641 strcpy(szFilename,filename.c_str());
1642 strcpy(szTitle,title.c_str());
1644 ofn.lpstrFile=szFilename;
1645 ofn.lpstrFileTitle=szTitle;
1647 if(GetOpenFileName(&ofn))
1649 filename=szFilename;
1655 synfig::String prev_path;
1656 if(!_preferences.get_value("curr_path",prev_path))
1659 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1660 dialog->set_current_folder(prev_path);
1661 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1662 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1663 if(!filename.empty())
1664 dialog->set_filename(filename);
1665 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1666 filename=dialog->get_filename();
1678 GtkWidget *fileselection;
1679 fileselection = gtk_file_selection_new(title.c_str());
1682 if(basename(filename)==filename)
1684 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1687 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1689 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1691 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1692 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1694 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1695 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1697 gtk_widget_show(fileselection);
1705 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1706 _preferences.set_value("curr_path",dirname(filename));
1710 gtk_widget_destroy(fileselection);
1713 gtk_widget_destroy(fileselection);
1720 App::dialog_save_file(const std::string &title, std::string &filename)
1722 #ifdef USE_WIN32_FILE_DIALOGS
1723 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1725 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1726 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1727 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1729 ofn.lStructSize=sizeof(OPENFILENAME);
1730 ofn.hwndOwner = hWnd;
1731 ofn.hInstance = hInstance;
1732 ofn.lpstrFilter = szFilter;
1733 // ofn.lpstrCustomFilter=NULL;
1734 // ofn.nMaxCustFilter=0;
1735 // ofn.nFilterIndex=0;
1736 // ofn.lpstrFile=NULL;
1737 ofn.nMaxFile=MAX_PATH;
1738 // ofn.lpstrFileTitle=NULL;
1739 // ofn.lpstrInitialDir=NULL;
1740 // ofn.lpstrTitle=NULL;
1741 ofn.Flags=OFN_OVERWRITEPROMPT;
1742 // ofn.nFileOffset=0;
1743 // ofn.nFileExtension=0;
1744 ofn.lpstrDefExt=TEXT("sif");
1745 // ofn.lCustData = 0l;
1747 // ofn.lpTemplateName=NULL;
1749 CHAR szFilename[MAX_PATH];
1751 strcpy(szFilename,filename.c_str());
1752 strcpy(szTitle,title.c_str());
1754 ofn.lpstrFile=szFilename;
1755 ofn.lpstrFileTitle=szTitle;
1757 if(GetSaveFileName(&ofn))
1759 filename=szFilename;
1764 synfig::String prev_path;
1765 if(!_preferences.get_value("curr_path",prev_path))
1768 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1769 dialog->set_current_folder(prev_path);
1770 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1771 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1772 if(!filename.empty())
1773 dialog->set_filename(filename);
1774 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1775 filename=dialog->get_filename();
1781 // return dialog_open_file(title, filename);
1786 App::dialog_saveas_file(const std::string &title, std::string &filename)
1788 #if USE_WIN32_FILE_DIALOGS
1789 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1791 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1792 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1793 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1795 ofn.lStructSize=sizeof(OPENFILENAME);
1796 ofn.hwndOwner = hWnd;
1797 ofn.hInstance = hInstance;
1798 ofn.lpstrFilter = szFilter;
1799 // ofn.lpstrCustomFilter=NULL;
1800 // ofn.nMaxCustFilter=0;
1801 // ofn.nFilterIndex=0;
1802 // ofn.lpstrFile=NULL;
1803 ofn.nMaxFile=MAX_PATH;
1804 // ofn.lpstrFileTitle=NULL;
1805 // ofn.lpstrInitialDir=NULL;
1806 // ofn.lpstrTitle=NULL;
1807 ofn.Flags=OFN_OVERWRITEPROMPT;
1808 // ofn.nFileOffset=0;
1809 // ofn.nFileExtension=0;
1810 ofn.lpstrDefExt=TEXT("sif");
1811 // ofn.lCustData = 0l;
1813 // ofn.lpTemplateName=NULL;
1815 CHAR szFilename[MAX_PATH];
1817 strcpy(szFilename,filename.c_str());
1818 strcpy(szTitle,title.c_str());
1820 ofn.lpstrFile=szFilename;
1821 ofn.lpstrFileTitle=szTitle;
1823 if(GetSaveFileName(&ofn))
1825 filename=szFilename;
1830 synfig::String prev_path;
1831 if(!_preferences.get_value("curr_path",prev_path))
1834 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1835 dialog->set_current_folder(prev_path);
1836 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1837 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1838 if(!filename.empty())
1839 dialog->set_filename(filename);
1840 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1841 filename=dialog->get_filename();
1847 // return dialog_open_file(title, filename);
1852 App::dialog_error_blocking(const std::string &title, const std::string &message)
1857 true // use_separator
1859 Gtk::Label label(message);
1862 dialog.get_vbox()->pack_start(label);
1863 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1869 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1874 true // use_separator
1876 Gtk::Label label(message);
1879 dialog.get_vbox()->pack_start(label);
1880 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1886 App::dialog_yes_no(const std::string &title, const std::string &message)
1891 true // use_separator
1893 Gtk::Label label(message);
1896 dialog.get_vbox()->pack_start(label);
1897 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1898 dialog.add_button(Gtk::StockID("gtk-no"),0);
1900 return dialog.run();
1904 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1909 true // use_separator
1911 Gtk::Label label(message);
1914 dialog.get_vbox()->pack_start(label);
1915 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1916 dialog.add_button(Gtk::StockID("gtk-no"),0);
1917 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1919 return dialog.run();
1923 App::dialog_not_implemented()
1926 "Feature not available", // Title
1928 true // use_separator
1930 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1933 dialog.get_vbox()->pack_start(label);
1934 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1940 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1945 true // use_separator
1947 Gtk::Label label(message);
1949 dialog.get_vbox()->pack_start(label);
1952 entry.set_text(text);
1954 entry.set_activates_default(true);
1955 dialog.get_vbox()->pack_start(entry);
1957 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1958 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1959 dialog.set_default_response(Gtk::RESPONSE_OK);
1960 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1963 if(dialog.run()!=Gtk::RESPONSE_OK)
1966 text=entry.get_text();
1975 App::open(std::string filename)
1977 return open_as(filename,filename);
1981 App::open_as(std::string filename,std::string as)
1984 char long_name[1024];
1985 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1991 OneMoment one_moment;
1993 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1994 if(canvas && get_instance(canvas))
1996 get_instance(canvas)->find_canvas_view(canvas)->present();
1997 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2000 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2002 add_recent_file(as);
2004 handle<Instance> instance(Instance::create(canvas));
2007 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2011 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)")))
2012 instance->dialog_cvs_update();
2016 dialog_error_blocking(_("Error"), x);
2021 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2025 _preferences.set_value("curr_path",dirname(as));
2034 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2035 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2037 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2039 canvas->rend_desc().set_frame_rate(24.0);
2040 canvas->rend_desc().set_time_start(0.0);
2041 canvas->rend_desc().set_time_end(00.0);
2042 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2043 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2044 canvas->rend_desc().set_tl(Vector(-4,2.25));
2045 canvas->rend_desc().set_br(Vector(4,-2.25));
2046 canvas->rend_desc().set_w(480);
2047 canvas->rend_desc().set_h(270);
2048 canvas->rend_desc().set_antialias(1);
2049 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2050 canvas->set_file_name(file_name);
2052 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2058 string filename="*.sif";
2060 while(dialog_open_file("Open", filename))
2062 // If the filename still has wildcards, then we should
2063 // continue looking for the file we want
2064 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2070 get_ui_interface()->error(_("Unable to open file"));
2075 App::set_selected_instance(etl::loose_handle<Instance> instance)
2077 /* if(get_selected_instance()==instance)
2079 selected_instance=instance;
2080 signal_instance_selected()(instance);
2086 selected_instance=instance;
2087 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2091 instance->focus(instance->get_canvas());
2094 set_selected_canvas_view(0);
2096 signal_instance_selected()(instance);
2100 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2102 selected_canvas_view=canvas_view;
2103 signal_canvas_view_focus()(selected_canvas_view);
2106 selected_instance=canvas_view->get_instance();
2107 signal_instance_selected()(canvas_view->get_instance());
2110 if(get_selected_canvas_view()==canvas_view)
2112 signal_canvas_view_focus()(selected_canvas_view);
2113 signal_instance_selected()(canvas_view->get_instance());
2116 selected_canvas_view=canvas_view;
2117 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2118 set_selected_instance(canvas_view->get_instance());
2119 signal_canvas_view_focus()(selected_canvas_view);
2123 etl::loose_handle<Instance>
2124 App::get_instance(Canvas::Handle canvas)
2126 if(!canvas) return 0;
2127 canvas=canvas->get_root();
2129 std::list<etl::handle<Instance> >::iterator iter;
2130 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2132 if((*iter)->get_canvas()==canvas)
2141 (new class About())->show();
2147 if(selected_instance)
2148 selected_instance->undo();
2154 if(selected_instance)
2155 selected_instance->redo();
2159 studio::App::get_base_path()
2161 return app_base_path_;