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 ======================================================= */
37 #ifdef HAVE_SYS_ERRNO_H
38 #include <sys/errno.h>
40 #include <gtkmm/fileselection.h>
41 #include <gtkmm/dialog.h>
42 #include <gtkmm/messagedialog.h>
43 #include <gtkmm/label.h>
44 #include <gtkmm/stock.h>
45 #include <gtkmm/stockitem.h>
46 #include <gtkmm/iconsource.h>
47 #include <gtkmm/inputdialog.h>
48 #include <gtkmm/accelmap.h>
49 #include <gtkmm/uimanager.h>
53 #include <synfig/loadcanvas.h>
58 #include "canvasview.h"
59 #include "dialog_setup.h"
60 #include "dialog_gradient.h"
61 #include "dialog_color.h"
64 #include "onemoment.h"
66 #include "dockmanager.h"
68 #include "state_eyedrop.h"
69 #include "state_normal.h"
70 #include "state_draw.h"
71 #include "state_fill.h"
72 #include "state_bline.h"
73 #include "state_polygon.h"
74 #include "state_sketch.h"
75 #include "state_gradient.h"
76 #include "state_circle.h"
77 #include "state_rectangle.h"
78 #include "state_smoothmove.h"
79 #include "state_scale.h"
80 #include "state_width.h"
81 #include "state_rotate.h"
82 #include "state_zoom.h"
84 #include "devicetracker.h"
85 #include "dialog_tooloptions.h"
87 #include "autorecover.h"
89 #include <synfigapp/settings.h>
90 #include "dock_history.h"
91 #include "dock_canvases.h"
92 #include "dock_keyframes.h"
93 #include "dock_layers.h"
94 #include "dock_params.h"
95 #include "dock_metadata.h"
96 #include "dock_children.h"
97 #include "dock_info.h"
98 #include "dock_navigator.h"
99 #include "dock_layergroups.h"
100 #include "dock_timetrack.h"
101 #include "dock_curves.h"
103 #include "mod_palette/mod_palette.h"
104 #include "mod_mirror/mod_mirror.h"
106 #include <sys/stat.h>
112 #include "statemanager.h"
119 #define _WIN32_WINNT 0x0500
122 #include <gtkmm/accelmap.h>
123 #include <gtkmm/filechooser.h>
124 #include <gtkmm/filechooserdialog.h>
130 /* === U S I N G =========================================================== */
134 using namespace synfig;
135 using namespace studio;
137 /* === M A C R O S ========================================================= */
139 #ifndef SYNFIG_USER_APP_DIR
141 #define SYNFIG_USER_APP_DIR "Library/Synfig"
142 #elif defined(_WIN32)
143 #define SYNFIG_USER_APP_DIR "Synfig"
145 #define SYNFIG_USER_APP_DIR ".synfig"
150 #define DPM2DPI(x) (float(x)/39.3700787402f)
151 #define DPI2DPM(x) (float(x)*39.3700787402f)
157 # define IMAGE_DIR "share\\pixmaps"
162 # define IMAGE_DIR "/usr/local/share/pixmaps"
166 # define IMAGE_EXT "tif"
169 #include <synfigapp/main.h>
171 /* === S I G N A L S ======================================================= */
173 static sigc::signal<void> signal_present_all_;
175 App::signal_present_all() { return signal_present_all_; }
177 static sigc::signal<void> signal_recent_files_changed_;
179 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
181 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
182 sigc::signal<void,etl::loose_handle<CanvasView> >&
183 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
185 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
186 sigc::signal<void,etl::handle<Instance> >&
187 App::signal_instance_selected() { return signal_instance_selected_; }
189 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
190 sigc::signal<void,etl::handle<Instance> >&
191 App::signal_instance_created() { return signal_instance_created_; }
193 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
194 sigc::signal<void,etl::handle<Instance> >&
195 App::signal_instance_deleted() { return signal_instance_deleted_; }
197 /* === G L O B A L S ======================================================= */
199 static std::list<std::string> recent_files;
200 const std::list<std::string>& App::get_recent_files() { return recent_files; }
202 int App::Busy::count;
203 bool App::shutdown_in_progress;
205 synfig::Gamma App::gamma;
207 Glib::RefPtr<studio::UIManager> App::ui_manager_;
209 synfig::Distance::System App::distance_system;
211 studio::Dialog_Setup* App::dialog_setup;
213 etl::handle< studio::ModPalette > mod_palette_;
214 //studio::Dialog_Palette* App::dialog_palette;
216 std::list<etl::handle<Instance> > App::instance_list;
218 static etl::handle<synfigapp::UIInterface> ui_interface_;
219 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
221 etl::handle<Instance> App::selected_instance;
222 etl::handle<CanvasView> App::selected_canvas_view;
224 studio::Toolbox *studio::App::toolbox=NULL;
226 studio::AutoRecover *studio::App::auto_recover=NULL;
228 studio::IPC *ipc=NULL;
230 studio::DockManager* studio::App::dock_manager=0;
232 studio::DeviceTracker* studio::App::device_tracker=0;
234 studio::Dialog_Gradient* studio::App::dialog_gradient;
236 studio::Dialog_Color* studio::App::dialog_color;
238 Gtk::InputDialog* studio::App::dialog_input;
240 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
242 studio::Dock_History* dock_history;
243 studio::Dock_Canvases* dock_canvases;
244 studio::Dock_Keyframes* dock_keyframes;
245 studio::Dock_Layers* dock_layers;
246 studio::Dock_Params* dock_params;
247 studio::Dock_MetaData* dock_meta_data;
248 studio::Dock_Children* dock_children;
249 studio::Dock_Info* dock_info;
250 studio::Dock_LayerGroups* dock_layer_groups;
251 studio::Dock_Navigator* dock_navigator;
252 studio::Dock_Timetrack* dock_timetrack;
253 studio::Dock_Curves* dock_curves;
255 std::list< etl::handle< studio::Module > > module_list_;
257 bool studio::App::use_colorspace_gamma=true;
258 bool studio::App::single_threaded=false;
260 static int max_recent_files_=25;
261 int studio::App::get_max_recent_files() { return max_recent_files_; }
262 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
264 static synfig::String app_base_path_;
269 really_delete_widget(Gtk::Widget *widget)
271 synfig::info("really delete %p", (void*)widget);
276 // nasty workaround - when we've finished with a popup menu, we want to delete it
277 // attaching to the signal_hide() signal gets us here before the action on the menu has run,
278 // so schedule the real delete to happen in 50ms, giving the action a chance to run
280 delete_widget(Gtk::Widget *widget)
282 synfig::info("delete %p", (void*)widget);
283 Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
286 }; // END of namespace studio
287 studio::StateManager* state_manager;
292 class GlobalUIInterface : public synfigapp::UIInterface
296 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
301 true // use_separator
303 Gtk::Label label(message);
306 dialog.get_vbox()->pack_start(label);
307 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
308 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
310 dialog.set_default_response(dflt);
312 return (Response)dialog.run();
314 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
319 true // use_separator
321 Gtk::Label label(message);
324 dialog.get_vbox()->pack_start(label);
325 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
326 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
327 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
329 dialog.set_default_response(dflt);
331 return (Response)dialog.run();
333 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
338 true // use_separator
340 Gtk::Label label(message);
343 dialog.get_vbox()->pack_start(label);
344 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
345 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
347 dialog.set_default_response(dflt);
349 return (Response)dialog.run();
353 task(const std::string &task)
355 std::cerr<<task<<std::endl;
356 while(studio::App::events_pending())studio::App::iteration(false);
361 error(const std::string &err)
363 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
370 warning(const std::string &err)
372 std::cerr<<"warning: "<<err<<std::endl;
373 while(studio::App::events_pending())studio::App::iteration(false);
378 amount_complete(int /*current*/, int /*total*/)
380 while(studio::App::events_pending())studio::App::iteration(false);
385 /* === P R O C E D U R E S ================================================= */
389 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
391 action_group_list.push_back(action_group);
392 Gtk::UIManager::insert_action_group(action_group, pos);
396 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
398 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
399 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
400 if(*iter==action_group)
402 action_group_list.erase(iter);
403 Gtk::UIManager::remove_action_group(action_group);
406 synfig::error("Unable to find action group");
410 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
412 ui_manager->insert_action_group(group,0);
414 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
415 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
417 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
419 if(*iter && (*iter)->get_name()!="menus")
421 synfig::info("Removing action group "+(*iter)->get_name());
422 ui_manager->remove_action_group(*iter);
425 ui_manager->insert_action_group(group,0);
427 for(;!prev_groups.empty();prev_groups.pop_front())
429 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
430 ui_manager->insert_action_group(prev_groups.front(),1);
434 class Preferences : public synfigapp::Settings
437 virtual bool get_value(const synfig::String& key, synfig::String& value)const
441 value=strprintf("%f %f %f %f",
442 App::gamma.get_gamma_r(),
443 App::gamma.get_gamma_g(),
444 App::gamma.get_gamma_b(),
445 App::gamma.get_black_level()
449 if(key=="time_format")
451 value=strprintf("%i",App::get_time_format());
454 if(key=="file_history.size")
456 value=strprintf("%i",App::get_max_recent_files());
459 if(key=="use_colorspace_gamma")
461 value=strprintf("%i",(int)App::use_colorspace_gamma);
464 if(key=="distance_system")
466 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
469 if(key=="single_threaded")
471 value=strprintf("%i",(int)App::single_threaded);
474 if(key=="auto_recover_backup_interval")
476 value=strprintf("%i",App::auto_recover->get_timeout());
480 return synfigapp::Settings::get_value(key,value);
483 virtual bool set_value(const synfig::String& key,const synfig::String& value)
489 strscanf(value,"%f %f %f %f",
496 App::gamma.set_all(r,g,b,blk);
500 if(key=="time_format")
502 int i(atoi(value.c_str()));
503 App::set_time_format(static_cast<synfig::Time::Format>(i));
506 if(key=="auto_recover_backup_interval")
508 int i(atoi(value.c_str()));
509 App::auto_recover->set_timeout(i);
512 if(key=="file_history.size")
514 int i(atoi(value.c_str()));
515 App::set_max_recent_files(i);
518 if(key=="use_colorspace_gamma")
520 int i(atoi(value.c_str()));
521 App::use_colorspace_gamma=i;
524 if(key=="distance_system")
526 App::distance_system=Distance::ident_system(value);;
529 if(key=="single_threaded")
531 int i(atoi(value.c_str()));
532 App::single_threaded=i;
536 return synfigapp::Settings::set_value(key,value);
539 virtual KeyList get_key_list()const
541 KeyList ret(synfigapp::Settings::get_key_list());
542 ret.push_back("gamma");
543 ret.push_back("time_format");
544 ret.push_back("distance_system");
545 ret.push_back("file_history.size");
546 ret.push_back("use_colorspace_gamma");
547 ret.push_back("single_threaded");
548 ret.push_back("auto_recover_backup_interval");
553 static ::Preferences _preferences;
558 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
560 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
562 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
564 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
565 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
566 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
567 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
568 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
569 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
570 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
571 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
572 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
573 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
574 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
575 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
577 // Add the synfigapp actions...
578 synfigapp::Action::Book::iterator iter;
579 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
581 actions_action_group->add(Gtk::Action::create(
582 "action-"+iter->second.name,
583 get_action_stock_id(iter->second),
584 iter->second.local_name,iter->second.local_name
588 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
589 #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); }
590 #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); }
592 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
593 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
594 DEFINE_ACTION("open", Gtk::Stock::OPEN);
595 DEFINE_ACTION("save", Gtk::Stock::SAVE);
596 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
597 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
598 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
599 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
600 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
601 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
602 DEFINE_ACTION("import", _("Import"));
603 DEFINE_ACTION("render", _("Render"));
604 DEFINE_ACTION("preview", _("Preview"));
605 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
606 DEFINE_ACTION("sound", _("Sound File"));
607 DEFINE_ACTION("options", _("Options"));
608 DEFINE_ACTION("close", _("Close View"));
609 DEFINE_ACTION("close-document", _("Close Document"));
612 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
613 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
614 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
615 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
616 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
617 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
618 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
619 DEFINE_ACTION("properties", _("Properties"));
621 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
622 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
623 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
624 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
625 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
626 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
627 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
628 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
629 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
630 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
631 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
632 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
633 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
634 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
635 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
636 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
637 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
638 DEFINE_ACTION("play", _("Play"));
639 // DEFINE_ACTION("pause", _("Pause"));
640 DEFINE_ACTION("stop", _("Stop"));
641 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
642 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
643 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
644 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
645 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
646 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
647 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
648 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
649 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
650 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
651 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
652 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
653 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
654 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
655 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
656 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
657 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
658 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
659 DEFINE_ACTION("seek-end", _("Seek to End"));
661 DEFINE_ACTION("action-group_add", _("Add group"));
663 DEFINE_ACTION("canvas-new", _("New Canvas"));
665 DEFINE_ACTION("amount-inc", _("Increase Amount"));
666 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
671 // Set up synfigapp actions
673 synfigapp::Action::Book::iterator iter;
675 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
677 Gtk::StockID stock_id;
679 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
681 //Gtk::Image* image(manage(new Gtk::Image()));
682 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
683 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
684 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
685 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
686 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
687 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
688 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
689 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
690 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
691 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
693 actions_action_group->add(Gtk::Action::create(
694 "action-"+iter->second.name,
696 iter->second.local_name,iter->second.local_name
704 Glib::ustring ui_info =
706 " <popup name='menu-toolbox' action='menu-toolbox'>"
707 " <menu action='menu-file'>"
710 " <popup name='menu-main' action='menu-main'>"
711 " <menu action='menu-file'>"
712 " <menuitem action='save' />"
713 " <menuitem action='save-as' />"
714 " <menuitem action='revert' />"
715 " <separator name='bleh01'/>"
716 " <menuitem action='cvs-add' />"
717 " <menuitem action='cvs-update' />"
718 " <menuitem action='cvs-commit' />"
719 " <menuitem action='cvs-revert' />"
720 " <separator name='bleh02'/>"
721 " <menuitem action='import' />"
722 " <separator name='bleh03'/>"
723 " <menuitem action='render' />"
724 " <menuitem action='preview' />"
725 " <menuitem action='sound' />"
726 " <separator name='bleh04'/>"
727 " <menuitem action='options' />"
728 " <menuitem action='close' />"
729 " <menuitem action='close-document' />"
731 " <menu action='menu-edit'>"
732 " <menuitem action='undo'/>"
733 " <menuitem action='redo'/>"
734 " <separator name='bleh05'/>"
735 " <menuitem action='cut'/>"
736 " <menuitem action='copy'/>"
737 " <menuitem action='paste'/>"
738 " <separator name='bleh06'/>"
739 " <menuitem action='select-all-ducks'/>"
740 " <menuitem action='unselect-all-layers'/>"
741 " <separator name='bleh07'/>"
742 " <menuitem action='properties'/>"
744 " <menu action='menu-view'>"
745 " <menu action='menu-duck-mask'>"
746 " <menuitem action='mask-position-ducks' />"
747 " <menuitem action='mask-vertex-ducks' />"
748 " <menuitem action='mask-tangent-ducks' />"
749 " <menuitem action='mask-radius-ducks' />"
750 " <menuitem action='mask-width-ducks' />"
751 " <menuitem action='mask-angle-ducks' />"
753 " <menu action='menu-preview-quality'>"
754 " <menuitem action='quality-00' />"
755 " <menuitem action='quality-01' />"
756 " <menuitem action='quality-02' />"
757 " <menuitem action='quality-03' />"
758 " <menuitem action='quality-04' />"
759 " <menuitem action='quality-05' />"
760 " <menuitem action='quality-06' />"
761 " <menuitem action='quality-07' />"
762 " <menuitem action='quality-08' />"
763 " <menuitem action='quality-09' />"
764 " <menuitem action='quality-10' />"
766 " <separator name='bleh08'/>"
767 " <menuitem action='play'/>"
768 //" <menuitem action='pause'/>"
769 " <menuitem action='stop'/>"
770 " <menuitem action='dialog-flipbook'/>"
771 " <separator name='bleh09'/>"
772 " <menuitem action='toggle-grid-show'/>"
773 " <menuitem action='toggle-grid-snap'/>"
774 " <menuitem action='toggle-guide-show'/>"
775 " <menuitem action='toggle-low-res'/>"
776 " <menuitem action='toggle-onion-skin'/>"
777 " <separator name='bleh10'/>"
778 " <menuitem action='canvas-zoom-in'/>"
779 " <menuitem action='canvas-zoom-out'/>"
780 " <menuitem action='canvas-zoom-fit'/>"
781 " <menuitem action='canvas-zoom-100'/>"
782 " <separator name='bleh11'/>"
783 " <menuitem action='time-zoom-in'/>"
784 " <menuitem action='time-zoom-out'/>"
785 " <separator name='bleh12'/>"
786 " <menuitem action='jump-next-keyframe'/>"
787 " <menuitem action='jump-prev-keyframe'/>"
788 " <menuitem action='seek-next-frame'/>"
789 " <menuitem action='seek-prev-frame'/>"
790 " <menuitem action='seek-next-second'/>"
791 " <menuitem action='seek-prev-second'/>"
792 " <menuitem action='seek-begin'/>"
793 " <menuitem action='seek-end'/>"
795 " <menu action='menu-canvas'>"
796 " <menuitem action='canvas-new'/>"
798 " <menu name='menu-state' action='menu-state'>"
800 " <menu action='menu-group'>"
801 " <menuitem action='action-group_add'/>"
803 " <menu action='menu-layer'>"
804 //" <menuitem action='cut'/>"
805 //" <menuitem action='copy'/>"
806 //" <menuitem action='paste'/>"
807 //" <separator name='bleh06'/>"
808 " <menu action='menu-layer-new'></menu>"
809 " <menuitem action='amount-inc'/>"
810 " <menuitem action='amount-dec'/>"
812 " <menu action='menu-keyframe'>"
813 " <menuitem action='keyframe-properties'/>"
820 " <menubar name='MenuBar'>"
821 " <menu action='MenuFile'>"
822 " <menuitem action='New'/>"
823 " <menuitem action='Open'/>"
825 " <menuitem action='Quit'/>"
827 " <menu action='MenuEdit'>"
828 " <menuitem action='Cut'/>"
829 " <menuitem action='Copy'/>"
830 " <menuitem action='Paste'/>"
833 " <toolbar name='ToolBar'>"
834 " <toolitem action='Open'/>"
835 " <toolitem action='Quit'/>"
841 actions_action_group->set_sensitive(false);
842 App::ui_manager()->set_add_tearoffs(true);
843 App::ui_manager()->insert_action_group(menus_action_group,1);
844 App::ui_manager()->insert_action_group(actions_action_group,1);
845 App::ui_manager()->add_ui_from_string(ui_info);
847 //App::ui_manager()->get_accel_group()->unlock();
849 catch(const Glib::Error& ex)
851 synfig::error("building menus and toolbars failed: " + ex.what());
854 // Add default keyboard accelerators
855 #define ACCEL(path,accel) \
857 Gtk::AccelKey accel_key(accel,path); \
858 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
861 #define ACCEL2(accel) \
863 Gtk::AccelKey accel_key(accel); \
864 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
867 ACCEL("<Actions>//select-all-ducks","<Control>a");
868 ACCEL("<Actions>//unselect-all-layers","<Control>d");
869 ACCEL("<Actions>//render","F9");
870 ACCEL("<Actions>//preview","F11");
871 ACCEL("<Actions>//properties","F8");
872 ACCEL("<Actions>//options","F12");
873 ACCEL("<Actions>//import","<control>i");
874 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
875 ACCEL("<Actions>//toggle-grid-show","<Control>g");
876 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
877 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
878 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
879 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
880 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
881 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
882 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
883 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
885 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
886 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
888 ACCEL("<Actions>//quality-01","<Control>1");
889 ACCEL("<Actions>//quality-02","<Control>2");
890 ACCEL("<Actions>//quality-03","<Control>3");
891 ACCEL("<Actions>//quality-04","<Control>4");
892 ACCEL("<Actions>//quality-05","<Control>5");
893 ACCEL("<Actions>//quality-06","<Control>6");
894 ACCEL("<Actions>//quality-07","<Control>7");
895 ACCEL("<Actions>//quality-08","<Control>8");
896 ACCEL("<Actions>//quality-09","<Control>9");
897 ACCEL("<Actions>//quality-10","<Control>0");
898 ACCEL("<Actions>//undo","<Control>z");
899 ACCEL("<Actions>//redo","<Control>r");
900 ACCEL("<Actions>//action-layer_remove","Delete");
902 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
903 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
904 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
905 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
906 ACCEL("<Actions>//time-zoom-in","+");
907 ACCEL("<Actions>//time-zoom-out","_");
909 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
910 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
912 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
913 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
914 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
915 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
916 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
917 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
918 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
919 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
920 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
921 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
922 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
923 ACCEL("<Actions>//play", "<Control>p");
924 ACCEL("<Actions>//seek-begin","Home");
925 ACCEL("<Actions>//seek-end","End");
927 ACCEL("<Actions>//state-normal", "<Mod1>a");
928 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
929 ACCEL("<Actions>//state-scale", "<Mod1>d");
930 ACCEL("<Actions>//state-rotate", "<Mod1>s");
932 ACCEL("<Actions>//state-bline", "<Mod1>b");
933 ACCEL("<Actions>//state-circle", "<Mod1>c");
934 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
935 ACCEL("<Actions>//state-gradient", "<Mod1>g");
937 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
938 ACCEL("<Actions>//state-fill", "<Mod1>f");
939 ACCEL("<Actions>//state-zoom", "<Mod1>z");
940 ACCEL("<Actions>//state-polygon", "<Mod1>p");
942 ACCEL("<Actions>//state-draw", "<Mod1>w");
943 ACCEL("<Actions>//state-sketch", "<Mod1>k");
944 ACCEL("<Actions>//state-width", "<Mod1>t");
945 ACCEL("<Actions>//state-mirror", "<Mod1>m");
947 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
953 #define mkdir(x,y) mkdir(x)
956 /* === M E T H O D S ======================================================= */
958 App::App(int *argc, char ***argv):
959 Gtk::Main(argc,argv),
960 IconController(etl::dirname((*argv)[0]))
962 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
965 ui_interface_=new GlobalUIInterface();
969 // don't call thread_init() if threads are already initialized
970 // on some machines bonobo_init() initialized threads before we get here
971 if (!g_thread_supported())
974 distance_system=Distance::SYSTEM_UNITS;
976 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
979 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
983 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
989 if(!SYNFIG_CHECK_VERSION())
991 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
992 dialog_error_blocking("Synfig Studio",
993 "This copy of Synfig Studio was compiled against a\n"
994 "different version of libsynfig than what is currently\n"
995 "installed. Synfig Studio will now abort. Try downloading\n"
996 "the latest version from the Synfig website at\n"
997 "http://synfig.org/Download"
1001 Glib::set_application_name(_("Synfig Studio"));
1004 about_window.set_can_self_destruct(false);
1005 about_window.show();
1007 shutdown_in_progress=false;
1008 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1009 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1011 // Initialize the Synfig library
1012 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1015 get_ui_interface()->error(_("Failed to initialize synfig!"));
1019 // add the preferences to the settings
1020 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1024 studio_init_cb.task(_("Init UI Manager..."));
1025 App::ui_manager_=studio::UIManager::create();
1028 studio_init_cb.task(_("Init Dock Manager..."));
1029 dock_manager=new studio::DockManager();
1031 studio_init_cb.task(_("Init State Manager..."));
1032 state_manager=new StateManager();
1034 studio_init_cb.task(_("Init Toolbox..."));
1035 toolbox=new studio::Toolbox();
1037 studio_init_cb.task(_("Init Tool Options..."));
1038 dialog_tool_options=new studio::Dialog_ToolOptions();
1039 dock_manager->register_dockable(*dialog_tool_options);
1041 studio_init_cb.task(_("Init History..."));
1042 dock_history=new studio::Dock_History();
1043 dock_manager->register_dockable(*dock_history);
1045 studio_init_cb.task(_("Init Canvases..."));
1046 dock_canvases=new studio::Dock_Canvases();
1047 dock_manager->register_dockable(*dock_canvases);
1049 studio_init_cb.task(_("Init Keyframes..."));
1050 dock_keyframes=new studio::Dock_Keyframes();
1051 dock_manager->register_dockable(*dock_keyframes);
1053 studio_init_cb.task(_("Init Layers..."));
1054 dock_layers=new studio::Dock_Layers();
1055 dock_manager->register_dockable(*dock_layers);
1057 studio_init_cb.task(_("Init Params..."));
1058 dock_params=new studio::Dock_Params();
1059 dock_manager->register_dockable(*dock_params);
1061 studio_init_cb.task(_("Init MetaData..."));
1062 dock_meta_data=new studio::Dock_MetaData();
1063 dock_manager->register_dockable(*dock_meta_data);
1065 studio_init_cb.task(_("Init Children..."));
1066 dock_children=new studio::Dock_Children();
1067 dock_manager->register_dockable(*dock_children);
1069 studio_init_cb.task(_("Init Info..."));
1070 dock_info = new studio::Dock_Info();
1071 dock_manager->register_dockable(*dock_info);
1073 studio_init_cb.task(_("Init Navigator..."));
1074 dock_navigator = new studio::Dock_Navigator();
1075 dock_manager->register_dockable(*dock_navigator);
1077 studio_init_cb.task(_("Init Timetrack..."));
1078 dock_timetrack = new studio::Dock_Timetrack();
1079 dock_manager->register_dockable(*dock_timetrack);
1081 studio_init_cb.task(_("Init Curve Editor..."));
1082 dock_curves = new studio::Dock_Curves();
1083 dock_manager->register_dockable(*dock_curves);
1085 studio_init_cb.task(_("Init Layer Groups..."));
1086 dock_layer_groups = new studio::Dock_LayerGroups();
1087 dock_manager->register_dockable(*dock_layer_groups);
1090 studio_init_cb.task(_("Init Color Dialog..."));
1091 dialog_color=new studio::Dialog_Color();
1093 studio_init_cb.task(_("Init Gradient Dialog..."));
1094 dialog_gradient=new studio::Dialog_Gradient();
1096 studio_init_cb.task(_("Init DeviceTracker..."));
1097 device_tracker=new studio::DeviceTracker();
1099 studio_init_cb.task(_("Init Tools..."));
1100 state_manager->add_state(&state_normal);
1101 state_manager->add_state(&state_smooth_move);
1102 state_manager->add_state(&state_scale);
1103 state_manager->add_state(&state_rotate);
1105 state_manager->add_state(&state_bline);
1108 state_manager->add_state(&state_circle);
1109 state_manager->add_state(&state_rectangle);
1111 state_manager->add_state(&state_gradient);
1112 state_manager->add_state(&state_eyedrop);
1113 state_manager->add_state(&state_fill);
1115 state_manager->add_state(&state_zoom);
1117 // Enabled - it's useful to be able to work with polygons without tangent ducks getting in the way.
1118 // I know we can switch tangent ducks off, but why not allow this kind of layer as well?
1119 if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon);
1121 // Enabled for now. Let's see whether they're good enough yet.
1122 if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw);
1123 if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
1125 // Disabled by default - it doesn't work properly?
1126 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1128 studio_init_cb.task(_("Init ModPalette..."));
1129 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1131 studio_init_cb.task(_("Init ModMirror..."));
1132 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1135 studio_init_cb.task(_("Init Setup Dialog..."));
1136 dialog_setup=new studio::Dialog_Setup();
1138 studio_init_cb.task(_("Init Input Dialog..."));
1139 dialog_input=new Gtk::InputDialog();
1140 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1141 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1143 studio_init_cb.task(_("Init auto recovery..."));
1144 auto_recover=new AutoRecover();
1146 studio_init_cb.amount_complete(9250,10000);
1147 studio_init_cb.task(_("Loading Settings..."));
1149 studio_init_cb.task(_("Checking auto-recover..."));
1151 studio_init_cb.amount_complete(9900,10000);
1153 if(auto_recover->recovery_needed())
1155 about_window.hide();
1157 get_ui_interface()->yes_no(
1159 _("Synfig Studio seems to have crashed\n"
1160 "before you could save all your files.\n"
1161 "Would you like to re-open those files\n"
1162 "and recover your unsaved changes?")
1163 )==synfigapp::UIInterface::RESPONSE_YES
1166 if(!auto_recover->recover())
1168 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1171 get_ui_interface()->error(
1172 _("Synfig Studio has attempted to recover\n"
1173 "from a previous crash. The files that it has\n"
1174 "recovered are NOT YET SAVED. It would be a good\n"
1175 "idea to review them and save them now.")
1178 about_window.show();
1181 // Look for any files given on the command line,
1182 // and load them if found.
1183 for(;*argc>=1;(*argc)--)
1184 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1186 studio_init_cb.task(_("Loading files..."));
1187 about_window.hide();
1188 open((*argv)[*argc]);
1189 about_window.show();
1192 studio_init_cb.task(_("Done."));
1193 studio_init_cb.amount_complete(10000,10000);
1199 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1203 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1207 StateManager* App::get_state_manager() { return state_manager; }
1211 shutdown_in_progress=true;
1215 synfigapp::Main::settings().remove_domain("pref");
1217 selected_instance=0;
1219 // Unload all of the modules
1220 for(;!module_list_.empty();module_list_.pop_back());
1222 delete state_manager;
1226 delete auto_recover;
1230 // studio::App::iteration(false);
1234 // studio::App::iteration(false);
1236 // studio::App::iteration(false);
1238 delete dialog_setup;
1240 delete dialog_gradient;
1242 delete dialog_color;
1244 delete dialog_input;
1246 delete dock_manager;
1248 instance_list.clear();
1250 // studio::App::iteration(false);
1254 App::get_user_app_directory()
1256 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1260 App::get_config_file(const synfig::String& file)
1262 return Glib::build_filename(get_user_app_directory(),file);
1266 App::add_recent_file(const std::string &file_name)
1268 std::string filename(file_name);
1270 assert(!filename.empty());
1272 if(filename.empty())
1275 // Toss out any "hidden" files
1276 if(basename(filename)[0]=='.')
1279 // If we aren't an absolute path, turn ourselves into one
1280 if(!is_absolute_path(filename))
1281 filename=absolute_path(filename);
1283 list<string>::iterator iter;
1284 // Check to see if the file is already on the list.
1285 // If it is, then remove it from the list
1286 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1289 recent_files.erase(iter);
1294 // Push the filename to the front of the list
1295 recent_files.push_front(filename);
1297 // Clean out the files at the end of the list.
1298 while(recent_files.size()>(unsigned)get_max_recent_files())
1299 recent_files.pop_back();
1301 signal_recent_files_changed_();
1306 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1309 App::get_time_format()
1311 return _App_time_format;
1315 App::set_time_format(synfig::Time::Format x)
1322 App::save_settings()
1327 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1328 setlocale(LC_NUMERIC, "C");
1330 std::string filename=get_config_file("accelrc");
1331 Gtk::AccelMap::save(filename);
1334 std::string filename=get_config_file("recentfiles");
1336 std::ofstream file(filename.c_str());
1340 synfig::warning("Unable to save %s",filename.c_str());
1344 list<string>::reverse_iterator iter;
1346 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1350 std::string filename=get_config_file("settings");
1351 synfigapp::Main::settings().save_to_file(filename);
1352 setlocale(LC_NUMERIC,old_locale);
1356 synfig::warning("Caught exception when attempting to save settings.");
1361 App::load_settings()
1366 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1367 setlocale(LC_NUMERIC, "C");
1369 std::string filename=get_config_file("accelrc");
1370 Gtk::AccelMap::load(filename);
1373 std::string filename=get_config_file("recentfiles");
1375 std::ifstream file(filename.c_str());
1379 std::string recent_file;
1380 getline(file,recent_file);
1381 if(!recent_file.empty())
1382 add_recent_file(recent_file);
1385 std::string filename=get_config_file("settings");
1386 if(!synfigapp::Main::settings().load_from_file(filename))
1388 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1389 //if(!synfigapp::Main::settings().load_from_file(filename))
1391 gamma.set_gamma(1.0/2.2);
1392 reset_initial_window_configuration();
1395 setlocale(LC_NUMERIC,old_locale);
1399 synfig::warning("Caught exception when attempting to load settings.");
1404 App::reset_initial_window_configuration()
1406 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1407 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1408 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1409 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1410 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1411 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1412 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1413 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1414 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1415 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1416 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1417 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1418 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1419 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1423 App::shutdown_request(GdkEventAny*)
1427 //return !shutdown_in_progress;
1433 if(shutdown_in_progress)return;
1436 get_ui_interface()->task(_("Quit Request"));
1439 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1443 std::list<etl::handle<Instance> >::iterator iter;
1444 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1446 if(!(*iter)->safe_close())
1450 if((*iter)->synfigapp::Instance::get_action_count())
1452 handle<synfigapp::UIInterface> uim;
1453 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1455 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1456 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1458 case synfigapp::UIInterface::RESPONSE_NO:
1460 case synfigapp::UIInterface::RESPONSE_YES:
1463 case synfigapp::UIInterface::RESPONSE_CANCEL:
1472 if((*iter)->synfigapp::Instance::is_modified())
1474 handle<synfigapp::UIInterface> uim;
1475 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1477 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() );
1478 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1480 case synfigapp::UIInterface::RESPONSE_NO:
1482 case synfigapp::UIInterface::RESPONSE_YES:
1483 (*iter)->dialog_cvs_commit();
1485 case synfigapp::UIInterface::RESPONSE_CANCEL:
1494 // This next line causes things to crash for some reason
1498 shutdown_in_progress=true;
1500 instance_list.clear();
1502 while(studio::App::events_pending())studio::App::iteration(false);
1505 auto_recover->normal_shutdown();
1507 get_ui_interface()->task(_("Quit Request sent"));
1513 dialog_setup->refresh();
1514 dialog_setup->show();
1517 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1518 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1521 //#define USE_WIN32_FILE_DIALOGS 1
1524 #ifdef USE_WIN32_FILE_DIALOGS
1525 static OPENFILENAME ofn={};
1529 #include <gdk/gdkwin32.h>
1533 App::dialog_open_file(const std::string &title, std::string &filename)
1535 #ifdef USE_WIN32_FILE_DIALOGS
1536 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1538 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1539 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1540 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1542 ofn.lStructSize=sizeof(OPENFILENAME);
1543 ofn.hwndOwner = hWnd;
1544 ofn.hInstance = hInstance;
1545 ofn.lpstrFilter = szFilter;
1546 // ofn.lpstrCustomFilter=NULL;
1547 // ofn.nMaxCustFilter=0;
1548 // ofn.nFilterIndex=0;
1549 // ofn.lpstrFile=NULL;
1550 ofn.nMaxFile=MAX_PATH;
1551 // ofn.lpstrFileTitle=NULL;
1552 // ofn.lpstrInitialDir=NULL;
1553 // ofn.lpstrTitle=NULL;
1554 ofn.Flags=OFN_HIDEREADONLY;
1555 // ofn.nFileOffset=0;
1556 // ofn.nFileExtension=0;
1557 ofn.lpstrDefExt=TEXT("sif");
1558 // ofn.lCustData = 0l;
1560 // ofn.lpTemplateName=NULL;
1562 CHAR szFilename[MAX_PATH];
1564 strcpy(szFilename,filename.c_str());
1565 strcpy(szTitle,title.c_str());
1567 ofn.lpstrFile=szFilename;
1568 ofn.lpstrFileTitle=szTitle;
1570 if(GetOpenFileName(&ofn))
1572 filename=szFilename;
1578 synfig::String prev_path;
1579 if(!_preferences.get_value("curr_path",prev_path))
1581 prev_path = absolute_path(prev_path);
1583 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1584 dialog->set_current_folder(prev_path);
1585 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1586 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1587 if(!filename.empty())
1588 if (is_absolute_path(filename))
1589 dialog->set_filename(filename);
1591 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1592 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1593 filename=dialog->get_filename();
1605 GtkWidget *fileselection;
1606 fileselection = gtk_file_selection_new(title.c_str());
1609 if(basename(filename)==filename)
1611 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1614 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1616 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1618 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1619 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1621 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1622 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1624 gtk_widget_show(fileselection);
1632 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1633 _preferences.set_value("curr_path",dirname(filename));
1637 gtk_widget_destroy(fileselection);
1640 gtk_widget_destroy(fileselection);
1647 App::dialog_save_file(const std::string &title, std::string &filename)
1649 #if USE_WIN32_FILE_DIALOGS
1650 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1652 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1653 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1654 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1656 ofn.lStructSize=sizeof(OPENFILENAME);
1657 ofn.hwndOwner = hWnd;
1658 ofn.hInstance = hInstance;
1659 ofn.lpstrFilter = szFilter;
1660 // ofn.lpstrCustomFilter=NULL;
1661 // ofn.nMaxCustFilter=0;
1662 // ofn.nFilterIndex=0;
1663 // ofn.lpstrFile=NULL;
1664 ofn.nMaxFile=MAX_PATH;
1665 // ofn.lpstrFileTitle=NULL;
1666 // ofn.lpstrInitialDir=NULL;
1667 // ofn.lpstrTitle=NULL;
1668 ofn.Flags=OFN_OVERWRITEPROMPT;
1669 // ofn.nFileOffset=0;
1670 // ofn.nFileExtension=0;
1671 ofn.lpstrDefExt=TEXT("sif");
1672 // ofn.lCustData = 0l;
1674 // ofn.lpTemplateName=NULL;
1676 CHAR szFilename[MAX_PATH];
1678 strcpy(szFilename,filename.c_str());
1679 strcpy(szTitle,title.c_str());
1681 ofn.lpstrFile=szFilename;
1682 ofn.lpstrFileTitle=szTitle;
1684 if(GetSaveFileName(&ofn))
1686 filename=szFilename;
1687 _preferences.set_value("curr_path",dirname(filename));
1692 synfig::String prev_path;
1693 if(!_preferences.get_value("curr_path",prev_path))
1695 prev_path = absolute_path(prev_path);
1697 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1698 dialog->set_current_folder(prev_path);
1699 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1700 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1701 if(!filename.empty())
1703 std::string full_path;
1704 if (is_absolute_path(filename))
1705 full_path = filename;
1707 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1708 // select the file if it exists
1709 dialog->set_filename(full_path);
1711 // if the file doesn't exist, put its name into the filename box
1713 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1714 dialog->set_current_name(basename(filename));
1716 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1717 filename=dialog->get_filename();
1719 _preferences.set_value("curr_path",dirname(filename));
1724 // return dialog_open_file(title, filename);
1729 App::dialog_error_blocking(const std::string &title, const std::string &message)
1731 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1732 dialog.set_title(title);
1738 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1740 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
1741 dialog.set_title(title);
1747 App::dialog_yes_no(const std::string &title, const std::string &message)
1752 true // use_separator
1754 Gtk::Label label(message);
1757 dialog.get_vbox()->pack_start(label);
1758 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1759 dialog.add_button(Gtk::StockID("gtk-no"),0);
1761 return dialog.run();
1765 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1770 true // use_separator
1772 Gtk::Label label(message);
1775 dialog.get_vbox()->pack_start(label);
1776 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1777 dialog.add_button(Gtk::StockID("gtk-no"),0);
1778 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1780 return dialog.run();
1784 App::dialog_not_implemented()
1786 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1787 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
1792 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1797 true // use_separator
1799 Gtk::Label label(message);
1801 dialog.get_vbox()->pack_start(label);
1804 entry.set_text(text);
1806 entry.set_activates_default(true);
1807 dialog.get_vbox()->pack_start(entry);
1809 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1810 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1811 dialog.set_default_response(Gtk::RESPONSE_OK);
1812 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1815 if(dialog.run()!=Gtk::RESPONSE_OK)
1818 text=entry.get_text();
1827 App::open(std::string filename)
1829 return open_as(filename,filename);
1832 // this is called from autorecover.cpp:
1833 // App::open_as(get_shadow_file_name(filename),filename)
1834 // other than that, 'filename' and 'as' are the same
1836 App::open_as(std::string filename,std::string as)
1839 char long_name[1024];
1840 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1846 OneMoment one_moment;
1848 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1849 if(canvas && get_instance(canvas))
1851 get_instance(canvas)->find_canvas_view(canvas)->present();
1852 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1855 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1857 add_recent_file(as);
1859 handle<Instance> instance(Instance::create(canvas));
1862 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1866 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)")))
1867 instance->dialog_cvs_update();
1871 dialog_error_blocking(_("Error"), x);
1876 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1880 _preferences.set_value("curr_path",dirname(as));
1889 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1890 canvas->set_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
1892 String file_name(strprintf("%s%d.sifz", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
1894 canvas->rend_desc().set_frame_rate(24.0);
1895 canvas->rend_desc().set_time_start(0.0);
1896 canvas->rend_desc().set_time_end(00.0);
1897 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1898 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1899 canvas->rend_desc().set_tl(Vector(-4,2.25));
1900 canvas->rend_desc().set_br(Vector(4,-2.25));
1901 canvas->rend_desc().set_w(480);
1902 canvas->rend_desc().set_h(270);
1903 canvas->rend_desc().set_antialias(1);
1904 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1905 canvas->set_file_name(file_name);
1907 handle<Instance> instance = Instance::create(canvas);
1909 if (!getenv("SYNFIG_DISABLE_NEW_CANVAS_EDIT_PROPERTIES"))
1910 instance->find_canvas_view(canvas)->canvas_properties.present();
1916 string filename="*.sif";
1918 while(dialog_open_file("Open", filename))
1920 // If the filename still has wildcards, then we should
1921 // continue looking for the file we want
1922 if(find(filename.begin(),filename.end(),'*')!=filename.end())
1928 get_ui_interface()->error(_("Unable to open file"));
1933 App::set_selected_instance(etl::loose_handle<Instance> instance)
1935 /* if(get_selected_instance()==instance)
1937 selected_instance=instance;
1938 signal_instance_selected()(instance);
1944 selected_instance=instance;
1945 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
1949 instance->focus(instance->get_canvas());
1952 set_selected_canvas_view(0);
1954 signal_instance_selected()(instance);
1958 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
1960 selected_canvas_view=canvas_view;
1961 signal_canvas_view_focus()(selected_canvas_view);
1964 selected_instance=canvas_view->get_instance();
1965 signal_instance_selected()(canvas_view->get_instance());
1968 if(get_selected_canvas_view()==canvas_view)
1970 signal_canvas_view_focus()(selected_canvas_view);
1971 signal_instance_selected()(canvas_view->get_instance());
1974 selected_canvas_view=canvas_view;
1975 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
1976 set_selected_instance(canvas_view->get_instance());
1977 signal_canvas_view_focus()(selected_canvas_view);
1981 etl::loose_handle<Instance>
1982 App::get_instance(etl::handle<synfig::Canvas> canvas)
1984 if(!canvas) return 0;
1985 canvas=canvas->get_root();
1987 std::list<etl::handle<Instance> >::iterator iter;
1988 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
1990 if((*iter)->get_canvas()==canvas)
1999 (new class About())->show();
2005 if(selected_instance)
2006 selected_instance->undo();
2012 if(selected_instance)
2013 selected_instance->redo();
2017 studio::App::get_base_path()
2019 return app_base_path_;