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);
415 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
416 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
419 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
422 if(*iter && (*iter)->get_name()!="menus")
424 synfig::info("Removing action group "+(*iter)->get_name());
425 ui_manager->remove_action_group(*iter);
429 ui_manager->insert_action_group(group,0);
432 for(;!prev_groups.empty();prev_groups.pop_front())
434 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
435 ui_manager->insert_action_group(prev_groups.front(),1);
440 class Preferences : public synfigapp::Settings
443 virtual bool get_value(const synfig::String& key, synfig::String& value)const
447 value=strprintf("%f %f %f %f",
448 App::gamma.get_gamma_r(),
449 App::gamma.get_gamma_g(),
450 App::gamma.get_gamma_b(),
451 App::gamma.get_black_level()
455 if(key=="time_format")
457 value=strprintf("%i",App::get_time_format());
460 if(key=="file_history.size")
462 value=strprintf("%i",App::get_max_recent_files());
465 if(key=="use_colorspace_gamma")
467 value=strprintf("%i",(int)App::use_colorspace_gamma);
470 if(key=="distance_system")
472 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
475 if(key=="single_threaded")
477 value=strprintf("%i",(int)App::single_threaded);
480 if(key=="auto_recover_backup_interval")
482 value=strprintf("%i",App::auto_recover->get_timeout());
486 return synfigapp::Settings::get_value(key,value);
489 virtual bool set_value(const synfig::String& key,const synfig::String& value)
495 strscanf(value,"%f %f %f %f",
502 App::gamma.set_all(r,g,b,blk);
506 if(key=="time_format")
508 int i(atoi(value.c_str()));
509 App::set_time_format(static_cast<synfig::Time::Format>(i));
512 if(key=="auto_recover_backup_interval")
514 int i(atoi(value.c_str()));
515 App::auto_recover->set_timeout(i);
518 if(key=="file_history.size")
520 int i(atoi(value.c_str()));
521 App::set_max_recent_files(i);
524 if(key=="use_colorspace_gamma")
526 int i(atoi(value.c_str()));
527 App::use_colorspace_gamma=i;
530 if(key=="distance_system")
532 App::distance_system=Distance::ident_system(value);;
535 if(key=="single_threaded")
537 int i(atoi(value.c_str()));
538 App::single_threaded=i;
542 return synfigapp::Settings::set_value(key,value);
545 virtual KeyList get_key_list()const
547 KeyList ret(synfigapp::Settings::get_key_list());
548 ret.push_back("gamma");
549 ret.push_back("time_format");
550 ret.push_back("distance_system");
551 ret.push_back("file_history.size");
552 ret.push_back("use_colorspace_gamma");
553 ret.push_back("single_threaded");
554 ret.push_back("auto_recover_backup_interval");
559 static ::Preferences _preferences;
564 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
566 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
568 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
570 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
571 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
572 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
573 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
574 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
575 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
576 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
577 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
578 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
579 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
580 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
581 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
583 // Add the synfigapp actions...
584 synfigapp::Action::Book::iterator iter;
585 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
587 actions_action_group->add(Gtk::Action::create(
588 "action-"+iter->second.name,
589 get_action_stock_id(iter->second),
590 iter->second.local_name,iter->second.local_name
594 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
595 #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); }
596 #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); }
598 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
599 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
600 DEFINE_ACTION("open", Gtk::Stock::OPEN);
601 DEFINE_ACTION("save", Gtk::Stock::SAVE);
602 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
603 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
604 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
605 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
606 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
607 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
608 DEFINE_ACTION("import", _("Import"));
609 DEFINE_ACTION("render", _("Render"));
610 DEFINE_ACTION("preview", _("Preview"));
611 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
612 DEFINE_ACTION("sound", _("Sound File"));
613 DEFINE_ACTION("options", _("Options"));
614 DEFINE_ACTION("close", _("Close View"));
615 DEFINE_ACTION("close-document", _("Close Document"));
618 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
619 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
620 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
621 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
622 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
623 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
624 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
625 DEFINE_ACTION("properties", _("Properties"));
627 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
628 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
629 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
630 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
631 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
632 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
633 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
634 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
635 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
636 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
637 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
638 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
639 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
640 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
641 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
642 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
643 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
644 DEFINE_ACTION("play", _("Play"));
645 // DEFINE_ACTION("pause", _("Pause"));
646 DEFINE_ACTION("stop", _("Stop"));
647 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
648 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
649 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
650 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
651 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
652 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
653 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
654 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
655 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
656 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
657 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
658 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
659 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
660 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
661 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
662 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
663 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
664 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
665 DEFINE_ACTION("seek-end", _("Seek to End"));
667 DEFINE_ACTION("action-group_add", _("Add group"));
669 DEFINE_ACTION("canvas-new", _("New Canvas"));
671 DEFINE_ACTION("amount-inc", _("Increase Amount"));
672 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
677 // Set up synfigapp actions
679 synfigapp::Action::Book::iterator iter;
681 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
683 Gtk::StockID stock_id;
685 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
687 //Gtk::Image* image(manage(new Gtk::Image()));
688 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
689 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
690 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
691 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
692 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
693 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
694 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
695 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
696 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
697 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
699 actions_action_group->add(Gtk::Action::create(
700 "action-"+iter->second.name,
702 iter->second.local_name,iter->second.local_name
710 Glib::ustring ui_info =
712 " <popup name='menu-toolbox' action='menu-toolbox'>"
713 " <menu action='menu-file'>"
716 " <popup name='menu-main' action='menu-main'>"
717 " <menu action='menu-file'>"
718 " <menuitem action='save' />"
719 " <menuitem action='save-as' />"
720 " <menuitem action='revert' />"
721 " <separator name='bleh01'/>"
722 " <menuitem action='cvs-add' />"
723 " <menuitem action='cvs-update' />"
724 " <menuitem action='cvs-commit' />"
725 " <menuitem action='cvs-revert' />"
726 " <separator name='bleh02'/>"
727 " <menuitem action='import' />"
728 " <separator name='bleh03'/>"
729 " <menuitem action='render' />"
730 " <menuitem action='preview' />"
731 " <menuitem action='sound' />"
732 " <separator name='bleh04'/>"
733 " <menuitem action='options' />"
734 " <menuitem action='close' />"
735 " <menuitem action='close-document' />"
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 for(;*argc>=1;(*argc)--)
1190 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1192 studio_init_cb.task(_("Loading files..."));
1193 about_window.hide();
1194 open((*argv)[*argc]);
1195 about_window.show();
1198 studio_init_cb.task(_("Done."));
1199 studio_init_cb.amount_complete(10000,10000);
1205 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1209 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1213 StateManager* App::get_state_manager() { return state_manager; }
1217 shutdown_in_progress=true;
1221 synfigapp::Main::settings().remove_domain("pref");
1223 selected_instance=0;
1225 // Unload all of the modules
1226 for(;!module_list_.empty();module_list_.pop_back());
1228 delete state_manager;
1232 delete auto_recover;
1236 // studio::App::iteration(false);
1240 // studio::App::iteration(false);
1242 // studio::App::iteration(false);
1244 delete dialog_setup;
1246 delete dialog_gradient;
1248 delete dialog_color;
1250 delete dialog_input;
1252 delete dock_manager;
1254 instance_list.clear();
1256 // studio::App::iteration(false);
1260 App::get_user_app_directory()
1262 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1266 App::get_config_file(const synfig::String& file)
1268 return Glib::build_filename(get_user_app_directory(),file);
1272 App::add_recent_file(const std::string &file_name)
1274 std::string filename(file_name);
1276 assert(!filename.empty());
1278 if(filename.empty())
1281 // Toss out any "hidden" files
1282 if(basename(filename)[0]=='.')
1285 // If we aren't an absolute path, turn ourselves into one
1286 if(!is_absolute_path(filename))
1287 filename=absolute_path(filename);
1289 list<string>::iterator iter;
1290 // Check to see if the file is already on the list.
1291 // If it is, then remove it from the list
1292 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1295 recent_files.erase(iter);
1300 // Push the filename to the front of the list
1301 recent_files.push_front(filename);
1303 // Clean out the files at the end of the list.
1304 while(recent_files.size()>(unsigned)get_max_recent_files())
1305 recent_files.pop_back();
1307 signal_recent_files_changed_();
1312 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1315 App::get_time_format()
1317 return _App_time_format;
1321 App::set_time_format(synfig::Time::Format x)
1328 App::save_settings()
1333 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1334 setlocale(LC_NUMERIC, "C");
1336 std::string filename=get_config_file("accelrc");
1337 Gtk::AccelMap::save(filename);
1340 std::string filename=get_config_file("recentfiles");
1342 std::ofstream file(filename.c_str());
1346 synfig::warning("Unable to save %s",filename.c_str());
1350 list<string>::reverse_iterator iter;
1352 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1356 std::string filename=get_config_file("settings");
1357 synfigapp::Main::settings().save_to_file(filename);
1358 setlocale(LC_NUMERIC,old_locale);
1362 synfig::warning("Caught exception when attempting to save settings.");
1367 App::load_settings()
1372 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1373 setlocale(LC_NUMERIC, "C");
1375 std::string filename=get_config_file("accelrc");
1376 Gtk::AccelMap::load(filename);
1379 std::string filename=get_config_file("recentfiles");
1381 std::ifstream file(filename.c_str());
1385 std::string recent_file;
1386 getline(file,recent_file);
1387 if(!recent_file.empty())
1388 add_recent_file(recent_file);
1391 std::string filename=get_config_file("settings");
1392 if(!synfigapp::Main::settings().load_from_file(filename))
1394 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1395 //if(!synfigapp::Main::settings().load_from_file(filename))
1397 gamma.set_gamma(1.0/2.2);
1398 reset_initial_window_configuration();
1401 setlocale(LC_NUMERIC,old_locale);
1405 synfig::warning("Caught exception when attempting to load settings.");
1410 App::reset_initial_window_configuration()
1412 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1413 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1414 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1415 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1416 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1417 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1418 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1419 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1420 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1421 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1422 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1423 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1424 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1425 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1429 App::shutdown_request(GdkEventAny*)
1433 //return !shutdown_in_progress;
1439 if(shutdown_in_progress)return;
1442 get_ui_interface()->task(_("Quit Request"));
1445 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1449 std::list<etl::handle<Instance> >::iterator iter;
1450 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1452 if(!(*iter)->safe_close())
1456 if((*iter)->synfigapp::Instance::get_action_count())
1458 handle<synfigapp::UIInterface> uim;
1459 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1461 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1462 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1464 case synfigapp::UIInterface::RESPONSE_NO:
1466 case synfigapp::UIInterface::RESPONSE_YES:
1469 case synfigapp::UIInterface::RESPONSE_CANCEL:
1478 if((*iter)->synfigapp::Instance::is_modified())
1480 handle<synfigapp::UIInterface> uim;
1481 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1483 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() );
1484 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1486 case synfigapp::UIInterface::RESPONSE_NO:
1488 case synfigapp::UIInterface::RESPONSE_YES:
1489 (*iter)->dialog_cvs_commit();
1491 case synfigapp::UIInterface::RESPONSE_CANCEL:
1500 // This next line causes things to crash for some reason
1504 shutdown_in_progress=true;
1506 instance_list.clear();
1508 while(studio::App::events_pending())studio::App::iteration(false);
1511 auto_recover->normal_shutdown();
1513 get_ui_interface()->task(_("Quit Request sent"));
1519 dialog_setup->refresh();
1520 dialog_setup->show();
1523 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1524 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1527 //#define USE_WIN32_FILE_DIALOGS 1
1530 #ifdef USE_WIN32_FILE_DIALOGS
1531 static OPENFILENAME ofn={};
1535 #include <gdk/gdkwin32.h>
1539 App::dialog_open_file(const std::string &title, std::string &filename)
1541 #ifdef USE_WIN32_FILE_DIALOGS
1542 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1544 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1545 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1546 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1548 ofn.lStructSize=sizeof(OPENFILENAME);
1549 ofn.hwndOwner = hWnd;
1550 ofn.hInstance = hInstance;
1551 ofn.lpstrFilter = szFilter;
1552 // ofn.lpstrCustomFilter=NULL;
1553 // ofn.nMaxCustFilter=0;
1554 // ofn.nFilterIndex=0;
1555 // ofn.lpstrFile=NULL;
1556 ofn.nMaxFile=MAX_PATH;
1557 // ofn.lpstrFileTitle=NULL;
1558 // ofn.lpstrInitialDir=NULL;
1559 // ofn.lpstrTitle=NULL;
1560 ofn.Flags=OFN_HIDEREADONLY;
1561 // ofn.nFileOffset=0;
1562 // ofn.nFileExtension=0;
1563 ofn.lpstrDefExt=TEXT("sif");
1564 // ofn.lCustData = 0l;
1566 // ofn.lpTemplateName=NULL;
1568 CHAR szFilename[MAX_PATH];
1570 strcpy(szFilename,filename.c_str());
1571 strcpy(szTitle,title.c_str());
1573 ofn.lpstrFile=szFilename;
1574 ofn.lpstrFileTitle=szTitle;
1576 if(GetOpenFileName(&ofn))
1578 filename=szFilename;
1584 synfig::String prev_path;
1585 if(!_preferences.get_value("curr_path",prev_path))
1587 prev_path = absolute_path(prev_path);
1589 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1590 dialog->set_current_folder(prev_path);
1591 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1592 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1593 if(!filename.empty())
1594 if (is_absolute_path(filename))
1595 dialog->set_filename(filename);
1597 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1598 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1599 filename=dialog->get_filename();
1611 GtkWidget *fileselection;
1612 fileselection = gtk_file_selection_new(title.c_str());
1615 if(basename(filename)==filename)
1617 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1620 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1622 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1624 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1625 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1627 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1628 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1630 gtk_widget_show(fileselection);
1638 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1639 _preferences.set_value("curr_path",dirname(filename));
1643 gtk_widget_destroy(fileselection);
1646 gtk_widget_destroy(fileselection);
1653 App::dialog_save_file(const std::string &title, std::string &filename)
1655 #if USE_WIN32_FILE_DIALOGS
1656 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1658 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1659 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1660 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1662 ofn.lStructSize=sizeof(OPENFILENAME);
1663 ofn.hwndOwner = hWnd;
1664 ofn.hInstance = hInstance;
1665 ofn.lpstrFilter = szFilter;
1666 // ofn.lpstrCustomFilter=NULL;
1667 // ofn.nMaxCustFilter=0;
1668 // ofn.nFilterIndex=0;
1669 // ofn.lpstrFile=NULL;
1670 ofn.nMaxFile=MAX_PATH;
1671 // ofn.lpstrFileTitle=NULL;
1672 // ofn.lpstrInitialDir=NULL;
1673 // ofn.lpstrTitle=NULL;
1674 ofn.Flags=OFN_OVERWRITEPROMPT;
1675 // ofn.nFileOffset=0;
1676 // ofn.nFileExtension=0;
1677 ofn.lpstrDefExt=TEXT("sif");
1678 // ofn.lCustData = 0l;
1680 // ofn.lpTemplateName=NULL;
1682 CHAR szFilename[MAX_PATH];
1684 strcpy(szFilename,filename.c_str());
1685 strcpy(szTitle,title.c_str());
1687 ofn.lpstrFile=szFilename;
1688 ofn.lpstrFileTitle=szTitle;
1690 if(GetSaveFileName(&ofn))
1692 filename=szFilename;
1693 _preferences.set_value("curr_path",dirname(filename));
1698 synfig::String prev_path;
1699 if(!_preferences.get_value("curr_path",prev_path))
1701 prev_path = absolute_path(prev_path);
1703 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1704 dialog->set_current_folder(prev_path);
1705 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1706 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1707 if(!filename.empty())
1709 std::string full_path;
1710 if (is_absolute_path(filename))
1711 full_path = filename;
1713 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1714 // select the file if it exists
1715 dialog->set_filename(full_path);
1717 // if the file doesn't exist, put its name into the filename box
1719 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1720 dialog->set_current_name(basename(filename));
1722 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1723 filename=dialog->get_filename();
1725 _preferences.set_value("curr_path",dirname(filename));
1730 // return dialog_open_file(title, filename);
1735 App::dialog_error_blocking(const std::string &title, const std::string &message)
1737 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1738 dialog.set_title(title);
1744 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1746 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
1747 dialog.set_title(title);
1753 App::dialog_yes_no(const std::string &title, const std::string &message)
1758 true // use_separator
1760 Gtk::Label label(message);
1763 dialog.get_vbox()->pack_start(label);
1764 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1765 dialog.add_button(Gtk::StockID("gtk-no"),0);
1767 return dialog.run();
1771 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1776 true // use_separator
1778 Gtk::Label label(message);
1781 dialog.get_vbox()->pack_start(label);
1782 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1783 dialog.add_button(Gtk::StockID("gtk-no"),0);
1784 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1786 return dialog.run();
1790 App::dialog_not_implemented()
1792 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1793 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
1798 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1803 true // use_separator
1805 Gtk::Label label(message);
1807 dialog.get_vbox()->pack_start(label);
1810 entry.set_text(text);
1812 entry.set_activates_default(true);
1813 dialog.get_vbox()->pack_start(entry);
1815 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1816 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1817 dialog.set_default_response(Gtk::RESPONSE_OK);
1818 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1821 if(dialog.run()!=Gtk::RESPONSE_OK)
1824 text=entry.get_text();
1833 App::open(std::string filename)
1835 return open_as(filename,filename);
1838 // this is called from autorecover.cpp:
1839 // App::open_as(get_shadow_file_name(filename),filename)
1840 // other than that, 'filename' and 'as' are the same
1842 App::open_as(std::string filename,std::string as)
1845 char long_name[1024];
1846 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1852 OneMoment one_moment;
1854 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1855 if(canvas && get_instance(canvas))
1857 get_instance(canvas)->find_canvas_view(canvas)->present();
1858 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1861 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1863 add_recent_file(as);
1865 handle<Instance> instance(Instance::create(canvas));
1868 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1872 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)")))
1873 instance->dialog_cvs_update();
1877 dialog_error_blocking(_("Error"), x);
1882 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1886 _preferences.set_value("curr_path",dirname(as));
1895 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1896 canvas->set_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
1898 String file_name(strprintf("%s%d.sifz", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
1900 canvas->rend_desc().set_frame_rate(24.0);
1901 canvas->rend_desc().set_time_start(0.0);
1902 canvas->rend_desc().set_time_end(00.0);
1903 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1904 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1905 canvas->rend_desc().set_tl(Vector(-4,2.25));
1906 canvas->rend_desc().set_br(Vector(4,-2.25));
1907 canvas->rend_desc().set_w(480);
1908 canvas->rend_desc().set_h(270);
1909 canvas->rend_desc().set_antialias(1);
1910 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1911 canvas->set_file_name(file_name);
1913 handle<Instance> instance = Instance::create(canvas);
1915 if (!getenv("SYNFIG_DISABLE_NEW_CANVAS_EDIT_PROPERTIES"))
1916 instance->find_canvas_view(canvas)->canvas_properties.present();
1922 string filename="*.sif";
1924 while(dialog_open_file("Open", filename))
1926 // If the filename still has wildcards, then we should
1927 // continue looking for the file we want
1928 if(find(filename.begin(),filename.end(),'*')!=filename.end())
1934 get_ui_interface()->error(_("Unable to open file"));
1939 App::set_selected_instance(etl::loose_handle<Instance> instance)
1941 /* if(get_selected_instance()==instance)
1943 selected_instance=instance;
1944 signal_instance_selected()(instance);
1950 selected_instance=instance;
1951 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
1955 instance->focus(instance->get_canvas());
1958 set_selected_canvas_view(0);
1960 signal_instance_selected()(instance);
1964 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
1966 selected_canvas_view=canvas_view;
1967 signal_canvas_view_focus()(selected_canvas_view);
1970 selected_instance=canvas_view->get_instance();
1971 signal_instance_selected()(canvas_view->get_instance());
1974 if(get_selected_canvas_view()==canvas_view)
1976 signal_canvas_view_focus()(selected_canvas_view);
1977 signal_instance_selected()(canvas_view->get_instance());
1980 selected_canvas_view=canvas_view;
1981 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
1982 set_selected_instance(canvas_view->get_instance());
1983 signal_canvas_view_focus()(selected_canvas_view);
1987 etl::loose_handle<Instance>
1988 App::get_instance(etl::handle<synfig::Canvas> canvas)
1990 if(!canvas) return 0;
1991 canvas=canvas->get_root();
1993 std::list<etl::handle<Instance> >::iterator iter;
1994 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
1996 if((*iter)->get_canvas()==canvas)
2005 (new class About())->show();
2011 if(selected_instance)
2012 selected_instance->undo();
2018 if(selected_instance)
2019 selected_instance->redo();
2023 studio::App::get_base_path()
2025 return app_base_path_;