1 /* === S Y N F I G ========================================================= */
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
38 #ifdef HAVE_SYS_ERRNO_H
39 #include <sys/errno.h>
41 #include <gtkmm/fileselection.h>
42 #include <gtkmm/dialog.h>
43 #include <gtkmm/messagedialog.h>
44 #include <gtkmm/label.h>
45 #include <gtkmm/stock.h>
46 #include <gtkmm/stockitem.h>
47 #include <gtkmm/iconsource.h>
48 #include <gtkmm/inputdialog.h>
49 #include <gtkmm/accelmap.h>
50 #include <gtkmm/uimanager.h>
54 #include <synfig/loadcanvas.h>
59 #include "canvasview.h"
60 #include "dialog_setup.h"
61 #include "dialog_gradient.h"
62 #include "dialog_color.h"
65 #include "onemoment.h"
67 #include "dockmanager.h"
69 #include "state_eyedrop.h"
70 #include "state_normal.h"
71 #include "state_draw.h"
72 #include "state_fill.h"
73 #include "state_bline.h"
74 #include "state_polygon.h"
75 #include "state_sketch.h"
76 #include "state_gradient.h"
77 #include "state_circle.h"
78 #include "state_rectangle.h"
79 #include "state_smoothmove.h"
80 #include "state_scale.h"
81 #include "state_width.h"
82 #include "state_rotate.h"
83 #include "state_zoom.h"
85 #include "devicetracker.h"
86 #include "dialog_tooloptions.h"
88 #include "autorecover.h"
90 #include <synfigapp/settings.h>
91 #include "dock_history.h"
92 #include "dock_canvases.h"
93 #include "dock_keyframes.h"
94 #include "dock_layers.h"
95 #include "dock_params.h"
96 #include "dock_metadata.h"
97 #include "dock_children.h"
98 #include "dock_info.h"
99 #include "dock_navigator.h"
100 #include "dock_layergroups.h"
101 #include "dock_timetrack.h"
102 #include "dock_curves.h"
104 #include "mod_palette/mod_palette.h"
105 #include "mod_mirror/mod_mirror.h"
107 #include <sys/stat.h>
113 #include "statemanager.h"
120 #define _WIN32_WINNT 0x0500
123 #include <gtkmm/accelmap.h>
124 #include <gtkmm/filechooser.h>
125 #include <gtkmm/filechooserdialog.h>
131 /* === U S I N G =========================================================== */
135 using namespace synfig;
136 using namespace studio;
138 /* === M A C R O S ========================================================= */
140 #ifndef SYNFIG_USER_APP_DIR
142 #define SYNFIG_USER_APP_DIR "Library/Synfig"
143 #elif defined(_WIN32)
144 #define SYNFIG_USER_APP_DIR "Synfig"
146 #define SYNFIG_USER_APP_DIR ".synfig"
151 #define DPM2DPI(x) (float(x)/39.3700787402f)
152 #define DPI2DPM(x) (float(x)*39.3700787402f)
158 # define IMAGE_DIR "share\\pixmaps"
163 # define IMAGE_DIR "/usr/local/share/pixmaps"
167 # define IMAGE_EXT "tif"
170 #include <synfigapp/main.h>
172 /* === S I G N A L S ======================================================= */
174 static sigc::signal<void> signal_present_all_;
176 App::signal_present_all() { return signal_present_all_; }
178 static sigc::signal<void> signal_recent_files_changed_;
180 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
182 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
183 sigc::signal<void,etl::loose_handle<CanvasView> >&
184 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
186 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
187 sigc::signal<void,etl::handle<Instance> >&
188 App::signal_instance_selected() { return signal_instance_selected_; }
190 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
191 sigc::signal<void,etl::handle<Instance> >&
192 App::signal_instance_created() { return signal_instance_created_; }
194 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
195 sigc::signal<void,etl::handle<Instance> >&
196 App::signal_instance_deleted() { return signal_instance_deleted_; }
198 /* === G L O B A L S ======================================================= */
200 static std::list<std::string> recent_files;
201 const std::list<std::string>& App::get_recent_files() { return recent_files; }
203 int App::Busy::count;
204 bool App::shutdown_in_progress;
206 synfig::Gamma App::gamma;
208 Glib::RefPtr<studio::UIManager> App::ui_manager_;
210 synfig::Distance::System App::distance_system;
212 studio::Dialog_Setup* App::dialog_setup;
214 etl::handle< studio::ModPalette > mod_palette_;
215 //studio::Dialog_Palette* App::dialog_palette;
217 std::list<etl::handle<Instance> > App::instance_list;
219 static etl::handle<synfigapp::UIInterface> ui_interface_;
220 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
222 etl::handle<Instance> App::selected_instance;
223 etl::handle<CanvasView> App::selected_canvas_view;
225 studio::Toolbox *studio::App::toolbox=NULL;
227 studio::AutoRecover *studio::App::auto_recover=NULL;
229 studio::IPC *ipc=NULL;
231 studio::DockManager* studio::App::dock_manager=0;
233 studio::DeviceTracker* studio::App::device_tracker=0;
235 studio::Dialog_Gradient* studio::App::dialog_gradient;
237 studio::Dialog_Color* studio::App::dialog_color;
239 Gtk::InputDialog* studio::App::dialog_input;
241 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
243 studio::Dock_History* dock_history;
244 studio::Dock_Canvases* dock_canvases;
245 studio::Dock_Keyframes* dock_keyframes;
246 studio::Dock_Layers* dock_layers;
247 studio::Dock_Params* dock_params;
248 studio::Dock_MetaData* dock_meta_data;
249 studio::Dock_Children* dock_children;
250 studio::Dock_Info* dock_info;
251 studio::Dock_LayerGroups* dock_layer_groups;
252 studio::Dock_Navigator* dock_navigator;
253 studio::Dock_Timetrack* dock_timetrack;
254 studio::Dock_Curves* dock_curves;
256 std::list< etl::handle< studio::Module > > module_list_;
258 bool studio::App::use_colorspace_gamma=true;
259 bool studio::App::single_threaded=false;
261 static int max_recent_files_=25;
262 int studio::App::get_max_recent_files() { return max_recent_files_; }
263 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
265 static synfig::String app_base_path_;
270 really_delete_widget(Gtk::Widget *widget)
272 // synfig::info("really delete %p", (void*)widget);
277 // nasty workaround - when we've finished with a popup menu, we want to delete it
278 // attaching to the signal_hide() signal gets us here before the action on the menu has run,
279 // so schedule the real delete to happen in 50ms, giving the action a chance to run
281 delete_widget(Gtk::Widget *widget)
283 // synfig::info("delete %p", (void*)widget);
284 Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
287 }; // END of namespace studio
288 studio::StateManager* state_manager;
293 class GlobalUIInterface : public synfigapp::UIInterface
297 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
302 true // use_separator
304 Gtk::Label label(message);
307 dialog.get_vbox()->pack_start(label);
308 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
309 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
311 dialog.set_default_response(dflt);
313 return (Response)dialog.run();
315 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
320 true // use_separator
322 Gtk::Label label(message);
325 dialog.get_vbox()->pack_start(label);
326 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
327 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
328 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
330 dialog.set_default_response(dflt);
332 return (Response)dialog.run();
334 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
339 true // use_separator
341 Gtk::Label label(message);
344 dialog.get_vbox()->pack_start(label);
345 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
346 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
348 dialog.set_default_response(dflt);
350 return (Response)dialog.run();
354 task(const std::string &task)
356 std::cerr<<task<<std::endl;
357 while(studio::App::events_pending())studio::App::iteration(false);
362 error(const std::string &err)
364 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
371 warning(const std::string &err)
373 std::cerr<<"warning: "<<err<<std::endl;
374 while(studio::App::events_pending())studio::App::iteration(false);
379 amount_complete(int /*current*/, int /*total*/)
381 while(studio::App::events_pending())studio::App::iteration(false);
386 /* === P R O C E D U R E S ================================================= */
390 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
392 action_group_list.push_back(action_group);
393 Gtk::UIManager::insert_action_group(action_group, pos);
397 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
399 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
400 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
401 if(*iter==action_group)
403 action_group_list.erase(iter);
404 Gtk::UIManager::remove_action_group(action_group);
407 synfig::error("Unable to find action group");
411 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
413 ui_manager->insert_action_group(group,0);
415 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
416 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
418 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
420 if(*iter && (*iter)->get_name()!="menus")
422 synfig::info("Removing action group "+(*iter)->get_name());
423 ui_manager->remove_action_group(*iter);
426 ui_manager->insert_action_group(group,0);
428 for(;!prev_groups.empty();prev_groups.pop_front())
430 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
431 ui_manager->insert_action_group(prev_groups.front(),1);
435 class Preferences : public synfigapp::Settings
438 virtual bool get_value(const synfig::String& key, synfig::String& value)const
442 value=strprintf("%f %f %f %f",
443 App::gamma.get_gamma_r(),
444 App::gamma.get_gamma_g(),
445 App::gamma.get_gamma_b(),
446 App::gamma.get_black_level()
450 if(key=="time_format")
452 value=strprintf("%i",App::get_time_format());
455 if(key=="file_history.size")
457 value=strprintf("%i",App::get_max_recent_files());
460 if(key=="use_colorspace_gamma")
462 value=strprintf("%i",(int)App::use_colorspace_gamma);
465 if(key=="distance_system")
467 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
470 if(key=="single_threaded")
472 value=strprintf("%i",(int)App::single_threaded);
475 if(key=="auto_recover_backup_interval")
477 value=strprintf("%i",App::auto_recover->get_timeout());
481 return synfigapp::Settings::get_value(key,value);
484 virtual bool set_value(const synfig::String& key,const synfig::String& value)
490 strscanf(value,"%f %f %f %f",
497 App::gamma.set_all(r,g,b,blk);
501 if(key=="time_format")
503 int i(atoi(value.c_str()));
504 App::set_time_format(static_cast<synfig::Time::Format>(i));
507 if(key=="auto_recover_backup_interval")
509 int i(atoi(value.c_str()));
510 App::auto_recover->set_timeout(i);
513 if(key=="file_history.size")
515 int i(atoi(value.c_str()));
516 App::set_max_recent_files(i);
519 if(key=="use_colorspace_gamma")
521 int i(atoi(value.c_str()));
522 App::use_colorspace_gamma=i;
525 if(key=="distance_system")
527 App::distance_system=Distance::ident_system(value);;
530 if(key=="single_threaded")
532 int i(atoi(value.c_str()));
533 App::single_threaded=i;
537 return synfigapp::Settings::set_value(key,value);
540 virtual KeyList get_key_list()const
542 KeyList ret(synfigapp::Settings::get_key_list());
543 ret.push_back("gamma");
544 ret.push_back("time_format");
545 ret.push_back("distance_system");
546 ret.push_back("file_history.size");
547 ret.push_back("use_colorspace_gamma");
548 ret.push_back("single_threaded");
549 ret.push_back("auto_recover_backup_interval");
554 static ::Preferences _preferences;
559 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
561 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
563 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
565 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
566 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
567 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
568 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
569 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
570 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
571 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
572 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
573 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
574 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
575 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
576 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
578 // Add the synfigapp actions...
579 synfigapp::Action::Book::iterator iter;
580 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
582 actions_action_group->add(Gtk::Action::create(
583 "action-"+iter->second.name,
584 get_action_stock_id(iter->second),
585 iter->second.local_name,iter->second.local_name
589 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
590 #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); }
591 #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); }
593 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
594 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
595 DEFINE_ACTION("new", Gtk::Stock::NEW);
596 DEFINE_ACTION("open", Gtk::Stock::OPEN);
597 DEFINE_ACTION("save", Gtk::Stock::SAVE);
598 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
599 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
600 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
601 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
602 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
603 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
604 DEFINE_ACTION("import", _("Import"));
605 DEFINE_ACTION("render", _("Render"));
606 DEFINE_ACTION("preview", _("Preview"));
607 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
608 DEFINE_ACTION("sound", _("Sound File"));
609 DEFINE_ACTION("options", _("Options"));
610 DEFINE_ACTION("close", _("Close View"));
611 DEFINE_ACTION("close-document", _("Close Document"));
612 DEFINE_ACTION("quit", Gtk::Stock::QUIT);
615 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
616 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
617 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
618 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
619 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
620 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
621 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
622 DEFINE_ACTION("properties", _("Properties"));
624 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
625 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
626 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
627 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
628 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
629 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
630 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
631 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
632 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
633 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
634 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
635 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
636 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
637 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
638 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
639 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
640 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
641 DEFINE_ACTION("play", _("Play"));
642 // DEFINE_ACTION("pause", _("Pause"));
643 DEFINE_ACTION("stop", _("Stop"));
644 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
645 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
646 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
647 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
648 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
649 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
650 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
651 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
652 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
653 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
654 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
655 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
656 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
657 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
658 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
659 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
660 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
661 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
662 DEFINE_ACTION("seek-end", _("Seek to End"));
664 DEFINE_ACTION("action-group_add", _("Add group"));
666 DEFINE_ACTION("canvas-new", _("New Canvas"));
668 DEFINE_ACTION("amount-inc", _("Increase Amount"));
669 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
674 // Set up synfigapp actions
676 synfigapp::Action::Book::iterator iter;
678 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
680 Gtk::StockID stock_id;
682 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
684 //Gtk::Image* image(manage(new Gtk::Image()));
685 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
686 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
687 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
688 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
689 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
690 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
691 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
692 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
693 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
694 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
696 actions_action_group->add(Gtk::Action::create(
697 "action-"+iter->second.name,
699 iter->second.local_name,iter->second.local_name
707 Glib::ustring ui_info =
709 " <popup name='menu-toolbox' action='menu-toolbox'>"
710 " <menu action='menu-file'>"
713 " <popup name='menu-main' action='menu-main'>"
714 " <menu action='menu-file'>"
715 " <menuitem action='new' />"
716 " <menuitem action='open' />"
717 " <menuitem action='save' />"
718 " <menuitem action='save-as' />"
719 " <menuitem action='revert' />"
720 " <separator name='bleh01'/>"
721 " <menuitem action='cvs-add' />"
722 " <menuitem action='cvs-update' />"
723 " <menuitem action='cvs-commit' />"
724 " <menuitem action='cvs-revert' />"
725 " <separator name='bleh02'/>"
726 " <menuitem action='import' />"
727 " <separator name='bleh03'/>"
728 " <menuitem action='render' />"
729 " <menuitem action='preview' />"
730 " <menuitem action='sound' />"
731 " <separator name='bleh04'/>"
732 " <menuitem action='options' />"
733 " <menuitem action='close' />"
734 " <menuitem action='close-document' />"
735 " <menuitem action='quit' />"
737 " <menu action='menu-edit'>"
738 " <menuitem action='undo'/>"
739 " <menuitem action='redo'/>"
740 " <separator name='bleh05'/>"
741 " <menuitem action='cut'/>"
742 " <menuitem action='copy'/>"
743 " <menuitem action='paste'/>"
744 " <separator name='bleh06'/>"
745 " <menuitem action='select-all-ducks'/>"
746 " <menuitem action='unselect-all-layers'/>"
747 " <separator name='bleh07'/>"
748 " <menuitem action='properties'/>"
750 " <menu action='menu-view'>"
751 " <menu action='menu-duck-mask'>"
752 " <menuitem action='mask-position-ducks' />"
753 " <menuitem action='mask-vertex-ducks' />"
754 " <menuitem action='mask-tangent-ducks' />"
755 " <menuitem action='mask-radius-ducks' />"
756 " <menuitem action='mask-width-ducks' />"
757 " <menuitem action='mask-angle-ducks' />"
759 " <menu action='menu-preview-quality'>"
760 " <menuitem action='quality-00' />"
761 " <menuitem action='quality-01' />"
762 " <menuitem action='quality-02' />"
763 " <menuitem action='quality-03' />"
764 " <menuitem action='quality-04' />"
765 " <menuitem action='quality-05' />"
766 " <menuitem action='quality-06' />"
767 " <menuitem action='quality-07' />"
768 " <menuitem action='quality-08' />"
769 " <menuitem action='quality-09' />"
770 " <menuitem action='quality-10' />"
772 " <separator name='bleh08'/>"
773 " <menuitem action='play'/>"
774 //" <menuitem action='pause'/>"
775 " <menuitem action='stop'/>"
776 " <menuitem action='dialog-flipbook'/>"
777 " <separator name='bleh09'/>"
778 " <menuitem action='toggle-grid-show'/>"
779 " <menuitem action='toggle-grid-snap'/>"
780 " <menuitem action='toggle-guide-show'/>"
781 " <menuitem action='toggle-low-res'/>"
782 " <menuitem action='toggle-onion-skin'/>"
783 " <separator name='bleh10'/>"
784 " <menuitem action='canvas-zoom-in'/>"
785 " <menuitem action='canvas-zoom-out'/>"
786 " <menuitem action='canvas-zoom-fit'/>"
787 " <menuitem action='canvas-zoom-100'/>"
788 " <separator name='bleh11'/>"
789 " <menuitem action='time-zoom-in'/>"
790 " <menuitem action='time-zoom-out'/>"
791 " <separator name='bleh12'/>"
792 " <menuitem action='jump-next-keyframe'/>"
793 " <menuitem action='jump-prev-keyframe'/>"
794 " <menuitem action='seek-next-frame'/>"
795 " <menuitem action='seek-prev-frame'/>"
796 " <menuitem action='seek-next-second'/>"
797 " <menuitem action='seek-prev-second'/>"
798 " <menuitem action='seek-begin'/>"
799 " <menuitem action='seek-end'/>"
801 " <menu action='menu-canvas'>"
802 " <menuitem action='canvas-new'/>"
804 " <menu name='menu-state' action='menu-state'>"
806 " <menu action='menu-group'>"
807 " <menuitem action='action-group_add'/>"
809 " <menu action='menu-layer'>"
810 //" <menuitem action='cut'/>"
811 //" <menuitem action='copy'/>"
812 //" <menuitem action='paste'/>"
813 //" <separator name='bleh06'/>"
814 " <menu action='menu-layer-new'></menu>"
815 " <menuitem action='amount-inc'/>"
816 " <menuitem action='amount-dec'/>"
818 " <menu action='menu-keyframe'>"
819 " <menuitem action='keyframe-properties'/>"
826 " <menubar name='MenuBar'>"
827 " <menu action='MenuFile'>"
828 " <menuitem action='New'/>"
829 " <menuitem action='Open'/>"
831 " <menuitem action='Quit'/>"
833 " <menu action='MenuEdit'>"
834 " <menuitem action='Cut'/>"
835 " <menuitem action='Copy'/>"
836 " <menuitem action='Paste'/>"
839 " <toolbar name='ToolBar'>"
840 " <toolitem action='Open'/>"
841 " <toolitem action='Quit'/>"
847 actions_action_group->set_sensitive(false);
848 App::ui_manager()->set_add_tearoffs(true);
849 App::ui_manager()->insert_action_group(menus_action_group,1);
850 App::ui_manager()->insert_action_group(actions_action_group,1);
851 App::ui_manager()->add_ui_from_string(ui_info);
853 //App::ui_manager()->get_accel_group()->unlock();
855 catch(const Glib::Error& ex)
857 synfig::error("building menus and toolbars failed: " + ex.what());
860 // Add default keyboard accelerators
861 #define ACCEL(path,accel) \
863 Gtk::AccelKey accel_key(accel,path); \
864 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
867 #define ACCEL2(accel) \
869 Gtk::AccelKey accel_key(accel); \
870 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
873 ACCEL("<Actions>//select-all-ducks","<Control>a");
874 ACCEL("<Actions>//unselect-all-layers","<Control>d");
875 ACCEL("<Actions>//render","F9");
876 ACCEL("<Actions>//preview","F11");
877 ACCEL("<Actions>//properties","F8");
878 ACCEL("<Actions>//options","F12");
879 ACCEL("<Actions>//import","<control>i");
880 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
881 ACCEL("<Actions>//toggle-grid-show","<Control>g");
882 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
883 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
884 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
885 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
886 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
887 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
888 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
889 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
891 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
892 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
894 ACCEL("<Actions>//quality-01","<Control>1");
895 ACCEL("<Actions>//quality-02","<Control>2");
896 ACCEL("<Actions>//quality-03","<Control>3");
897 ACCEL("<Actions>//quality-04","<Control>4");
898 ACCEL("<Actions>//quality-05","<Control>5");
899 ACCEL("<Actions>//quality-06","<Control>6");
900 ACCEL("<Actions>//quality-07","<Control>7");
901 ACCEL("<Actions>//quality-08","<Control>8");
902 ACCEL("<Actions>//quality-09","<Control>9");
903 ACCEL("<Actions>//quality-10","<Control>0");
904 ACCEL("<Actions>//undo","<Control>z");
905 ACCEL("<Actions>//redo","<Control>r");
906 ACCEL("<Actions>//action-layer_remove","Delete");
908 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
909 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
910 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
911 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
912 ACCEL("<Actions>//time-zoom-in","+");
913 ACCEL("<Actions>//time-zoom-out","_");
915 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
916 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
918 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
919 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
920 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
921 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
922 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
923 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
924 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
925 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
926 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
927 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
928 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
929 ACCEL("<Actions>//play", "<Control>p");
930 ACCEL("<Actions>//seek-begin","Home");
931 ACCEL("<Actions>//seek-end","End");
933 ACCEL("<Actions>//state-normal", "<Mod1>a");
934 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
935 ACCEL("<Actions>//state-scale", "<Mod1>d");
936 ACCEL("<Actions>//state-rotate", "<Mod1>s");
938 ACCEL("<Actions>//state-bline", "<Mod1>b");
939 ACCEL("<Actions>//state-circle", "<Mod1>c");
940 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
941 ACCEL("<Actions>//state-gradient", "<Mod1>g");
943 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
944 ACCEL("<Actions>//state-fill", "<Mod1>f");
945 ACCEL("<Actions>//state-zoom", "<Mod1>z");
946 ACCEL("<Actions>//state-polygon", "<Mod1>p");
948 ACCEL("<Actions>//state-draw", "<Mod1>w");
949 ACCEL("<Actions>//state-sketch", "<Mod1>k");
950 ACCEL("<Actions>//state-width", "<Mod1>t");
951 ACCEL("<Actions>//state-mirror", "<Mod1>m");
953 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
959 #define mkdir(x,y) mkdir(x)
962 /* === M E T H O D S ======================================================= */
964 App::App(int *argc, char ***argv):
965 Gtk::Main(argc,argv),
966 IconController(etl::dirname((*argv)[0]))
968 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
971 ui_interface_=new GlobalUIInterface();
975 // don't call thread_init() if threads are already initialized
976 // on some machines bonobo_init() initialized threads before we get here
977 if (!g_thread_supported())
980 distance_system=Distance::SYSTEM_UNITS;
982 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
985 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
989 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
995 if(!SYNFIG_CHECK_VERSION())
997 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
998 dialog_error_blocking("Synfig Studio",
999 "This copy of Synfig Studio was compiled against a\n"
1000 "different version of libsynfig than what is currently\n"
1001 "installed. Synfig Studio will now abort. Try downloading\n"
1002 "the latest version from the Synfig website at\n"
1003 "http://synfig.org/Download"
1007 Glib::set_application_name(_("Synfig Studio"));
1010 about_window.set_can_self_destruct(false);
1011 about_window.show();
1013 shutdown_in_progress=false;
1014 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1015 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1017 // Initialize the Synfig library
1018 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1021 get_ui_interface()->error(_("Failed to initialize synfig!"));
1025 // add the preferences to the settings
1026 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1030 studio_init_cb.task(_("Init UI Manager..."));
1031 App::ui_manager_=studio::UIManager::create();
1034 studio_init_cb.task(_("Init Dock Manager..."));
1035 dock_manager=new studio::DockManager();
1037 studio_init_cb.task(_("Init State Manager..."));
1038 state_manager=new StateManager();
1040 studio_init_cb.task(_("Init Toolbox..."));
1041 toolbox=new studio::Toolbox();
1043 studio_init_cb.task(_("Init Tool Options..."));
1044 dialog_tool_options=new studio::Dialog_ToolOptions();
1045 dock_manager->register_dockable(*dialog_tool_options);
1047 studio_init_cb.task(_("Init History..."));
1048 dock_history=new studio::Dock_History();
1049 dock_manager->register_dockable(*dock_history);
1051 studio_init_cb.task(_("Init Canvases..."));
1052 dock_canvases=new studio::Dock_Canvases();
1053 dock_manager->register_dockable(*dock_canvases);
1055 studio_init_cb.task(_("Init Keyframes..."));
1056 dock_keyframes=new studio::Dock_Keyframes();
1057 dock_manager->register_dockable(*dock_keyframes);
1059 studio_init_cb.task(_("Init Layers..."));
1060 dock_layers=new studio::Dock_Layers();
1061 dock_manager->register_dockable(*dock_layers);
1063 studio_init_cb.task(_("Init Params..."));
1064 dock_params=new studio::Dock_Params();
1065 dock_manager->register_dockable(*dock_params);
1067 studio_init_cb.task(_("Init MetaData..."));
1068 dock_meta_data=new studio::Dock_MetaData();
1069 dock_manager->register_dockable(*dock_meta_data);
1071 studio_init_cb.task(_("Init Children..."));
1072 dock_children=new studio::Dock_Children();
1073 dock_manager->register_dockable(*dock_children);
1075 studio_init_cb.task(_("Init Info..."));
1076 dock_info = new studio::Dock_Info();
1077 dock_manager->register_dockable(*dock_info);
1079 studio_init_cb.task(_("Init Navigator..."));
1080 dock_navigator = new studio::Dock_Navigator();
1081 dock_manager->register_dockable(*dock_navigator);
1083 studio_init_cb.task(_("Init Timetrack..."));
1084 dock_timetrack = new studio::Dock_Timetrack();
1085 dock_manager->register_dockable(*dock_timetrack);
1087 studio_init_cb.task(_("Init Curve Editor..."));
1088 dock_curves = new studio::Dock_Curves();
1089 dock_manager->register_dockable(*dock_curves);
1091 studio_init_cb.task(_("Init Layer Groups..."));
1092 dock_layer_groups = new studio::Dock_LayerGroups();
1093 dock_manager->register_dockable(*dock_layer_groups);
1096 studio_init_cb.task(_("Init Color Dialog..."));
1097 dialog_color=new studio::Dialog_Color();
1099 studio_init_cb.task(_("Init Gradient Dialog..."));
1100 dialog_gradient=new studio::Dialog_Gradient();
1102 studio_init_cb.task(_("Init DeviceTracker..."));
1103 device_tracker=new studio::DeviceTracker();
1105 studio_init_cb.task(_("Init Tools..."));
1106 state_manager->add_state(&state_normal);
1107 state_manager->add_state(&state_smooth_move);
1108 state_manager->add_state(&state_scale);
1109 state_manager->add_state(&state_rotate);
1111 state_manager->add_state(&state_bline);
1114 state_manager->add_state(&state_circle);
1115 state_manager->add_state(&state_rectangle);
1117 state_manager->add_state(&state_gradient);
1118 state_manager->add_state(&state_eyedrop);
1119 state_manager->add_state(&state_fill);
1121 state_manager->add_state(&state_zoom);
1123 // Enabled - it's useful to be able to work with polygons without tangent ducks getting in the way.
1124 // I know we can switch tangent ducks off, but why not allow this kind of layer as well?
1125 if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon);
1127 // Enabled for now. Let's see whether they're good enough yet.
1128 if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw);
1129 if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
1131 // Disabled by default - it doesn't work properly?
1132 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1134 studio_init_cb.task(_("Init ModPalette..."));
1135 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1137 studio_init_cb.task(_("Init ModMirror..."));
1138 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1141 studio_init_cb.task(_("Init Setup Dialog..."));
1142 dialog_setup=new studio::Dialog_Setup();
1144 studio_init_cb.task(_("Init Input Dialog..."));
1145 dialog_input=new Gtk::InputDialog();
1146 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1147 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1149 studio_init_cb.task(_("Init auto recovery..."));
1150 auto_recover=new AutoRecover();
1152 studio_init_cb.amount_complete(9250,10000);
1153 studio_init_cb.task(_("Loading Settings..."));
1155 studio_init_cb.task(_("Checking auto-recover..."));
1157 studio_init_cb.amount_complete(9900,10000);
1159 if(auto_recover->recovery_needed())
1161 about_window.hide();
1163 get_ui_interface()->yes_no(
1165 _("Synfig Studio seems to have crashed\n"
1166 "before you could save all your files.\n"
1167 "Would you like to re-open those files\n"
1168 "and recover your unsaved changes?")
1169 )==synfigapp::UIInterface::RESPONSE_YES
1172 if(!auto_recover->recover())
1174 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1177 get_ui_interface()->error(
1178 _("Synfig Studio has attempted to recover\n"
1179 "from a previous crash. The files that it has\n"
1180 "recovered are NOT YET SAVED. It would be a good\n"
1181 "idea to review them and save them now.")
1184 about_window.show();
1187 // Look for any files given on the command line,
1188 // and load them if found.
1189 bool opened_any = false;
1190 for(;*argc>=1;(*argc)--)
1191 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1193 studio_init_cb.task(_("Loading files..."));
1194 about_window.hide();
1195 open((*argv)[*argc]);
1197 about_window.show();
1200 // if no file was specified to be opened, create a new document to help new users get started more easily
1204 studio_init_cb.task(_("Done."));
1205 studio_init_cb.amount_complete(10000,10000);
1211 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1215 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1219 StateManager* App::get_state_manager() { return state_manager; }
1223 shutdown_in_progress=true;
1227 synfigapp::Main::settings().remove_domain("pref");
1229 selected_instance=0;
1231 // Unload all of the modules
1232 for(;!module_list_.empty();module_list_.pop_back())
1235 delete state_manager;
1239 delete auto_recover;
1243 // studio::App::iteration(false);
1247 // studio::App::iteration(false);
1249 // studio::App::iteration(false);
1251 delete dialog_setup;
1253 delete dialog_gradient;
1255 delete dialog_color;
1257 delete dialog_input;
1259 delete dock_manager;
1261 instance_list.clear();
1263 // studio::App::iteration(false);
1267 App::get_user_app_directory()
1269 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1273 App::get_config_file(const synfig::String& file)
1275 return Glib::build_filename(get_user_app_directory(),file);
1279 App::add_recent_file(const std::string &file_name)
1281 std::string filename(file_name);
1283 assert(!filename.empty());
1285 if(filename.empty())
1288 // Toss out any "hidden" files
1289 if(basename(filename)[0]=='.')
1292 // If we aren't an absolute path, turn ourselves into one
1293 if(!is_absolute_path(filename))
1294 filename=absolute_path(filename);
1296 list<string>::iterator iter;
1297 // Check to see if the file is already on the list.
1298 // If it is, then remove it from the list
1299 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1302 recent_files.erase(iter);
1307 // Push the filename to the front of the list
1308 recent_files.push_front(filename);
1310 // Clean out the files at the end of the list.
1311 while(recent_files.size()>(unsigned)get_max_recent_files())
1312 recent_files.pop_back();
1314 signal_recent_files_changed_();
1319 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1322 App::get_time_format()
1324 return _App_time_format;
1328 App::set_time_format(synfig::Time::Format x)
1335 App::save_settings()
1340 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1341 setlocale(LC_NUMERIC, "C");
1343 std::string filename=get_config_file("accelrc");
1344 Gtk::AccelMap::save(filename);
1347 std::string filename=get_config_file("recentfiles");
1349 std::ofstream file(filename.c_str());
1353 synfig::warning("Unable to save %s",filename.c_str());
1357 list<string>::reverse_iterator iter;
1359 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1363 std::string filename=get_config_file("settings");
1364 synfigapp::Main::settings().save_to_file(filename);
1365 setlocale(LC_NUMERIC,old_locale);
1369 synfig::warning("Caught exception when attempting to save settings.");
1374 App::load_settings()
1379 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1380 setlocale(LC_NUMERIC, "C");
1382 std::string filename=get_config_file("accelrc");
1383 Gtk::AccelMap::load(filename);
1386 std::string filename=get_config_file("recentfiles");
1388 std::ifstream file(filename.c_str());
1392 std::string recent_file;
1393 getline(file,recent_file);
1394 if(!recent_file.empty())
1395 add_recent_file(recent_file);
1398 std::string filename=get_config_file("settings");
1399 if(!synfigapp::Main::settings().load_from_file(filename))
1401 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1402 //if(!synfigapp::Main::settings().load_from_file(filename))
1404 gamma.set_gamma(1.0/2.2);
1405 reset_initial_window_configuration();
1408 setlocale(LC_NUMERIC,old_locale);
1412 synfig::warning("Caught exception when attempting to load settings.");
1417 App::reset_initial_window_configuration()
1419 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1420 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1421 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1422 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1423 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1424 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1425 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1426 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1427 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1428 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1429 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1430 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1431 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1432 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1436 App::shutdown_request(GdkEventAny*)
1440 //return !shutdown_in_progress;
1446 if(shutdown_in_progress)return;
1449 get_ui_interface()->task(_("Quit Request"));
1452 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1456 std::list<etl::handle<Instance> >::iterator iter;
1457 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1459 if(!(*iter)->safe_close())
1463 if((*iter)->synfigapp::Instance::get_action_count())
1465 handle<synfigapp::UIInterface> uim;
1466 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1468 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1469 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1471 case synfigapp::UIInterface::RESPONSE_NO:
1473 case synfigapp::UIInterface::RESPONSE_YES:
1476 case synfigapp::UIInterface::RESPONSE_CANCEL:
1485 if((*iter)->synfigapp::Instance::is_modified())
1487 handle<synfigapp::UIInterface> uim;
1488 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1490 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() );
1491 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1493 case synfigapp::UIInterface::RESPONSE_NO:
1495 case synfigapp::UIInterface::RESPONSE_YES:
1496 (*iter)->dialog_cvs_commit();
1498 case synfigapp::UIInterface::RESPONSE_CANCEL:
1507 // This next line causes things to crash for some reason
1511 shutdown_in_progress=true;
1513 instance_list.clear();
1515 while(studio::App::events_pending())studio::App::iteration(false);
1518 auto_recover->normal_shutdown();
1520 get_ui_interface()->task(_("Quit Request sent"));
1526 dialog_setup->refresh();
1527 dialog_setup->show();
1530 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1531 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1534 //#define USE_WIN32_FILE_DIALOGS 1
1537 #ifdef USE_WIN32_FILE_DIALOGS
1538 static OPENFILENAME ofn={};
1542 #include <gdk/gdkwin32.h>
1546 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1548 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1550 #ifdef USE_WIN32_FILE_DIALOGS
1551 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1553 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1554 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1555 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1557 ofn.lStructSize=sizeof(OPENFILENAME);
1558 ofn.hwndOwner = hWnd;
1559 ofn.hInstance = hInstance;
1560 ofn.lpstrFilter = szFilter;
1561 // ofn.lpstrCustomFilter=NULL;
1562 // ofn.nMaxCustFilter=0;
1563 // ofn.nFilterIndex=0;
1564 // ofn.lpstrFile=NULL;
1565 ofn.nMaxFile=MAX_PATH;
1566 // ofn.lpstrFileTitle=NULL;
1567 // ofn.lpstrInitialDir=NULL;
1568 // ofn.lpstrTitle=NULL;
1569 ofn.Flags=OFN_HIDEREADONLY;
1570 // ofn.nFileOffset=0;
1571 // ofn.nFileExtension=0;
1572 ofn.lpstrDefExt=TEXT("sif");
1573 // ofn.lCustData = 0l;
1575 // ofn.lpTemplateName=NULL;
1577 CHAR szFilename[MAX_PATH];
1579 strcpy(szFilename,filename.c_str());
1580 strcpy(szTitle,title.c_str());
1582 ofn.lpstrFile=szFilename;
1583 ofn.lpstrFileTitle=szTitle;
1585 if(GetOpenFileName(&ofn))
1587 filename=szFilename;
1593 synfig::String prev_path;
1595 if(!_preferences.get_value(preference, prev_path))
1598 prev_path = absolute_path(prev_path);
1600 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1602 dialog->set_current_folder(prev_path);
1603 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1604 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1606 if (filename.empty())
1607 dialog->set_filename(prev_path);
1608 else if (is_absolute_path(filename))
1609 dialog->set_filename(filename);
1611 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1613 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1614 filename = dialog->get_filename();
1615 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1616 _preferences.set_value(preference, dirname(filename));
1630 GtkWidget *fileselection;
1631 fileselection = gtk_file_selection_new(title.c_str());
1634 if(basename(filename)==filename)
1636 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1639 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1641 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1643 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1644 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1646 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1647 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1649 gtk_widget_show(fileselection);
1657 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1658 _preferences.set_value(preference,dirname(filename));
1662 gtk_widget_destroy(fileselection);
1665 gtk_widget_destroy(fileselection);
1672 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1674 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1676 #if USE_WIN32_FILE_DIALOGS
1677 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1679 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1680 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1681 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1683 ofn.lStructSize=sizeof(OPENFILENAME);
1684 ofn.hwndOwner = hWnd;
1685 ofn.hInstance = hInstance;
1686 ofn.lpstrFilter = szFilter;
1687 // ofn.lpstrCustomFilter=NULL;
1688 // ofn.nMaxCustFilter=0;
1689 // ofn.nFilterIndex=0;
1690 // ofn.lpstrFile=NULL;
1691 ofn.nMaxFile=MAX_PATH;
1692 // ofn.lpstrFileTitle=NULL;
1693 // ofn.lpstrInitialDir=NULL;
1694 // ofn.lpstrTitle=NULL;
1695 ofn.Flags=OFN_OVERWRITEPROMPT;
1696 // ofn.nFileOffset=0;
1697 // ofn.nFileExtension=0;
1698 ofn.lpstrDefExt=TEXT("sif");
1699 // ofn.lCustData = 0l;
1701 // ofn.lpTemplateName=NULL;
1703 CHAR szFilename[MAX_PATH];
1705 strcpy(szFilename,filename.c_str());
1706 strcpy(szTitle,title.c_str());
1708 ofn.lpstrFile=szFilename;
1709 ofn.lpstrFileTitle=szTitle;
1711 if(GetSaveFileName(&ofn))
1713 filename=szFilename;
1714 _preferences.set_value(preference,dirname(filename));
1719 synfig::String prev_path;
1721 if(!_preferences.get_value(preference, prev_path))
1724 prev_path = absolute_path(prev_path);
1726 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1728 dialog->set_current_folder(prev_path);
1729 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1730 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1732 if (filename.empty())
1733 dialog->set_filename(prev_path);
1736 std::string full_path;
1737 if (is_absolute_path(filename))
1738 full_path = filename;
1740 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1742 // select the file if it exists
1743 dialog->set_filename(full_path);
1745 // if the file doesn't exist, put its name into the filename box
1747 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1748 dialog->set_current_name(basename(filename));
1751 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1752 filename = dialog->get_filename();
1753 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
1754 _preferences.set_value(preference, dirname(filename));
1765 App::dialog_error_blocking(const std::string &title, const std::string &message)
1767 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1768 dialog.set_title(title);
1774 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1776 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
1777 dialog.set_title(title);
1783 App::dialog_yes_no(const std::string &title, const std::string &message)
1788 true // use_separator
1790 Gtk::Label label(message);
1793 dialog.get_vbox()->pack_start(label);
1794 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1795 dialog.add_button(Gtk::StockID("gtk-no"),0);
1797 return dialog.run();
1801 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1806 true // use_separator
1808 Gtk::Label label(message);
1811 dialog.get_vbox()->pack_start(label);
1812 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1813 dialog.add_button(Gtk::StockID("gtk-no"),0);
1814 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1816 return dialog.run();
1820 App::dialog_not_implemented()
1822 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1823 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
1828 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1833 true // use_separator
1835 Gtk::Label label(message);
1837 dialog.get_vbox()->pack_start(label);
1840 entry.set_text(text);
1842 entry.set_activates_default(true);
1843 dialog.get_vbox()->pack_start(entry);
1845 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1846 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1847 dialog.set_default_response(Gtk::RESPONSE_OK);
1848 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1851 if(dialog.run()!=Gtk::RESPONSE_OK)
1854 text=entry.get_text();
1863 App::open(std::string filename)
1865 return open_as(filename,filename);
1868 // this is called from autorecover.cpp:
1869 // App::open_as(get_shadow_file_name(filename),filename)
1870 // other than that, 'filename' and 'as' are the same
1872 App::open_as(std::string filename,std::string as)
1875 char long_name[1024];
1876 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1882 OneMoment one_moment;
1884 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1885 if(canvas && get_instance(canvas))
1887 get_instance(canvas)->find_canvas_view(canvas)->present();
1888 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1891 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1893 add_recent_file(as);
1895 handle<Instance> instance(Instance::create(canvas));
1898 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1902 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)")))
1903 instance->dialog_cvs_update();
1907 dialog_error_blocking(_("Error"), x);
1912 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1923 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1924 canvas->set_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
1926 String file_name(strprintf("%s%d.sifz", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
1928 canvas->rend_desc().set_frame_rate(24.0);
1929 canvas->rend_desc().set_time_start(0.0);
1930 canvas->rend_desc().set_time_end(5.0);
1931 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1932 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1933 canvas->rend_desc().set_tl(Vector(-4,2.25));
1934 canvas->rend_desc().set_br(Vector(4,-2.25));
1935 canvas->rend_desc().set_w(480);
1936 canvas->rend_desc().set_h(270);
1937 canvas->rend_desc().set_antialias(1);
1938 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1939 canvas->set_file_name(file_name);
1941 handle<Instance> instance = Instance::create(canvas);
1943 if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
1944 instance->find_canvas_view(canvas)->canvas_properties.present();
1950 string filename="*.sif";
1952 while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
1954 // If the filename still has wildcards, then we should
1955 // continue looking for the file we want
1956 if(find(filename.begin(),filename.end(),'*')!=filename.end())
1962 get_ui_interface()->error(_("Unable to open file"));
1967 App::set_selected_instance(etl::loose_handle<Instance> instance)
1969 /* if(get_selected_instance()==instance)
1971 selected_instance=instance;
1972 signal_instance_selected()(instance);
1978 selected_instance=instance;
1979 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
1983 instance->focus(instance->get_canvas());
1986 set_selected_canvas_view(0);
1988 signal_instance_selected()(instance);
1992 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
1994 selected_canvas_view=canvas_view;
1995 signal_canvas_view_focus()(selected_canvas_view);
1998 selected_instance=canvas_view->get_instance();
1999 signal_instance_selected()(canvas_view->get_instance());
2002 if(get_selected_canvas_view()==canvas_view)
2004 signal_canvas_view_focus()(selected_canvas_view);
2005 signal_instance_selected()(canvas_view->get_instance());
2008 selected_canvas_view=canvas_view;
2009 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2010 set_selected_instance(canvas_view->get_instance());
2011 signal_canvas_view_focus()(selected_canvas_view);
2015 etl::loose_handle<Instance>
2016 App::get_instance(etl::handle<synfig::Canvas> canvas)
2018 if(!canvas) return 0;
2019 canvas=canvas->get_root();
2021 std::list<etl::handle<Instance> >::iterator iter;
2022 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2024 if((*iter)->get_canvas()==canvas)
2033 (new class About())->show();
2039 if(selected_instance)
2040 selected_instance->undo();
2046 if(selected_instance)
2047 selected_instance->redo();
2051 studio::App::get_base_path()
2053 return app_base_path_;