1 /* === S Y N F I G ========================================================= */
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
10 ** Copyright (c) 2008 Gerald Young
12 ** This package is free software; you can redistribute it and/or
13 ** modify it under the terms of the GNU General Public License as
14 ** published by the Free Software Foundation; either version 2 of
15 ** the License, or (at your option) any later version.
17 ** This package is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ** General Public License for more details.
23 /* ========================================================================= */
25 /* === H E A D E R S ======================================================= */
44 #ifdef HAVE_SYS_ERRNO_H
45 #include <sys/errno.h>
47 #include <gtkmm/fileselection.h>
48 #include <gtkmm/dialog.h>
49 #include <gtkmm/messagedialog.h>
50 #include <gtkmm/label.h>
51 #include <gtkmm/stock.h>
52 #include <gtkmm/stockitem.h>
53 #include <gtkmm/iconsource.h>
54 #include <gtkmm/inputdialog.h>
55 #include <gtkmm/accelmap.h>
56 #include <gtkmm/uimanager.h>
60 #include <gdkmm/general.h>
62 #include <synfig/loadcanvas.h>
63 #include <synfig/savecanvas.h>
69 #include "canvasview.h"
70 #include "dialog_setup.h"
71 #include "dialog_gradient.h"
72 #include "dialog_color.h"
75 #include "onemoment.h"
77 #include "dockmanager.h"
79 #include "state_eyedrop.h"
80 #include "state_normal.h"
81 #include "state_draw.h"
82 #include "state_fill.h"
83 #include "state_bline.h"
84 #include "state_polygon.h"
85 #include "state_sketch.h"
86 #include "state_gradient.h"
87 #include "state_circle.h"
88 #include "state_rectangle.h"
89 #include "state_smoothmove.h"
90 #include "state_scale.h"
91 #include "state_width.h"
92 #include "state_rotate.h"
93 #include "state_zoom.h"
95 #include "devicetracker.h"
96 #include "dialog_tooloptions.h"
97 #include "widget_enum.h"
99 #include "autorecover.h"
101 #include <synfigapp/settings.h>
102 #include "dock_history.h"
103 #include "dock_canvases.h"
104 #include "dock_keyframes.h"
105 #include "dock_layers.h"
106 #include "dock_params.h"
107 #include "dock_metadata.h"
108 #include "dock_children.h"
109 #include "dock_info.h"
110 #include "dock_navigator.h"
111 #include "dock_layergroups.h"
112 #include "dock_timetrack.h"
113 #include "dock_curves.h"
115 #include "mod_palette/mod_palette.h"
116 #include "mod_mirror/mod_mirror.h"
118 #include <sys/stat.h>
124 #include "statemanager.h"
130 #include <gtkmm/accelmap.h>
131 #include <gtkmm/filechooser.h>
132 #include <gtkmm/filechooserdialog.h>
138 /* === U S I N G =========================================================== */
142 using namespace synfig;
143 using namespace studio;
145 /* === M A C R O S ========================================================= */
147 #ifndef SYNFIG_USER_APP_DIR
149 #define SYNFIG_USER_APP_DIR "Library/Synfig"
150 #elif defined(_WIN32)
151 #define SYNFIG_USER_APP_DIR "Synfig"
153 #define SYNFIG_USER_APP_DIR ".synfig"
158 #define DPM2DPI(x) (float(x)/39.3700787402f)
159 #define DPI2DPM(x) (float(x)*39.3700787402f)
165 # define IMAGE_DIR "share\\pixmaps"
170 # define IMAGE_DIR "/usr/local/share/pixmaps"
174 # define IMAGE_EXT "tif"
177 #include <synfigapp/main.h>
179 /* === S I G N A L S ======================================================= */
181 static sigc::signal<void> signal_present_all_;
183 App::signal_present_all() { return signal_present_all_; }
185 static sigc::signal<void> signal_recent_files_changed_;
187 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
189 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
190 sigc::signal<void,etl::loose_handle<CanvasView> >&
191 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
193 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
194 sigc::signal<void,etl::handle<Instance> >&
195 App::signal_instance_selected() { return signal_instance_selected_; }
197 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
198 sigc::signal<void,etl::handle<Instance> >&
199 App::signal_instance_created() { return signal_instance_created_; }
201 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
202 sigc::signal<void,etl::handle<Instance> >&
203 App::signal_instance_deleted() { return signal_instance_deleted_; }
205 /* === G L O B A L S ======================================================= */
207 static std::list<std::string> recent_files;
208 const std::list<std::string>& App::get_recent_files() { return recent_files; }
210 static std::list<std::string> recent_files_window_size;
212 int App::Busy::count;
213 bool App::shutdown_in_progress;
215 synfig::Gamma App::gamma;
217 Glib::RefPtr<studio::UIManager> App::ui_manager_;
219 synfig::Distance::System App::distance_system;
221 studio::Dialog_Setup* App::dialog_setup;
223 etl::handle< studio::ModPalette > mod_palette_;
224 //studio::Dialog_Palette* App::dialog_palette;
226 std::list<etl::handle<Instance> > App::instance_list;
228 static etl::handle<synfigapp::UIInterface> ui_interface_;
229 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
231 etl::handle<Instance> App::selected_instance;
232 etl::handle<CanvasView> App::selected_canvas_view;
234 studio::About *studio::App::about=NULL;
236 studio::Toolbox *studio::App::toolbox=NULL;
238 studio::AutoRecover *studio::App::auto_recover=NULL;
240 studio::IPC *ipc=NULL;
242 studio::DockManager* studio::App::dock_manager=0;
244 studio::DeviceTracker* studio::App::device_tracker=0;
246 studio::Dialog_Gradient* studio::App::dialog_gradient;
248 studio::Dialog_Color* studio::App::dialog_color;
250 Gtk::InputDialog* studio::App::dialog_input;
252 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
254 studio::Dock_History* dock_history;
255 studio::Dock_Canvases* dock_canvases;
256 studio::Dock_Keyframes* dock_keyframes;
257 studio::Dock_Layers* dock_layers;
258 studio::Dock_Params* dock_params;
259 studio::Dock_MetaData* dock_meta_data;
260 studio::Dock_Children* dock_children;
261 studio::Dock_Info* dock_info;
262 studio::Dock_LayerGroups* dock_layer_groups;
263 studio::Dock_Navigator* dock_navigator;
264 studio::Dock_Timetrack* dock_timetrack;
265 studio::Dock_Curves* dock_curves;
267 std::list< etl::handle< studio::Module > > module_list_;
269 bool studio::App::use_colorspace_gamma=true;
270 #ifdef SINGLE_THREADED
271 bool studio::App::single_threaded=false;
273 bool studio::App::restrict_radius_ducks=false;
274 String studio::App::browser_command("firefox");
276 static int max_recent_files_=25;
277 int studio::App::get_max_recent_files() { return max_recent_files_; }
278 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
280 static synfig::String app_base_path_;
285 really_delete_widget(Gtk::Widget *widget)
287 // synfig::info("really delete %p", (void*)widget);
292 // nasty workaround - when we've finished with a popup menu, we want to delete it
293 // attaching to the signal_hide() signal gets us here before the action on the menu has run,
294 // so schedule the real delete to happen in 50ms, giving the action a chance to run
296 delete_widget(Gtk::Widget *widget)
298 // synfig::info("delete %p", (void*)widget);
299 Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
302 }; // END of namespace studio
303 studio::StateManager* state_manager;
308 class GlobalUIInterface : public synfigapp::UIInterface
312 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
317 true // use_separator
319 Gtk::Label label(message);
322 dialog.get_vbox()->pack_start(label);
323 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
324 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
326 dialog.set_default_response(dflt);
328 return (Response)dialog.run();
330 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
335 true // use_separator
337 Gtk::Label label(message);
340 dialog.get_vbox()->pack_start(label);
341 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
342 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
343 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
345 dialog.set_default_response(dflt);
347 return (Response)dialog.run();
349 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
354 true // use_separator
356 Gtk::Label label(message);
359 dialog.get_vbox()->pack_start(label);
360 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
361 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
363 dialog.set_default_response(dflt);
365 return (Response)dialog.run();
369 task(const std::string &task)
371 std::cerr<<task<<std::endl;
372 while(studio::App::events_pending())studio::App::iteration(false);
377 error(const std::string &err)
379 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
386 warning(const std::string &err)
388 std::cerr<<"warning: "<<err<<std::endl;
389 while(studio::App::events_pending())studio::App::iteration(false);
394 amount_complete(int /*current*/, int /*total*/)
396 while(studio::App::events_pending())studio::App::iteration(false);
401 /* === P R O C E D U R E S ================================================= */
405 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
407 action_group_list.push_back(action_group);
408 Gtk::UIManager::insert_action_group(action_group, pos);
412 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
414 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
415 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
416 if(*iter==action_group)
418 action_group_list.erase(iter);
419 Gtk::UIManager::remove_action_group(action_group);
422 synfig::error("Unable to find action group");
426 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
428 ui_manager->insert_action_group(group,0);
430 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
431 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
433 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
435 if(*iter && (*iter)->get_name()!="menus")
437 synfig::info("Removing action group "+(*iter)->get_name());
438 ui_manager->remove_action_group(*iter);
441 ui_manager->insert_action_group(group,0);
443 for(;!prev_groups.empty();prev_groups.pop_front())
445 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
446 ui_manager->insert_action_group(prev_groups.front(),1);
450 class Preferences : public synfigapp::Settings
453 virtual bool get_value(const synfig::String& key, synfig::String& value)const
457 value=strprintf("%f %f %f %f",
458 App::gamma.get_gamma_r(),
459 App::gamma.get_gamma_g(),
460 App::gamma.get_gamma_b(),
461 App::gamma.get_black_level()
465 if(key=="time_format")
467 value=strprintf("%i",App::get_time_format());
470 if(key=="file_history.size")
472 value=strprintf("%i",App::get_max_recent_files());
475 if(key=="use_colorspace_gamma")
477 value=strprintf("%i",(int)App::use_colorspace_gamma);
480 if(key=="distance_system")
482 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
485 #ifdef SINGLE_THREADED
486 if(key=="single_threaded")
488 value=strprintf("%i",(int)App::single_threaded);
492 if(key=="auto_recover_backup_interval")
494 value=strprintf("%i",App::auto_recover->get_timeout());
497 if(key=="restrict_radius_ducks")
499 value=strprintf("%i",(int)App::restrict_radius_ducks);
502 if(key=="browser_command")
504 value=App::browser_command;
508 return synfigapp::Settings::get_value(key,value);
511 virtual bool set_value(const synfig::String& key,const synfig::String& value)
517 strscanf(value,"%f %f %f %f",
524 App::gamma.set_all(r,g,b,blk);
528 if(key=="time_format")
530 int i(atoi(value.c_str()));
531 App::set_time_format(static_cast<synfig::Time::Format>(i));
534 if(key=="auto_recover_backup_interval")
536 int i(atoi(value.c_str()));
537 App::auto_recover->set_timeout(i);
540 if(key=="file_history.size")
542 int i(atoi(value.c_str()));
543 App::set_max_recent_files(i);
546 if(key=="use_colorspace_gamma")
548 int i(atoi(value.c_str()));
549 App::use_colorspace_gamma=i;
552 if(key=="distance_system")
554 App::distance_system=Distance::ident_system(value);;
557 #ifdef SINGLE_THREADED
558 if(key=="single_threaded")
560 int i(atoi(value.c_str()));
561 App::single_threaded=i;
565 if(key=="restrict_radius_ducks")
567 int i(atoi(value.c_str()));
568 App::restrict_radius_ducks=i;
571 if(key=="browser_command")
573 App::browser_command=value;
577 return synfigapp::Settings::set_value(key,value);
580 virtual KeyList get_key_list()const
582 KeyList ret(synfigapp::Settings::get_key_list());
583 ret.push_back("gamma");
584 ret.push_back("time_format");
585 ret.push_back("distance_system");
586 ret.push_back("file_history.size");
587 ret.push_back("use_colorspace_gamma");
588 #ifdef SINGLE_THREADED
589 ret.push_back("single_threaded");
591 ret.push_back("auto_recover_backup_interval");
592 ret.push_back("restrict_radius_ducks");
593 ret.push_back("browser_command");
598 static ::Preferences _preferences;
603 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
605 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
607 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
609 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
610 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
611 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
612 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
613 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
614 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
615 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
616 menus_action_group->add( Gtk::Action::create("menu-lowres-pixel", _("Low-Res Pixel Size")) );
617 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
618 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
619 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
620 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
621 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
623 // Add the synfigapp actions...
624 synfigapp::Action::Book::iterator iter;
625 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
627 actions_action_group->add(Gtk::Action::create(
628 "action-"+iter->second.name,
629 get_action_stock_id(iter->second),
630 iter->second.local_name,iter->second.local_name
634 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
635 #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); }
636 #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); }
638 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
639 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
640 DEFINE_ACTION("new", Gtk::Stock::NEW);
641 DEFINE_ACTION("open", Gtk::Stock::OPEN);
642 DEFINE_ACTION("save", Gtk::Stock::SAVE);
643 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
644 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
645 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
646 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
647 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
648 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
649 DEFINE_ACTION("import", _("Import"));
650 DEFINE_ACTION("render", _("Render"));
651 DEFINE_ACTION("preview", _("Preview"));
652 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
653 DEFINE_ACTION("sound", _("Sound File"));
654 DEFINE_ACTION("options", _("Options"));
655 DEFINE_ACTION("close", _("Close View"));
656 DEFINE_ACTION("close-document", _("Close Document"));
657 DEFINE_ACTION("quit", Gtk::Stock::QUIT);
660 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
661 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
662 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
663 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
664 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
665 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
666 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
667 DEFINE_ACTION("properties", _("Properties"));
669 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
670 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
671 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
672 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
673 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
674 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
675 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
676 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
677 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
678 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
679 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
680 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
681 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
682 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
683 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
684 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
685 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
686 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
687 DEFINE_ACTION(strprintf("lowres-pixel-%d", *iter), strprintf(_("Set Low-Res pixel size to %d"), *iter));
688 DEFINE_ACTION("play", _("Play"));
689 // DEFINE_ACTION("pause", _("Pause"));
690 DEFINE_ACTION("stop", _("Stop"));
691 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
692 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
693 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
694 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
695 DEFINE_ACTION("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size"));
696 DEFINE_ACTION("increase-low-res-pixel-size", _("Increase Low-Res Pixel Size"));
697 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
698 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
699 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
700 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
701 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
702 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
703 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
704 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
705 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
706 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
707 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
708 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
709 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
710 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
711 DEFINE_ACTION("seek-end", _("Seek to End"));
713 DEFINE_ACTION("action-group_add", _("Add group"));
715 DEFINE_ACTION("canvas-new", _("New Canvas"));
717 DEFINE_ACTION("amount-inc", _("Increase Amount"));
718 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
723 // Set up synfigapp actions
725 synfigapp::Action::Book::iterator iter;
727 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
729 Gtk::StockID stock_id;
731 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
733 //Gtk::Image* image(manage(new Gtk::Image()));
734 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
735 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
736 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
737 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
738 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
739 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
740 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
741 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
742 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
743 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
745 actions_action_group->add(Gtk::Action::create(
746 "action-"+iter->second.name,
748 iter->second.local_name,iter->second.local_name
756 Glib::ustring ui_info =
758 " <popup name='menu-toolbox' action='menu-toolbox'>"
759 " <menu action='menu-file'>"
762 " <popup name='menu-main' action='menu-main'>"
763 " <menu action='menu-file'>"
764 " <menuitem action='new' />"
765 " <menuitem action='open' />"
766 " <menuitem action='save' />"
767 " <menuitem action='save-as' />"
768 " <menuitem action='revert' />"
769 " <separator name='bleh01'/>"
770 " <menuitem action='cvs-add' />"
771 " <menuitem action='cvs-update' />"
772 " <menuitem action='cvs-commit' />"
773 " <menuitem action='cvs-revert' />"
774 " <separator name='bleh02'/>"
775 " <menuitem action='import' />"
776 " <separator name='bleh03'/>"
777 " <menuitem action='render' />"
778 " <menuitem action='preview' />"
779 " <menuitem action='sound' />"
780 " <separator name='bleh04'/>"
781 " <menuitem action='options' />"
782 " <menuitem action='close' />"
783 " <menuitem action='close-document' />"
784 " <menuitem action='quit' />"
786 " <menu action='menu-edit'>"
787 " <menuitem action='undo'/>"
788 " <menuitem action='redo'/>"
789 " <separator name='bleh05'/>"
790 " <menuitem action='cut'/>"
791 " <menuitem action='copy'/>"
792 " <menuitem action='paste'/>"
793 " <separator name='bleh06'/>"
794 " <menuitem action='select-all-ducks'/>"
795 " <menuitem action='unselect-all-layers'/>"
796 " <separator name='bleh07'/>"
797 " <menuitem action='properties'/>"
799 " <menu action='menu-view'>"
800 " <menu action='menu-duck-mask'>"
801 " <menuitem action='mask-position-ducks' />"
802 " <menuitem action='mask-vertex-ducks' />"
803 " <menuitem action='mask-tangent-ducks' />"
804 " <menuitem action='mask-radius-ducks' />"
805 " <menuitem action='mask-width-ducks' />"
806 " <menuitem action='mask-angle-ducks' />"
808 " <menu action='menu-preview-quality'>"
809 " <menuitem action='quality-00' />"
810 " <menuitem action='quality-01' />"
811 " <menuitem action='quality-02' />"
812 " <menuitem action='quality-03' />"
813 " <menuitem action='quality-04' />"
814 " <menuitem action='quality-05' />"
815 " <menuitem action='quality-06' />"
816 " <menuitem action='quality-07' />"
817 " <menuitem action='quality-08' />"
818 " <menuitem action='quality-09' />"
819 " <menuitem action='quality-10' />"
821 " <menu action='menu-lowres-pixel'>"
822 " <menuitem action='decrease-low-res-pixel-size'/>"
823 " <menuitem action='increase-low-res-pixel-size'/>"
824 " <separator name='pixel-size-separator'/>"
827 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
828 ui_info += strprintf(" <menuitem action='lowres-pixel-%d' />", *iter);
832 " <separator name='bleh08'/>"
833 " <menuitem action='play'/>"
834 //" <menuitem action='pause'/>"
835 " <menuitem action='stop'/>"
836 " <menuitem action='dialog-flipbook'/>"
837 " <separator name='bleh09'/>"
838 " <menuitem action='toggle-grid-show'/>"
839 " <menuitem action='toggle-grid-snap'/>"
840 " <menuitem action='toggle-guide-show'/>"
841 " <menuitem action='toggle-low-res'/>"
842 " <menuitem action='toggle-onion-skin'/>"
843 " <separator name='bleh10'/>"
844 " <menuitem action='canvas-zoom-in'/>"
845 " <menuitem action='canvas-zoom-out'/>"
846 " <menuitem action='canvas-zoom-fit'/>"
847 " <menuitem action='canvas-zoom-100'/>"
848 " <separator name='bleh11'/>"
849 " <menuitem action='time-zoom-in'/>"
850 " <menuitem action='time-zoom-out'/>"
851 " <separator name='bleh12'/>"
852 " <menuitem action='jump-next-keyframe'/>"
853 " <menuitem action='jump-prev-keyframe'/>"
854 " <menuitem action='seek-next-frame'/>"
855 " <menuitem action='seek-prev-frame'/>"
856 " <menuitem action='seek-next-second'/>"
857 " <menuitem action='seek-prev-second'/>"
858 " <menuitem action='seek-begin'/>"
859 " <menuitem action='seek-end'/>"
861 " <menu action='menu-canvas'>"
862 " <menuitem action='canvas-new'/>"
864 " <menu name='menu-state' action='menu-state'>"
866 " <menu action='menu-group'>"
867 " <menuitem action='action-group_add'/>"
869 " <menu action='menu-layer'>"
870 //" <menuitem action='cut'/>"
871 //" <menuitem action='copy'/>"
872 //" <menuitem action='paste'/>"
873 //" <separator name='bleh06'/>"
874 " <menu action='menu-layer-new'></menu>"
875 " <menuitem action='amount-inc'/>"
876 " <menuitem action='amount-dec'/>"
878 " <menu action='menu-keyframe'>"
879 " <menuitem action='keyframe-properties'/>"
886 " <menubar name='MenuBar'>"
887 " <menu action='MenuFile'>"
888 " <menuitem action='New'/>"
889 " <menuitem action='Open'/>"
891 " <menuitem action='Quit'/>"
893 " <menu action='MenuEdit'>"
894 " <menuitem action='Cut'/>"
895 " <menuitem action='Copy'/>"
896 " <menuitem action='Paste'/>"
899 " <toolbar name='ToolBar'>"
900 " <toolitem action='Open'/>"
901 " <toolitem action='Quit'/>"
907 actions_action_group->set_sensitive(false);
908 App::ui_manager()->set_add_tearoffs(true);
909 App::ui_manager()->insert_action_group(menus_action_group,1);
910 App::ui_manager()->insert_action_group(actions_action_group,1);
911 App::ui_manager()->add_ui_from_string(ui_info);
913 //App::ui_manager()->get_accel_group()->unlock();
915 catch(const Glib::Error& ex)
917 synfig::error("building menus and toolbars failed: " + ex.what());
920 // Add default keyboard accelerators
921 #define ACCEL(path,accel) \
923 Gtk::AccelKey accel_key(accel,path); \
924 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
927 #define ACCEL2(accel) \
929 Gtk::AccelKey accel_key(accel); \
930 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
933 ACCEL("<Actions>//select-all-ducks","<Control>a");
934 ACCEL("<Actions>//unselect-all-layers","<Control>d");
935 ACCEL("<Actions>//render","F9");
936 ACCEL("<Actions>//preview","F11");
937 ACCEL("<Actions>//properties","F8");
938 ACCEL("<Actions>//options","F12");
939 ACCEL("<Actions>//import","<control>i");
940 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
941 ACCEL("<Actions>//toggle-grid-show","<Control>g");
942 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
943 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
944 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
945 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
946 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
947 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
948 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
949 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
951 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
952 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
954 ACCEL("<Actions>//quality-01","<Control>1");
955 ACCEL("<Actions>//quality-02","<Control>2");
956 ACCEL("<Actions>//quality-03","<Control>3");
957 ACCEL("<Actions>//quality-04","<Control>4");
958 ACCEL("<Actions>//quality-05","<Control>5");
959 ACCEL("<Actions>//quality-06","<Control>6");
960 ACCEL("<Actions>//quality-07","<Control>7");
961 ACCEL("<Actions>//quality-08","<Control>8");
962 ACCEL("<Actions>//quality-09","<Control>9");
963 ACCEL("<Actions>//quality-10","<Control>0");
964 ACCEL("<Actions>//undo","<Control>z");
965 ACCEL("<Actions>//redo","<Control>r");
966 ACCEL("<Actions>//action-layer_remove","Delete");
968 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
969 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
970 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
971 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
972 ACCEL("<Actions>//time-zoom-in","+");
973 ACCEL("<Actions>//time-zoom-out","_");
975 ACCEL2(Gtk::AccelKey('(',Gdk::CONTROL_MASK,"<Actions>//decrease-low-res-pixel-size"));
976 ACCEL2(Gtk::AccelKey(')',Gdk::CONTROL_MASK,"<Actions>//increase-low-res-pixel-size"));
978 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
979 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
981 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
982 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
983 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
984 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
985 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
986 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
987 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
988 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
989 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
990 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
991 ACCEL2(Gtk::AccelKey('o',Gdk::MOD1_MASK,"<Actions>//toggle-onion-skin"));
992 ACCEL("<Actions>//play", "<Control>p");
993 ACCEL("<Actions>//seek-begin","Home");
994 ACCEL("<Actions>//seek-end","End");
996 ACCEL("<Actions>//state-normal", "<Mod1>a");
997 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
998 ACCEL("<Actions>//state-scale", "<Mod1>d");
999 ACCEL("<Actions>//state-rotate", "<Mod1>s");
1001 ACCEL("<Actions>//state-bline", "<Mod1>b");
1002 ACCEL("<Actions>//state-circle", "<Mod1>c");
1003 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
1004 ACCEL("<Actions>//state-gradient", "<Mod1>g");
1006 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
1007 ACCEL("<Actions>//state-fill", "<Mod1>f");
1008 ACCEL("<Actions>//state-zoom", "<Mod1>z");
1009 ACCEL("<Actions>//state-polygon", "<Mod1>p");
1011 ACCEL("<Actions>//state-draw", "<Mod1>w");
1012 ACCEL("<Actions>//state-sketch", "<Mod1>k");
1013 ACCEL("<Actions>//state-width", "<Mod1>t");
1014 ACCEL("<Actions>//state-mirror", "<Mod1>m");
1016 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1022 #define mkdir(x,y) mkdir(x)
1025 /* === M E T H O D S ======================================================= */
1027 App::App(int *argc, char ***argv):
1028 Gtk::Main(argc,argv),
1029 IconController(etl::dirname((*argv)[0]))
1031 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1034 ui_interface_=new GlobalUIInterface();
1038 // don't call thread_init() if threads are already initialized
1039 // on some machines bonobo_init() initialized threads before we get here
1040 if (!g_thread_supported())
1041 Glib::thread_init();
1043 distance_system=Distance::SYSTEM_UNITS;
1045 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1048 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1052 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1058 if(!SYNFIG_CHECK_VERSION())
1060 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1061 dialog_error_blocking("Synfig Studio",
1062 "This copy of Synfig Studio was compiled against a\n"
1063 "different version of libsynfig than what is currently\n"
1064 "installed. Synfig Studio will now abort. Try downloading\n"
1065 "the latest version from the Synfig website at\n"
1066 "http://synfig.org/Download"
1070 Glib::set_application_name(_("Synfig Studio"));
1072 Splash splash_screen;
1073 splash_screen.set_can_self_destruct(false);
1074 splash_screen.show();
1076 shutdown_in_progress=false;
1077 SuperCallback synfig_init_cb(splash_screen.get_callback(),0,9000,10000);
1078 SuperCallback studio_init_cb(splash_screen.get_callback(),9000,10000,10000);
1080 // Initialize the Synfig library
1081 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1084 get_ui_interface()->error(_("Failed to initialize synfig!"));
1088 // add the preferences to the settings
1089 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1093 studio_init_cb.task(_("Init UI Manager..."));
1094 App::ui_manager_=studio::UIManager::create();
1097 studio_init_cb.task(_("Init Dock Manager..."));
1098 dock_manager=new studio::DockManager();
1100 studio_init_cb.task(_("Init State Manager..."));
1101 state_manager=new StateManager();
1103 studio_init_cb.task(_("Init Toolbox..."));
1104 toolbox=new studio::Toolbox();
1106 studio_init_cb.task(_("Init About Dialog..."));
1107 about=new studio::About();
1109 studio_init_cb.task(_("Init Tool Options..."));
1110 dialog_tool_options=new studio::Dialog_ToolOptions();
1111 dock_manager->register_dockable(*dialog_tool_options);
1113 studio_init_cb.task(_("Init History..."));
1114 dock_history=new studio::Dock_History();
1115 dock_manager->register_dockable(*dock_history);
1117 studio_init_cb.task(_("Init Canvases..."));
1118 dock_canvases=new studio::Dock_Canvases();
1119 dock_manager->register_dockable(*dock_canvases);
1121 studio_init_cb.task(_("Init Keyframes..."));
1122 dock_keyframes=new studio::Dock_Keyframes();
1123 dock_manager->register_dockable(*dock_keyframes);
1125 studio_init_cb.task(_("Init Layers..."));
1126 dock_layers=new studio::Dock_Layers();
1127 dock_manager->register_dockable(*dock_layers);
1129 studio_init_cb.task(_("Init Params..."));
1130 dock_params=new studio::Dock_Params();
1131 dock_manager->register_dockable(*dock_params);
1133 studio_init_cb.task(_("Init MetaData..."));
1134 dock_meta_data=new studio::Dock_MetaData();
1135 dock_manager->register_dockable(*dock_meta_data);
1137 studio_init_cb.task(_("Init Children..."));
1138 dock_children=new studio::Dock_Children();
1139 dock_manager->register_dockable(*dock_children);
1141 studio_init_cb.task(_("Init Info..."));
1142 dock_info = new studio::Dock_Info();
1143 dock_manager->register_dockable(*dock_info);
1145 studio_init_cb.task(_("Init Navigator..."));
1146 dock_navigator = new studio::Dock_Navigator();
1147 dock_manager->register_dockable(*dock_navigator);
1149 studio_init_cb.task(_("Init Timetrack..."));
1150 dock_timetrack = new studio::Dock_Timetrack();
1151 dock_manager->register_dockable(*dock_timetrack);
1153 studio_init_cb.task(_("Init Curve Editor..."));
1154 dock_curves = new studio::Dock_Curves();
1155 dock_manager->register_dockable(*dock_curves);
1157 studio_init_cb.task(_("Init Layer Groups..."));
1158 dock_layer_groups = new studio::Dock_LayerGroups();
1159 dock_manager->register_dockable(*dock_layer_groups);
1162 studio_init_cb.task(_("Init Color Dialog..."));
1163 dialog_color=new studio::Dialog_Color();
1165 studio_init_cb.task(_("Init Gradient Dialog..."));
1166 dialog_gradient=new studio::Dialog_Gradient();
1168 studio_init_cb.task(_("Init DeviceTracker..."));
1169 device_tracker=new studio::DeviceTracker();
1171 studio_init_cb.task(_("Init Tools..."));
1174 state_manager->add_state(&state_normal);
1175 state_manager->add_state(&state_smooth_move);
1176 state_manager->add_state(&state_scale);
1177 state_manager->add_state(&state_rotate);
1178 studio_init_cb.task(_("Init ModMirror...")); module_list_.push_back(new ModMirror()); module_list_.back()->start();
1181 state_manager->add_state(&state_bline);
1182 state_manager->add_state(&state_circle);
1183 state_manager->add_state(&state_rectangle);
1184 state_manager->add_state(&state_gradient);
1185 if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks
1188 if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw); // Enabled for now. Let's see whether they're good enough yet.
1189 if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
1190 state_manager->add_state(&state_fill);
1191 state_manager->add_state(&state_eyedrop);
1192 state_manager->add_state(&state_zoom);
1194 // Disabled by default - it doesn't work properly?
1195 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1197 studio_init_cb.task(_("Init ModPalette..."));
1198 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1200 studio_init_cb.task(_("Init Setup Dialog..."));
1201 dialog_setup=new studio::Dialog_Setup();
1203 studio_init_cb.task(_("Init Input Dialog..."));
1204 dialog_input=new Gtk::InputDialog();
1205 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1206 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1208 studio_init_cb.task(_("Init auto recovery..."));
1209 auto_recover=new AutoRecover();
1211 studio_init_cb.amount_complete(9250,10000);
1212 studio_init_cb.task(_("Loading Settings..."));
1214 studio_init_cb.task(_("Checking auto-recover..."));
1216 studio_init_cb.amount_complete(9900,10000);
1218 bool opened_any = false;
1219 if(auto_recover->recovery_needed())
1221 splash_screen.hide();
1222 if (get_ui_interface()->yes_no(_("Auto Recovery"),
1223 _("Synfig Studio seems to have crashed\n"
1224 "before you could save all your files.\n"
1225 "Would you like to re-open those files\n"
1226 "and recover your unsaved changes?")) ==
1227 synfigapp::UIInterface::RESPONSE_YES)
1229 int number_recovered;
1230 if(!auto_recover->recover(number_recovered))
1231 if (number_recovered)
1232 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1234 get_ui_interface()->error(_("Unable to recover from previous crash"));
1236 get_ui_interface()->error(
1237 _("Synfig Studio has attempted to recover\n"
1238 "from a previous crash. The files that it has\n"
1239 "recovered are NOT YET SAVED. It would be a good\n"
1240 "idea to review them and save them now."));
1242 if (number_recovered)
1245 splash_screen.show();
1248 // Look for any files given on the command line,
1249 // and load them if found.
1250 for(;*argc>=1;(*argc)--)
1251 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1253 studio_init_cb.task(_("Loading files..."));
1254 splash_screen.hide();
1255 open((*argv)[*argc]);
1257 splash_screen.show();
1260 // if no file was specified to be opened, create a new document to help new users get started more easily
1261 if (!opened_any && !getenv("SYNFIG_DISABLE_AUTOMATIC_DOCUMENT_CREATION"))
1264 studio_init_cb.task(_("Done."));
1265 studio_init_cb.amount_complete(10000,10000);
1271 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1275 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1279 StateManager* App::get_state_manager() { return state_manager; }
1283 shutdown_in_progress=true;
1287 synfigapp::Main::settings().remove_domain("pref");
1289 selected_instance=0;
1291 // Unload all of the modules
1292 for(;!module_list_.empty();module_list_.pop_back())
1295 delete state_manager;
1299 delete auto_recover;
1305 // studio::App::iteration(false);
1309 // studio::App::iteration(false);
1311 // studio::App::iteration(false);
1313 delete dialog_setup;
1315 delete dialog_gradient;
1317 delete dialog_color;
1319 delete dialog_input;
1321 delete dock_manager;
1323 instance_list.clear();
1325 // studio::App::iteration(false);
1329 App::get_user_app_directory()
1331 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1335 App::get_config_file(const synfig::String& file)
1337 return Glib::build_filename(get_user_app_directory(),file);
1340 #define SCALE_FACTOR (1280)
1341 //! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size
1343 App::set_recent_file_window_size(etl::handle<Instance> instance)
1345 int screen_w(Gdk::screen_width());
1346 int screen_h(Gdk::screen_height());
1348 const std::string &canvas_window_size = *recent_files_window_size.begin();
1350 if(canvas_window_size.empty())
1353 synfig::String::size_type current=0;
1354 bool seen_root(false), shown_non_root(false);
1356 while(current != synfig::String::npos)
1358 // find end of first field (canvas) or return
1359 synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
1360 if(separator == synfig::String::npos) break;
1363 synfig::Canvas::Handle canvas;
1365 canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current));
1367 catch(Exception::IDNotFound) {
1368 // can't find the canvas; skip to the next canvas or return
1369 separator = canvas_window_size.find_first_of('\t', current);
1370 if(separator == synfig::String::npos) return;
1371 current = separator+1;
1375 if (canvas->is_root())
1378 shown_non_root = true;
1380 // check that we have the tab character the ends this canvas' data or return
1381 current = separator+1;
1382 separator = canvas_window_size.find_first_of('\t', current);
1383 if(separator == synfig::String::npos) return;
1386 if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
1388 current = separator+1;
1392 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
1393 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
1394 x=x*screen_w/SCALE_FACTOR;
1395 y=y*screen_h/SCALE_FACTOR;
1396 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
1397 x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
1398 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
1399 y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
1401 if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
1402 if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
1404 CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
1405 canvasview->move(x,y);
1406 canvasview->resize(w*screen_w/SCALE_FACTOR,h*screen_h/SCALE_FACTOR);
1407 canvasview->present();
1409 current = separator+1;
1412 if (shown_non_root && !seen_root)
1413 instance->find_canvas_view(instance->get_canvas())->hide();
1417 App::add_recent_file(const etl::handle<Instance> instance)
1419 int screen_w(Gdk::screen_width());
1420 int screen_h(Gdk::screen_height());
1422 std::string canvas_window_size;
1424 const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
1425 Instance::CanvasViewList::const_iterator iter;
1427 for(iter=cview_list.begin();iter!=cview_list.end();iter++)
1429 if( !((*iter)->is_visible()) )
1432 etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
1433 int x_pos, y_pos, x_size, y_size;
1434 (*iter)->get_position(x_pos,y_pos);
1435 (*iter)->get_size(x_size,y_size);
1437 canvas_window_size += strprintf("%s %d %d %d %d\t",
1438 canvas->get_relative_id(canvas->get_root()).c_str(),
1439 x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h,
1440 x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
1443 add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
1448 App::add_recent_file(const std::string &file_name, const std::string &window_size)
1450 std::string filename(file_name);
1452 assert(!filename.empty());
1454 if(filename.empty())
1457 // Toss out any "hidden" files
1458 if(basename(filename)[0]=='.')
1461 // If we aren't an absolute path, turn ourselves into one
1462 if(!is_absolute_path(filename))
1463 filename=absolute_path(filename);
1465 std::string old_window_size;
1467 list<string>::iterator iter;
1468 list<string>::iterator iter_wsize;
1469 // Check to see if the file is already on the list.
1470 // If it is, then remove it from the list
1471 for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
1474 recent_files.erase(iter);
1475 old_window_size = *iter_wsize;
1476 recent_files_window_size.erase(iter_wsize);
1481 // Push the filename to the front of the list
1482 recent_files.push_front(filename);
1483 if(window_size.empty())
1484 recent_files_window_size.push_front(old_window_size);
1486 recent_files_window_size.push_front(window_size);
1488 // Clean out the files at the end of the list.
1489 while(recent_files.size()>(unsigned)get_max_recent_files())
1491 recent_files.pop_back();
1492 recent_files_window_size.pop_back();
1495 signal_recent_files_changed_();
1500 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1503 App::get_time_format()
1505 return _App_time_format;
1509 App::set_time_format(synfig::Time::Format x)
1516 App::save_settings()
1521 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1522 setlocale(LC_NUMERIC, "C");
1524 std::string filename=get_config_file("accelrc");
1525 Gtk::AccelMap::save(filename);
1528 std::string filename=get_config_file("recentfiles");
1530 std::ofstream file(filename.c_str());
1534 synfig::warning("Unable to save %s",filename.c_str());
1538 list<string>::reverse_iterator iter;
1540 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1544 std::string filename=get_config_file("recentfiles")+std::string("_window_size");
1546 std::ofstream file(filename.c_str());
1550 synfig::warning("Unable to save %s",filename.c_str());
1554 list<string>::reverse_iterator iter;
1556 for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
1560 std::string filename=get_config_file("settings");
1561 synfigapp::Main::settings().save_to_file(filename);
1562 setlocale(LC_NUMERIC,old_locale);
1566 synfig::warning("Caught exception when attempting to save settings.");
1571 App::load_settings()
1576 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1577 setlocale(LC_NUMERIC, "C");
1579 std::string filename=get_config_file("accelrc");
1580 Gtk::AccelMap::load(filename);
1583 bool window_size_broken = false;
1585 std::string filename=get_config_file("recentfiles");
1586 std::string filename_window_size=filename+std::string("_window_size");
1588 std::ifstream file(filename.c_str());
1589 std::ifstream file_window_size(filename_window_size.c_str());
1591 if(!file_window_size)
1592 window_size_broken = true;
1596 std::string recent_file;
1597 std::string recent_file_window_size;
1598 getline(file,recent_file);
1599 if(!window_size_broken)
1600 getline(file_window_size,recent_file_window_size);
1601 if(!recent_file.empty())
1603 if(!window_size_broken && !file_window_size)
1604 window_size_broken = true;
1605 if(!window_size_broken)
1606 add_recent_file(recent_file,recent_file_window_size);
1608 add_recent_file(recent_file);
1611 if(!window_size_broken && file_window_size)
1612 window_size_broken = true;
1614 if(window_size_broken)
1616 recent_files_window_size.clear();
1617 recent_files_window_size.resize(recent_files.size());
1620 std::string filename=get_config_file("settings");
1621 if(!synfigapp::Main::settings().load_from_file(filename))
1623 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1624 //if(!synfigapp::Main::settings().load_from_file(filename))
1626 gamma.set_gamma(1.0/2.2);
1627 reset_initial_window_configuration();
1630 setlocale(LC_NUMERIC,old_locale);
1634 synfig::warning("Caught exception when attempting to load settings.");
1639 App::reset_initial_window_configuration()
1641 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1642 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1643 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1644 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1645 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1646 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1647 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1648 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1649 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1650 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1651 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1652 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1653 #ifdef SINGLE_THREADED
1654 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1656 synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
1657 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1661 App::shutdown_request(GdkEventAny*)
1665 //return !shutdown_in_progress;
1671 if(shutdown_in_progress)return;
1674 get_ui_interface()->task(_("Quit Request"));
1677 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1681 std::list<etl::handle<Instance> >::iterator iter;
1682 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1684 if(!(*iter)->safe_close())
1688 if((*iter)->synfigapp::Instance::get_action_count())
1690 handle<synfigapp::UIInterface> uim;
1691 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1693 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1694 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1696 case synfigapp::UIInterface::RESPONSE_NO:
1698 case synfigapp::UIInterface::RESPONSE_YES:
1701 case synfigapp::UIInterface::RESPONSE_CANCEL:
1710 if((*iter)->synfigapp::Instance::is_modified())
1712 handle<synfigapp::UIInterface> uim;
1713 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1715 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() );
1716 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1718 case synfigapp::UIInterface::RESPONSE_NO:
1720 case synfigapp::UIInterface::RESPONSE_YES:
1721 (*iter)->dialog_cvs_commit();
1723 case synfigapp::UIInterface::RESPONSE_CANCEL:
1732 // This next line causes things to crash for some reason
1736 shutdown_in_progress=true;
1738 instance_list.clear();
1740 while(studio::App::events_pending())studio::App::iteration(false);
1743 auto_recover->normal_shutdown();
1745 get_ui_interface()->task(_("Quit Request sent"));
1751 dialog_setup->refresh();
1752 dialog_setup->show();
1755 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1756 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1759 //#define USE_WIN32_FILE_DIALOGS 1
1762 #ifdef USE_WIN32_FILE_DIALOGS
1763 static OPENFILENAME ofn={};
1767 #include <gdk/gdkwin32.h>
1771 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1773 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1775 #ifdef USE_WIN32_FILE_DIALOGS
1776 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1778 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1779 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1780 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1782 ofn.lStructSize=sizeof(OPENFILENAME);
1783 ofn.hwndOwner = hWnd;
1784 ofn.hInstance = hInstance;
1785 ofn.lpstrFilter = szFilter;
1786 // ofn.lpstrCustomFilter=NULL;
1787 // ofn.nMaxCustFilter=0;
1788 // ofn.nFilterIndex=0;
1789 // ofn.lpstrFile=NULL;
1790 ofn.nMaxFile=MAX_PATH;
1791 // ofn.lpstrFileTitle=NULL;
1792 // ofn.lpstrInitialDir=NULL;
1793 // ofn.lpstrTitle=NULL;
1794 ofn.Flags=OFN_HIDEREADONLY;
1795 // ofn.nFileOffset=0;
1796 // ofn.nFileExtension=0;
1797 ofn.lpstrDefExt=TEXT("sif");
1798 // ofn.lCustData = 0l;
1800 // ofn.lpTemplateName=NULL;
1802 CHAR szFilename[MAX_PATH];
1804 strcpy(szFilename,filename.c_str());
1805 strcpy(szTitle,title.c_str());
1807 ofn.lpstrFile=szFilename;
1808 ofn.lpstrFileTitle=szTitle;
1810 if(GetOpenFileName(&ofn))
1812 filename=szFilename;
1818 synfig::String prev_path;
1820 if(!_preferences.get_value(preference, prev_path))
1823 prev_path = absolute_path(prev_path);
1825 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1827 dialog->set_current_folder(prev_path);
1828 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1829 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1831 if (filename.empty())
1832 dialog->set_filename(prev_path);
1833 else if (is_absolute_path(filename))
1834 dialog->set_filename(filename);
1836 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1838 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1839 filename = dialog->get_filename();
1840 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1841 _preferences.set_value(preference, dirname(filename));
1855 GtkWidget *fileselection;
1856 fileselection = gtk_file_selection_new(title.c_str());
1859 if(basename(filename)==filename)
1861 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1864 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1866 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1868 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1869 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1871 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1872 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1874 gtk_widget_show(fileselection);
1882 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1883 _preferences.set_value(preference,dirname(filename));
1887 gtk_widget_destroy(fileselection);
1890 gtk_widget_destroy(fileselection);
1897 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1899 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1901 #if USE_WIN32_FILE_DIALOGS
1902 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1904 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1905 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1906 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1908 ofn.lStructSize=sizeof(OPENFILENAME);
1909 ofn.hwndOwner = hWnd;
1910 ofn.hInstance = hInstance;
1911 ofn.lpstrFilter = szFilter;
1912 // ofn.lpstrCustomFilter=NULL;
1913 // ofn.nMaxCustFilter=0;
1914 // ofn.nFilterIndex=0;
1915 // ofn.lpstrFile=NULL;
1916 ofn.nMaxFile=MAX_PATH;
1917 // ofn.lpstrFileTitle=NULL;
1918 // ofn.lpstrInitialDir=NULL;
1919 // ofn.lpstrTitle=NULL;
1920 ofn.Flags=OFN_OVERWRITEPROMPT;
1921 // ofn.nFileOffset=0;
1922 // ofn.nFileExtension=0;
1923 ofn.lpstrDefExt=TEXT("sif");
1924 // ofn.lCustData = 0l;
1926 // ofn.lpTemplateName=NULL;
1928 CHAR szFilename[MAX_PATH];
1930 strcpy(szFilename,filename.c_str());
1931 strcpy(szTitle,title.c_str());
1933 ofn.lpstrFile=szFilename;
1934 ofn.lpstrFileTitle=szTitle;
1936 if(GetSaveFileName(&ofn))
1938 filename=szFilename;
1939 _preferences.set_value(preference,dirname(filename));
1944 synfig::String prev_path;
1946 if(!_preferences.get_value(preference, prev_path))
1949 prev_path = absolute_path(prev_path);
1951 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1953 dialog->set_current_folder(prev_path);
1954 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1955 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1957 Widget_Enum *file_type_enum = 0;
1958 if (preference == ANIMATION_DIR_PREFERENCE)
1960 file_type_enum = manage(new Widget_Enum());
1961 file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
1962 .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
1963 .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
1964 .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
1965 file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
1967 Gtk::HBox *hbox = manage(new Gtk::HBox);
1968 hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
1969 hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
1972 dialog->set_extra_widget(*hbox);
1975 if (filename.empty())
1976 dialog->set_filename(prev_path);
1979 std::string full_path;
1980 if (is_absolute_path(filename))
1981 full_path = filename;
1983 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1985 // select the file if it exists
1986 dialog->set_filename(full_path);
1988 // if the file doesn't exist, put its name into the filename box
1990 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1991 dialog->set_current_name(basename(filename));
1994 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1995 if (preference == ANIMATION_DIR_PREFERENCE)
1996 set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
1997 filename = dialog->get_filename();
1998 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
1999 _preferences.set_value(preference, dirname(filename));
2010 App::dialog_error_blocking(const std::string &title, const std::string &message)
2012 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2013 dialog.set_title(title);
2019 App::dialog_warning_blocking(const std::string &title, const std::string &message)
2021 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
2022 dialog.set_title(title);
2028 App::dialog_yes_no(const std::string &title, const std::string &message)
2033 true // use_separator
2035 Gtk::Label label(message);
2038 dialog.get_vbox()->pack_start(label);
2039 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2040 dialog.add_button(Gtk::StockID("gtk-no"),0);
2042 return dialog.run();
2046 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
2051 true // use_separator
2053 Gtk::Label label(message);
2056 dialog.get_vbox()->pack_start(label);
2057 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2058 dialog.add_button(Gtk::StockID("gtk-no"),0);
2059 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
2061 return dialog.run();
2065 App::dialog_not_implemented()
2067 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2068 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
2073 try_open_url(const std::string &url)
2076 return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
2078 gchar* argv[3] = {strdup(App::browser_command.c_str()), strdup(url.c_str()), NULL};
2080 GError* gerror = NULL;
2082 retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &gerror);
2088 error(_("Could not execute specified web browser: %s"), gerror->message);
2089 g_error_free(gerror);
2100 if (!try_open_url("http://synfig.org/Documentation"))
2102 Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
2103 dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
2104 dialog.set_title(_("Help"));
2110 App::open_url(const std::string &url)
2116 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
2121 true // use_separator
2123 Gtk::Label label(message);
2125 dialog.get_vbox()->pack_start(label);
2128 entry.set_text(text);
2130 entry.set_activates_default(true);
2131 dialog.get_vbox()->pack_start(entry);
2133 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
2134 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
2135 dialog.set_default_response(Gtk::RESPONSE_OK);
2136 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
2139 if(dialog.run()!=Gtk::RESPONSE_OK)
2142 text=entry.get_text();
2151 App::open(std::string filename)
2153 return open_as(filename,filename);
2156 // this is called from autorecover.cpp:
2157 // App::open_as(get_shadow_file_name(filename),filename)
2158 // other than that, 'filename' and 'as' are the same
2160 App::open_as(std::string filename,std::string as)
2163 char long_name[1024];
2164 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2170 OneMoment one_moment;
2172 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2173 if(canvas && get_instance(canvas))
2175 get_instance(canvas)->find_canvas_view(canvas)->present();
2176 info("%s is already open", filename.c_str());
2177 // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2182 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2184 add_recent_file(as);
2186 handle<Instance> instance(Instance::create(canvas));
2189 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2191 set_recent_file_window_size(instance);
2195 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)")))
2196 instance->dialog_cvs_update();
2201 dialog_error_blocking(_("Error"), x);
2206 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2217 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2219 String file_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
2220 canvas->set_name(file_name);
2221 file_name += ".sifz";
2223 canvas->rend_desc().set_frame_rate(24.0);
2224 canvas->rend_desc().set_time_start(0.0);
2225 canvas->rend_desc().set_time_end(5.0);
2226 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2227 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2228 canvas->rend_desc().set_tl(Vector(-4,2.25));
2229 canvas->rend_desc().set_br(Vector(4,-2.25));
2230 canvas->rend_desc().set_w(480);
2231 canvas->rend_desc().set_h(270);
2232 canvas->rend_desc().set_antialias(1);
2233 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2234 canvas->set_file_name(file_name);
2236 handle<Instance> instance = Instance::create(canvas);
2238 if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
2239 instance->find_canvas_view(canvas)->canvas_properties.present();
2243 App::dialog_open(string filename)
2245 if (filename.empty())
2248 while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
2250 // If the filename still has wildcards, then we should
2251 // continue looking for the file we want
2252 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2258 get_ui_interface()->error(_("Unable to open file"));
2263 App::set_selected_instance(etl::loose_handle<Instance> instance)
2265 /* if(get_selected_instance()==instance)
2267 selected_instance=instance;
2268 signal_instance_selected()(instance);
2274 selected_instance=instance;
2275 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2279 instance->focus(instance->get_canvas());
2282 set_selected_canvas_view(0);
2284 signal_instance_selected()(instance);
2288 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2290 selected_canvas_view=canvas_view;
2291 signal_canvas_view_focus()(selected_canvas_view);
2294 selected_instance=canvas_view->get_instance();
2295 signal_instance_selected()(canvas_view->get_instance());
2298 if(get_selected_canvas_view()==canvas_view)
2300 signal_canvas_view_focus()(selected_canvas_view);
2301 signal_instance_selected()(canvas_view->get_instance());
2304 selected_canvas_view=canvas_view;
2305 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2306 set_selected_instance(canvas_view->get_instance());
2307 signal_canvas_view_focus()(selected_canvas_view);
2311 etl::loose_handle<Instance>
2312 App::get_instance(etl::handle<synfig::Canvas> canvas)
2314 if(!canvas) return 0;
2315 canvas=canvas->get_root();
2317 std::list<etl::handle<Instance> >::iterator iter;
2318 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2320 if((*iter)->get_canvas()==canvas)
2336 if(selected_instance)
2337 selected_instance->undo();
2343 if(selected_instance)
2344 selected_instance->redo();
2348 studio::App::get_base_path()
2350 return app_base_path_;