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 ======================================================= */
39 #ifdef HAVE_SYS_ERRNO_H
40 #include <sys/errno.h>
42 #include <gtkmm/fileselection.h>
43 #include <gtkmm/dialog.h>
44 #include <gtkmm/messagedialog.h>
45 #include <gtkmm/label.h>
46 #include <gtkmm/stock.h>
47 #include <gtkmm/stockitem.h>
48 #include <gtkmm/iconsource.h>
49 #include <gtkmm/inputdialog.h>
50 #include <gtkmm/accelmap.h>
51 #include <gtkmm/uimanager.h>
55 #include <gdkmm/general.h>
57 #include <synfig/loadcanvas.h>
58 #include <synfig/savecanvas.h>
64 #include "canvasview.h"
65 #include "dialog_setup.h"
66 #include "dialog_gradient.h"
67 #include "dialog_color.h"
70 #include "onemoment.h"
72 #include "dockmanager.h"
74 #include "state_eyedrop.h"
75 #include "state_normal.h"
76 #include "state_draw.h"
77 #include "state_fill.h"
78 #include "state_bline.h"
79 #include "state_polygon.h"
80 #include "state_sketch.h"
81 #include "state_gradient.h"
82 #include "state_circle.h"
83 #include "state_rectangle.h"
84 #include "state_smoothmove.h"
85 #include "state_scale.h"
86 #include "state_width.h"
87 #include "state_rotate.h"
88 #include "state_zoom.h"
90 #include "devicetracker.h"
91 #include "dialog_tooloptions.h"
92 #include "widget_enum.h"
94 #include "autorecover.h"
96 #include <synfigapp/settings.h>
97 #include "dock_history.h"
98 #include "dock_canvases.h"
99 #include "dock_keyframes.h"
100 #include "dock_layers.h"
101 #include "dock_params.h"
102 #include "dock_metadata.h"
103 #include "dock_children.h"
104 #include "dock_info.h"
105 #include "dock_navigator.h"
106 #include "dock_layergroups.h"
107 #include "dock_timetrack.h"
108 #include "dock_curves.h"
110 #include "mod_palette/mod_palette.h"
111 #include "mod_mirror/mod_mirror.h"
113 #include <sys/stat.h>
119 #include "statemanager.h"
126 #define _WIN32_WINNT 0x0500
129 #include <gtkmm/accelmap.h>
130 #include <gtkmm/filechooser.h>
131 #include <gtkmm/filechooserdialog.h>
137 /* === U S I N G =========================================================== */
141 using namespace synfig;
142 using namespace studio;
144 /* === M A C R O S ========================================================= */
146 #ifndef SYNFIG_USER_APP_DIR
148 #define SYNFIG_USER_APP_DIR "Library/Synfig"
149 #elif defined(_WIN32)
150 #define SYNFIG_USER_APP_DIR "Synfig"
152 #define SYNFIG_USER_APP_DIR ".synfig"
157 #define DPM2DPI(x) (float(x)/39.3700787402f)
158 #define DPI2DPM(x) (float(x)*39.3700787402f)
164 # define IMAGE_DIR "share\\pixmaps"
169 # define IMAGE_DIR "/usr/local/share/pixmaps"
173 # define IMAGE_EXT "tif"
176 #include <synfigapp/main.h>
178 /* === S I G N A L S ======================================================= */
180 static sigc::signal<void> signal_present_all_;
182 App::signal_present_all() { return signal_present_all_; }
184 static sigc::signal<void> signal_recent_files_changed_;
186 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
188 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
189 sigc::signal<void,etl::loose_handle<CanvasView> >&
190 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
192 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
193 sigc::signal<void,etl::handle<Instance> >&
194 App::signal_instance_selected() { return signal_instance_selected_; }
196 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
197 sigc::signal<void,etl::handle<Instance> >&
198 App::signal_instance_created() { return signal_instance_created_; }
200 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
201 sigc::signal<void,etl::handle<Instance> >&
202 App::signal_instance_deleted() { return signal_instance_deleted_; }
204 /* === G L O B A L S ======================================================= */
206 static std::list<std::string> recent_files;
207 const std::list<std::string>& App::get_recent_files() { return recent_files; }
209 static std::list<std::string> recent_files_window_size;
211 int App::Busy::count;
212 bool App::shutdown_in_progress;
214 synfig::Gamma App::gamma;
216 Glib::RefPtr<studio::UIManager> App::ui_manager_;
218 synfig::Distance::System App::distance_system;
220 studio::Dialog_Setup* App::dialog_setup;
222 etl::handle< studio::ModPalette > mod_palette_;
223 //studio::Dialog_Palette* App::dialog_palette;
225 std::list<etl::handle<Instance> > App::instance_list;
227 static etl::handle<synfigapp::UIInterface> ui_interface_;
228 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
230 etl::handle<Instance> App::selected_instance;
231 etl::handle<CanvasView> App::selected_canvas_view;
233 studio::About *studio::App::about=NULL;
235 studio::Toolbox *studio::App::toolbox=NULL;
237 studio::AutoRecover *studio::App::auto_recover=NULL;
239 studio::IPC *ipc=NULL;
241 studio::DockManager* studio::App::dock_manager=0;
243 studio::DeviceTracker* studio::App::device_tracker=0;
245 studio::Dialog_Gradient* studio::App::dialog_gradient;
247 studio::Dialog_Color* studio::App::dialog_color;
249 Gtk::InputDialog* studio::App::dialog_input;
251 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
253 studio::Dock_History* dock_history;
254 studio::Dock_Canvases* dock_canvases;
255 studio::Dock_Keyframes* dock_keyframes;
256 studio::Dock_Layers* dock_layers;
257 studio::Dock_Params* dock_params;
258 studio::Dock_MetaData* dock_meta_data;
259 studio::Dock_Children* dock_children;
260 studio::Dock_Info* dock_info;
261 studio::Dock_LayerGroups* dock_layer_groups;
262 studio::Dock_Navigator* dock_navigator;
263 studio::Dock_Timetrack* dock_timetrack;
264 studio::Dock_Curves* dock_curves;
266 std::list< etl::handle< studio::Module > > module_list_;
268 bool studio::App::use_colorspace_gamma=true;
269 #ifdef SINGLE_THREADED
270 bool studio::App::single_threaded=false;
272 bool studio::App::restrict_radius_ducks=false;
273 String studio::App::browser_command("firefox");
275 static int max_recent_files_=25;
276 int studio::App::get_max_recent_files() { return max_recent_files_; }
277 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
279 static synfig::String app_base_path_;
284 really_delete_widget(Gtk::Widget *widget)
286 // synfig::info("really delete %p", (void*)widget);
291 // nasty workaround - when we've finished with a popup menu, we want to delete it
292 // attaching to the signal_hide() signal gets us here before the action on the menu has run,
293 // so schedule the real delete to happen in 50ms, giving the action a chance to run
295 delete_widget(Gtk::Widget *widget)
297 // synfig::info("delete %p", (void*)widget);
298 Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
301 }; // END of namespace studio
302 studio::StateManager* state_manager;
307 class GlobalUIInterface : public synfigapp::UIInterface
311 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
316 true // use_separator
318 Gtk::Label label(message);
321 dialog.get_vbox()->pack_start(label);
322 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
323 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
325 dialog.set_default_response(dflt);
327 return (Response)dialog.run();
329 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
334 true // use_separator
336 Gtk::Label label(message);
339 dialog.get_vbox()->pack_start(label);
340 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
341 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
342 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
344 dialog.set_default_response(dflt);
346 return (Response)dialog.run();
348 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
353 true // use_separator
355 Gtk::Label label(message);
358 dialog.get_vbox()->pack_start(label);
359 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
360 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
362 dialog.set_default_response(dflt);
364 return (Response)dialog.run();
368 task(const std::string &task)
370 std::cerr<<task<<std::endl;
371 while(studio::App::events_pending())studio::App::iteration(false);
376 error(const std::string &err)
378 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
385 warning(const std::string &err)
387 std::cerr<<"warning: "<<err<<std::endl;
388 while(studio::App::events_pending())studio::App::iteration(false);
393 amount_complete(int /*current*/, int /*total*/)
395 while(studio::App::events_pending())studio::App::iteration(false);
400 /* === P R O C E D U R E S ================================================= */
404 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
406 action_group_list.push_back(action_group);
407 Gtk::UIManager::insert_action_group(action_group, pos);
411 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
413 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
414 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
415 if(*iter==action_group)
417 action_group_list.erase(iter);
418 Gtk::UIManager::remove_action_group(action_group);
421 synfig::error("Unable to find action group");
425 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
427 ui_manager->insert_action_group(group,0);
429 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
430 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
432 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
434 if(*iter && (*iter)->get_name()!="menus")
436 synfig::info("Removing action group "+(*iter)->get_name());
437 ui_manager->remove_action_group(*iter);
440 ui_manager->insert_action_group(group,0);
442 for(;!prev_groups.empty();prev_groups.pop_front())
444 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
445 ui_manager->insert_action_group(prev_groups.front(),1);
449 class Preferences : public synfigapp::Settings
452 virtual bool get_value(const synfig::String& key, synfig::String& value)const
456 value=strprintf("%f %f %f %f",
457 App::gamma.get_gamma_r(),
458 App::gamma.get_gamma_g(),
459 App::gamma.get_gamma_b(),
460 App::gamma.get_black_level()
464 if(key=="time_format")
466 value=strprintf("%i",App::get_time_format());
469 if(key=="file_history.size")
471 value=strprintf("%i",App::get_max_recent_files());
474 if(key=="use_colorspace_gamma")
476 value=strprintf("%i",(int)App::use_colorspace_gamma);
479 if(key=="distance_system")
481 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
484 #ifdef SINGLE_THREADED
485 if(key=="single_threaded")
487 value=strprintf("%i",(int)App::single_threaded);
491 if(key=="auto_recover_backup_interval")
493 value=strprintf("%i",App::auto_recover->get_timeout());
496 if(key=="restrict_radius_ducks")
498 value=strprintf("%i",(int)App::restrict_radius_ducks);
501 if(key=="browser_command")
503 value=App::browser_command;
507 return synfigapp::Settings::get_value(key,value);
510 virtual bool set_value(const synfig::String& key,const synfig::String& value)
516 strscanf(value,"%f %f %f %f",
523 App::gamma.set_all(r,g,b,blk);
527 if(key=="time_format")
529 int i(atoi(value.c_str()));
530 App::set_time_format(static_cast<synfig::Time::Format>(i));
533 if(key=="auto_recover_backup_interval")
535 int i(atoi(value.c_str()));
536 App::auto_recover->set_timeout(i);
539 if(key=="file_history.size")
541 int i(atoi(value.c_str()));
542 App::set_max_recent_files(i);
545 if(key=="use_colorspace_gamma")
547 int i(atoi(value.c_str()));
548 App::use_colorspace_gamma=i;
551 if(key=="distance_system")
553 App::distance_system=Distance::ident_system(value);;
556 #ifdef SINGLE_THREADED
557 if(key=="single_threaded")
559 int i(atoi(value.c_str()));
560 App::single_threaded=i;
564 if(key=="restrict_radius_ducks")
566 int i(atoi(value.c_str()));
567 App::restrict_radius_ducks=i;
570 if(key=="browser_command")
572 App::browser_command=value;
576 return synfigapp::Settings::set_value(key,value);
579 virtual KeyList get_key_list()const
581 KeyList ret(synfigapp::Settings::get_key_list());
582 ret.push_back("gamma");
583 ret.push_back("time_format");
584 ret.push_back("distance_system");
585 ret.push_back("file_history.size");
586 ret.push_back("use_colorspace_gamma");
587 #ifdef SINGLE_THREADED
588 ret.push_back("single_threaded");
590 ret.push_back("auto_recover_backup_interval");
591 ret.push_back("restrict_radius_ducks");
592 ret.push_back("browser_command");
597 static ::Preferences _preferences;
602 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
604 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
606 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
608 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
609 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
610 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
611 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
612 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
613 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
614 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
615 menus_action_group->add( Gtk::Action::create("menu-lowres-pixel", _("Low-Res Pixel Size")) );
616 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
617 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
618 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
619 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
620 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
622 // Add the synfigapp actions...
623 synfigapp::Action::Book::iterator iter;
624 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
626 actions_action_group->add(Gtk::Action::create(
627 "action-"+iter->second.name,
628 get_action_stock_id(iter->second),
629 iter->second.local_name,iter->second.local_name
633 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
634 #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); }
635 #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); }
637 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
638 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
639 DEFINE_ACTION("new", Gtk::Stock::NEW);
640 DEFINE_ACTION("open", Gtk::Stock::OPEN);
641 DEFINE_ACTION("save", Gtk::Stock::SAVE);
642 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
643 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
644 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
645 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
646 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
647 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
648 DEFINE_ACTION("import", _("Import"));
649 DEFINE_ACTION("render", _("Render"));
650 DEFINE_ACTION("preview", _("Preview"));
651 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
652 DEFINE_ACTION("sound", _("Sound File"));
653 DEFINE_ACTION("options", _("Options"));
654 DEFINE_ACTION("close", _("Close View"));
655 DEFINE_ACTION("close-document", _("Close Document"));
656 DEFINE_ACTION("quit", Gtk::Stock::QUIT);
659 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
660 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
661 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
662 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
663 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
664 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
665 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
666 DEFINE_ACTION("properties", _("Properties"));
668 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
669 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
670 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
671 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
672 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
673 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
674 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
675 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
676 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
677 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
678 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
679 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
680 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
681 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
682 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
683 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
684 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
685 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
686 DEFINE_ACTION(strprintf("lowres-pixel-%d", *iter), strprintf(_("Set Low-Res pixel size to %d"), *iter));
687 DEFINE_ACTION("play", _("Play"));
688 // DEFINE_ACTION("pause", _("Pause"));
689 DEFINE_ACTION("stop", _("Stop"));
690 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
691 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
692 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
693 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
694 DEFINE_ACTION("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size"));
695 DEFINE_ACTION("increase-low-res-pixel-size", _("Increase Low-Res Pixel Size"));
696 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
697 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
698 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
699 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
700 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
701 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
702 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
703 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
704 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
705 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
706 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
707 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
708 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
709 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
710 DEFINE_ACTION("seek-end", _("Seek to End"));
712 DEFINE_ACTION("action-group_add", _("Add group"));
714 DEFINE_ACTION("canvas-new", _("New Canvas"));
716 DEFINE_ACTION("amount-inc", _("Increase Amount"));
717 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
722 // Set up synfigapp actions
724 synfigapp::Action::Book::iterator iter;
726 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
728 Gtk::StockID stock_id;
730 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
732 //Gtk::Image* image(manage(new Gtk::Image()));
733 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
734 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
735 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
736 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
737 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
738 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
739 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
740 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
741 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
742 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
744 actions_action_group->add(Gtk::Action::create(
745 "action-"+iter->second.name,
747 iter->second.local_name,iter->second.local_name
755 Glib::ustring ui_info =
757 " <popup name='menu-toolbox' action='menu-toolbox'>"
758 " <menu action='menu-file'>"
761 " <popup name='menu-main' action='menu-main'>"
762 " <menu action='menu-file'>"
763 " <menuitem action='new' />"
764 " <menuitem action='open' />"
765 " <menuitem action='save' />"
766 " <menuitem action='save-as' />"
767 " <menuitem action='revert' />"
768 " <separator name='bleh01'/>"
769 " <menuitem action='cvs-add' />"
770 " <menuitem action='cvs-update' />"
771 " <menuitem action='cvs-commit' />"
772 " <menuitem action='cvs-revert' />"
773 " <separator name='bleh02'/>"
774 " <menuitem action='import' />"
775 " <separator name='bleh03'/>"
776 " <menuitem action='render' />"
777 " <menuitem action='preview' />"
778 " <menuitem action='sound' />"
779 " <separator name='bleh04'/>"
780 " <menuitem action='options' />"
781 " <menuitem action='close' />"
782 " <menuitem action='close-document' />"
783 " <menuitem action='quit' />"
785 " <menu action='menu-edit'>"
786 " <menuitem action='undo'/>"
787 " <menuitem action='redo'/>"
788 " <separator name='bleh05'/>"
789 " <menuitem action='cut'/>"
790 " <menuitem action='copy'/>"
791 " <menuitem action='paste'/>"
792 " <separator name='bleh06'/>"
793 " <menuitem action='select-all-ducks'/>"
794 " <menuitem action='unselect-all-layers'/>"
795 " <separator name='bleh07'/>"
796 " <menuitem action='properties'/>"
798 " <menu action='menu-view'>"
799 " <menu action='menu-duck-mask'>"
800 " <menuitem action='mask-position-ducks' />"
801 " <menuitem action='mask-vertex-ducks' />"
802 " <menuitem action='mask-tangent-ducks' />"
803 " <menuitem action='mask-radius-ducks' />"
804 " <menuitem action='mask-width-ducks' />"
805 " <menuitem action='mask-angle-ducks' />"
807 " <menu action='menu-preview-quality'>"
808 " <menuitem action='quality-00' />"
809 " <menuitem action='quality-01' />"
810 " <menuitem action='quality-02' />"
811 " <menuitem action='quality-03' />"
812 " <menuitem action='quality-04' />"
813 " <menuitem action='quality-05' />"
814 " <menuitem action='quality-06' />"
815 " <menuitem action='quality-07' />"
816 " <menuitem action='quality-08' />"
817 " <menuitem action='quality-09' />"
818 " <menuitem action='quality-10' />"
820 " <menu action='menu-lowres-pixel'>"
821 " <menuitem action='decrease-low-res-pixel-size'/>"
822 " <menuitem action='increase-low-res-pixel-size'/>"
823 " <separator name='pixel-size-separator'/>"
826 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
827 ui_info += strprintf(" <menuitem action='lowres-pixel-%d' />", *iter);
831 " <separator name='bleh08'/>"
832 " <menuitem action='play'/>"
833 //" <menuitem action='pause'/>"
834 " <menuitem action='stop'/>"
835 " <menuitem action='dialog-flipbook'/>"
836 " <separator name='bleh09'/>"
837 " <menuitem action='toggle-grid-show'/>"
838 " <menuitem action='toggle-grid-snap'/>"
839 " <menuitem action='toggle-guide-show'/>"
840 " <menuitem action='toggle-low-res'/>"
841 " <menuitem action='toggle-onion-skin'/>"
842 " <separator name='bleh10'/>"
843 " <menuitem action='canvas-zoom-in'/>"
844 " <menuitem action='canvas-zoom-out'/>"
845 " <menuitem action='canvas-zoom-fit'/>"
846 " <menuitem action='canvas-zoom-100'/>"
847 " <separator name='bleh11'/>"
848 " <menuitem action='time-zoom-in'/>"
849 " <menuitem action='time-zoom-out'/>"
850 " <separator name='bleh12'/>"
851 " <menuitem action='jump-next-keyframe'/>"
852 " <menuitem action='jump-prev-keyframe'/>"
853 " <menuitem action='seek-next-frame'/>"
854 " <menuitem action='seek-prev-frame'/>"
855 " <menuitem action='seek-next-second'/>"
856 " <menuitem action='seek-prev-second'/>"
857 " <menuitem action='seek-begin'/>"
858 " <menuitem action='seek-end'/>"
860 " <menu action='menu-canvas'>"
861 " <menuitem action='canvas-new'/>"
863 " <menu name='menu-state' action='menu-state'>"
865 " <menu action='menu-group'>"
866 " <menuitem action='action-group_add'/>"
868 " <menu action='menu-layer'>"
869 //" <menuitem action='cut'/>"
870 //" <menuitem action='copy'/>"
871 //" <menuitem action='paste'/>"
872 //" <separator name='bleh06'/>"
873 " <menu action='menu-layer-new'></menu>"
874 " <menuitem action='amount-inc'/>"
875 " <menuitem action='amount-dec'/>"
877 " <menu action='menu-keyframe'>"
878 " <menuitem action='keyframe-properties'/>"
885 " <menubar name='MenuBar'>"
886 " <menu action='MenuFile'>"
887 " <menuitem action='New'/>"
888 " <menuitem action='Open'/>"
890 " <menuitem action='Quit'/>"
892 " <menu action='MenuEdit'>"
893 " <menuitem action='Cut'/>"
894 " <menuitem action='Copy'/>"
895 " <menuitem action='Paste'/>"
898 " <toolbar name='ToolBar'>"
899 " <toolitem action='Open'/>"
900 " <toolitem action='Quit'/>"
906 actions_action_group->set_sensitive(false);
907 App::ui_manager()->set_add_tearoffs(true);
908 App::ui_manager()->insert_action_group(menus_action_group,1);
909 App::ui_manager()->insert_action_group(actions_action_group,1);
910 App::ui_manager()->add_ui_from_string(ui_info);
912 //App::ui_manager()->get_accel_group()->unlock();
914 catch(const Glib::Error& ex)
916 synfig::error("building menus and toolbars failed: " + ex.what());
919 // Add default keyboard accelerators
920 #define ACCEL(path,accel) \
922 Gtk::AccelKey accel_key(accel,path); \
923 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
926 #define ACCEL2(accel) \
928 Gtk::AccelKey accel_key(accel); \
929 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
932 ACCEL("<Actions>//select-all-ducks","<Control>a");
933 ACCEL("<Actions>//unselect-all-layers","<Control>d");
934 ACCEL("<Actions>//render","F9");
935 ACCEL("<Actions>//preview","F11");
936 ACCEL("<Actions>//properties","F8");
937 ACCEL("<Actions>//options","F12");
938 ACCEL("<Actions>//import","<control>i");
939 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
940 ACCEL("<Actions>//toggle-grid-show","<Control>g");
941 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
942 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
943 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
944 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
945 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
946 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
947 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
948 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
950 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
951 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
953 ACCEL("<Actions>//quality-01","<Control>1");
954 ACCEL("<Actions>//quality-02","<Control>2");
955 ACCEL("<Actions>//quality-03","<Control>3");
956 ACCEL("<Actions>//quality-04","<Control>4");
957 ACCEL("<Actions>//quality-05","<Control>5");
958 ACCEL("<Actions>//quality-06","<Control>6");
959 ACCEL("<Actions>//quality-07","<Control>7");
960 ACCEL("<Actions>//quality-08","<Control>8");
961 ACCEL("<Actions>//quality-09","<Control>9");
962 ACCEL("<Actions>//quality-10","<Control>0");
963 ACCEL("<Actions>//undo","<Control>z");
964 ACCEL("<Actions>//redo","<Control>r");
965 ACCEL("<Actions>//action-layer_remove","Delete");
967 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
968 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
969 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
970 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
971 ACCEL("<Actions>//time-zoom-in","+");
972 ACCEL("<Actions>//time-zoom-out","_");
974 ACCEL2(Gtk::AccelKey('(',Gdk::CONTROL_MASK,"<Actions>//decrease-low-res-pixel-size"));
975 ACCEL2(Gtk::AccelKey(')',Gdk::CONTROL_MASK,"<Actions>//increase-low-res-pixel-size"));
977 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
978 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
980 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
981 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
982 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
983 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
984 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
985 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
986 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
987 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
988 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
989 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
990 ACCEL2(Gtk::AccelKey('o',Gdk::MOD1_MASK,"<Actions>//toggle-onion-skin"));
991 ACCEL("<Actions>//play", "<Control>p");
992 ACCEL("<Actions>//seek-begin","Home");
993 ACCEL("<Actions>//seek-end","End");
995 ACCEL("<Actions>//state-normal", "<Mod1>a");
996 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
997 ACCEL("<Actions>//state-scale", "<Mod1>d");
998 ACCEL("<Actions>//state-rotate", "<Mod1>s");
1000 ACCEL("<Actions>//state-bline", "<Mod1>b");
1001 ACCEL("<Actions>//state-circle", "<Mod1>c");
1002 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
1003 ACCEL("<Actions>//state-gradient", "<Mod1>g");
1005 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
1006 ACCEL("<Actions>//state-fill", "<Mod1>f");
1007 ACCEL("<Actions>//state-zoom", "<Mod1>z");
1008 ACCEL("<Actions>//state-polygon", "<Mod1>p");
1010 ACCEL("<Actions>//state-draw", "<Mod1>w");
1011 ACCEL("<Actions>//state-sketch", "<Mod1>k");
1012 ACCEL("<Actions>//state-width", "<Mod1>t");
1013 ACCEL("<Actions>//state-mirror", "<Mod1>m");
1015 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1021 #define mkdir(x,y) mkdir(x)
1024 /* === M E T H O D S ======================================================= */
1026 App::App(int *argc, char ***argv):
1027 Gtk::Main(argc,argv),
1028 IconController(etl::dirname((*argv)[0]))
1030 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1033 ui_interface_=new GlobalUIInterface();
1037 // don't call thread_init() if threads are already initialized
1038 // on some machines bonobo_init() initialized threads before we get here
1039 if (!g_thread_supported())
1040 Glib::thread_init();
1042 distance_system=Distance::SYSTEM_UNITS;
1044 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1047 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1051 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1057 if(!SYNFIG_CHECK_VERSION())
1059 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1060 dialog_error_blocking("Synfig Studio",
1061 "This copy of Synfig Studio was compiled against a\n"
1062 "different version of libsynfig than what is currently\n"
1063 "installed. Synfig Studio will now abort. Try downloading\n"
1064 "the latest version from the Synfig website at\n"
1065 "http://synfig.org/Download"
1069 Glib::set_application_name(_("Synfig Studio"));
1071 Splash splash_screen;
1072 splash_screen.set_can_self_destruct(false);
1073 splash_screen.show();
1075 shutdown_in_progress=false;
1076 SuperCallback synfig_init_cb(splash_screen.get_callback(),0,9000,10000);
1077 SuperCallback studio_init_cb(splash_screen.get_callback(),9000,10000,10000);
1079 // Initialize the Synfig library
1080 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1083 get_ui_interface()->error(_("Failed to initialize synfig!"));
1087 // add the preferences to the settings
1088 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1092 studio_init_cb.task(_("Init UI Manager..."));
1093 App::ui_manager_=studio::UIManager::create();
1096 studio_init_cb.task(_("Init Dock Manager..."));
1097 dock_manager=new studio::DockManager();
1099 studio_init_cb.task(_("Init State Manager..."));
1100 state_manager=new StateManager();
1102 studio_init_cb.task(_("Init Toolbox..."));
1103 toolbox=new studio::Toolbox();
1105 studio_init_cb.task(_("Init About Dialog..."));
1106 about=new studio::About();
1108 studio_init_cb.task(_("Init Tool Options..."));
1109 dialog_tool_options=new studio::Dialog_ToolOptions();
1110 dock_manager->register_dockable(*dialog_tool_options);
1112 studio_init_cb.task(_("Init History..."));
1113 dock_history=new studio::Dock_History();
1114 dock_manager->register_dockable(*dock_history);
1116 studio_init_cb.task(_("Init Canvases..."));
1117 dock_canvases=new studio::Dock_Canvases();
1118 dock_manager->register_dockable(*dock_canvases);
1120 studio_init_cb.task(_("Init Keyframes..."));
1121 dock_keyframes=new studio::Dock_Keyframes();
1122 dock_manager->register_dockable(*dock_keyframes);
1124 studio_init_cb.task(_("Init Layers..."));
1125 dock_layers=new studio::Dock_Layers();
1126 dock_manager->register_dockable(*dock_layers);
1128 studio_init_cb.task(_("Init Params..."));
1129 dock_params=new studio::Dock_Params();
1130 dock_manager->register_dockable(*dock_params);
1132 studio_init_cb.task(_("Init MetaData..."));
1133 dock_meta_data=new studio::Dock_MetaData();
1134 dock_manager->register_dockable(*dock_meta_data);
1136 studio_init_cb.task(_("Init Children..."));
1137 dock_children=new studio::Dock_Children();
1138 dock_manager->register_dockable(*dock_children);
1140 studio_init_cb.task(_("Init Info..."));
1141 dock_info = new studio::Dock_Info();
1142 dock_manager->register_dockable(*dock_info);
1144 studio_init_cb.task(_("Init Navigator..."));
1145 dock_navigator = new studio::Dock_Navigator();
1146 dock_manager->register_dockable(*dock_navigator);
1148 studio_init_cb.task(_("Init Timetrack..."));
1149 dock_timetrack = new studio::Dock_Timetrack();
1150 dock_manager->register_dockable(*dock_timetrack);
1152 studio_init_cb.task(_("Init Curve Editor..."));
1153 dock_curves = new studio::Dock_Curves();
1154 dock_manager->register_dockable(*dock_curves);
1156 studio_init_cb.task(_("Init Layer Groups..."));
1157 dock_layer_groups = new studio::Dock_LayerGroups();
1158 dock_manager->register_dockable(*dock_layer_groups);
1161 studio_init_cb.task(_("Init Color Dialog..."));
1162 dialog_color=new studio::Dialog_Color();
1164 studio_init_cb.task(_("Init Gradient Dialog..."));
1165 dialog_gradient=new studio::Dialog_Gradient();
1167 studio_init_cb.task(_("Init DeviceTracker..."));
1168 device_tracker=new studio::DeviceTracker();
1170 studio_init_cb.task(_("Init Tools..."));
1173 state_manager->add_state(&state_normal);
1174 state_manager->add_state(&state_smooth_move);
1175 state_manager->add_state(&state_scale);
1176 state_manager->add_state(&state_rotate);
1177 studio_init_cb.task(_("Init ModMirror...")); module_list_.push_back(new ModMirror()); module_list_.back()->start();
1180 state_manager->add_state(&state_bline);
1181 state_manager->add_state(&state_circle);
1182 state_manager->add_state(&state_rectangle);
1183 state_manager->add_state(&state_gradient);
1184 if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks
1187 if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw); // Enabled for now. Let's see whether they're good enough yet.
1188 if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
1189 state_manager->add_state(&state_fill);
1190 state_manager->add_state(&state_eyedrop);
1191 state_manager->add_state(&state_zoom);
1193 // Disabled by default - it doesn't work properly?
1194 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1196 studio_init_cb.task(_("Init ModPalette..."));
1197 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1199 studio_init_cb.task(_("Init Setup Dialog..."));
1200 dialog_setup=new studio::Dialog_Setup();
1202 studio_init_cb.task(_("Init Input Dialog..."));
1203 dialog_input=new Gtk::InputDialog();
1204 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1205 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1207 studio_init_cb.task(_("Init auto recovery..."));
1208 auto_recover=new AutoRecover();
1210 studio_init_cb.amount_complete(9250,10000);
1211 studio_init_cb.task(_("Loading Settings..."));
1213 studio_init_cb.task(_("Checking auto-recover..."));
1215 studio_init_cb.amount_complete(9900,10000);
1217 bool opened_any = false;
1218 if(auto_recover->recovery_needed())
1220 splash_screen.hide();
1221 if (get_ui_interface()->yes_no(_("Auto Recovery"),
1222 _("Synfig Studio seems to have crashed\n"
1223 "before you could save all your files.\n"
1224 "Would you like to re-open those files\n"
1225 "and recover your unsaved changes?")) ==
1226 synfigapp::UIInterface::RESPONSE_YES)
1228 int number_recovered;
1229 if(!auto_recover->recover(number_recovered))
1230 if (number_recovered)
1231 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1233 get_ui_interface()->error(_("Unable to recover from previous crash"));
1235 get_ui_interface()->error(
1236 _("Synfig Studio has attempted to recover\n"
1237 "from a previous crash. The files that it has\n"
1238 "recovered are NOT YET SAVED. It would be a good\n"
1239 "idea to review them and save them now."));
1241 if (number_recovered)
1244 splash_screen.show();
1247 // Look for any files given on the command line,
1248 // and load them if found.
1249 for(;*argc>=1;(*argc)--)
1250 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1252 studio_init_cb.task(_("Loading files..."));
1253 splash_screen.hide();
1254 open((*argv)[*argc]);
1256 splash_screen.show();
1259 // if no file was specified to be opened, create a new document to help new users get started more easily
1260 if (!opened_any && !getenv("SYNFIG_DISABLE_AUTOMATIC_DOCUMENT_CREATION"))
1263 studio_init_cb.task(_("Done."));
1264 studio_init_cb.amount_complete(10000,10000);
1270 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1274 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1278 StateManager* App::get_state_manager() { return state_manager; }
1282 shutdown_in_progress=true;
1286 synfigapp::Main::settings().remove_domain("pref");
1288 selected_instance=0;
1290 // Unload all of the modules
1291 for(;!module_list_.empty();module_list_.pop_back())
1294 delete state_manager;
1298 delete auto_recover;
1304 // studio::App::iteration(false);
1308 // studio::App::iteration(false);
1310 // studio::App::iteration(false);
1312 delete dialog_setup;
1314 delete dialog_gradient;
1316 delete dialog_color;
1318 delete dialog_input;
1320 delete dock_manager;
1322 instance_list.clear();
1324 // studio::App::iteration(false);
1328 App::get_user_app_directory()
1330 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1334 App::get_config_file(const synfig::String& file)
1336 return Glib::build_filename(get_user_app_directory(),file);
1339 #define SCALE_FACTOR (1280)
1340 //! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size
1342 App::set_recent_file_window_size(etl::handle<Instance> instance)
1344 int screen_w(Gdk::screen_width());
1345 int screen_h(Gdk::screen_height());
1347 const std::string &canvas_window_size = *recent_files_window_size.begin();
1349 if(canvas_window_size.empty())
1352 synfig::String::size_type current=0;
1353 bool seen_root(false), shown_non_root(false);
1355 while(current != synfig::String::npos)
1357 // find end of first field (canvas) or return
1358 synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
1359 if(separator == synfig::String::npos) break;
1362 synfig::Canvas::Handle canvas;
1364 canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current));
1366 catch(Exception::IDNotFound) {
1367 // can't find the canvas; skip to the next canvas or return
1368 separator = canvas_window_size.find_first_of('\t', current);
1369 if(separator == synfig::String::npos) return;
1370 current = separator+1;
1374 if (canvas->is_root())
1377 shown_non_root = true;
1379 // check that we have the tab character the ends this canvas' data or return
1380 current = separator+1;
1381 separator = canvas_window_size.find_first_of('\t', current);
1382 if(separator == synfig::String::npos) return;
1385 if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
1387 current = separator+1;
1391 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
1392 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
1393 x=x*screen_w/SCALE_FACTOR;
1394 y=y*screen_h/SCALE_FACTOR;
1395 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
1396 x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
1397 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
1398 y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
1400 if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
1401 if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
1403 CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
1404 canvasview->move(x,y);
1405 canvasview->resize(w*screen_w/SCALE_FACTOR,h*screen_h/SCALE_FACTOR);
1406 canvasview->present();
1408 current = separator+1;
1411 if (shown_non_root && !seen_root)
1412 instance->find_canvas_view(instance->get_canvas())->hide();
1416 App::add_recent_file(const etl::handle<Instance> instance)
1418 int screen_w(Gdk::screen_width());
1419 int screen_h(Gdk::screen_height());
1421 std::string canvas_window_size;
1423 const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
1424 Instance::CanvasViewList::const_iterator iter;
1426 for(iter=cview_list.begin();iter!=cview_list.end();iter++)
1428 if( !((*iter)->is_visible()) )
1431 etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
1432 int x_pos, y_pos, x_size, y_size;
1433 (*iter)->get_position(x_pos,y_pos);
1434 (*iter)->get_size(x_size,y_size);
1436 canvas_window_size += strprintf("%s %d %d %d %d\t",
1437 canvas->get_relative_id(canvas->get_root()).c_str(),
1438 x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h,
1439 x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
1442 add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
1447 App::add_recent_file(const std::string &file_name, const std::string &window_size)
1449 std::string filename(file_name);
1451 assert(!filename.empty());
1453 if(filename.empty())
1456 // Toss out any "hidden" files
1457 if(basename(filename)[0]=='.')
1460 // If we aren't an absolute path, turn ourselves into one
1461 if(!is_absolute_path(filename))
1462 filename=absolute_path(filename);
1464 std::string old_window_size;
1466 list<string>::iterator iter;
1467 list<string>::iterator iter_wsize;
1468 // Check to see if the file is already on the list.
1469 // If it is, then remove it from the list
1470 for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
1473 recent_files.erase(iter);
1474 old_window_size = *iter_wsize;
1475 recent_files_window_size.erase(iter_wsize);
1480 // Push the filename to the front of the list
1481 recent_files.push_front(filename);
1482 if(window_size.empty())
1483 recent_files_window_size.push_front(old_window_size);
1485 recent_files_window_size.push_front(window_size);
1487 // Clean out the files at the end of the list.
1488 while(recent_files.size()>(unsigned)get_max_recent_files())
1490 recent_files.pop_back();
1491 recent_files_window_size.pop_back();
1494 signal_recent_files_changed_();
1499 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1502 App::get_time_format()
1504 return _App_time_format;
1508 App::set_time_format(synfig::Time::Format x)
1515 App::save_settings()
1520 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1521 setlocale(LC_NUMERIC, "C");
1523 std::string filename=get_config_file("accelrc");
1524 Gtk::AccelMap::save(filename);
1527 std::string filename=get_config_file("recentfiles");
1529 std::ofstream file(filename.c_str());
1533 synfig::warning("Unable to save %s",filename.c_str());
1537 list<string>::reverse_iterator iter;
1539 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1543 std::string filename=get_config_file("recentfiles")+std::string("_window_size");
1545 std::ofstream file(filename.c_str());
1549 synfig::warning("Unable to save %s",filename.c_str());
1553 list<string>::reverse_iterator iter;
1555 for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
1559 std::string filename=get_config_file("settings");
1560 synfigapp::Main::settings().save_to_file(filename);
1561 setlocale(LC_NUMERIC,old_locale);
1565 synfig::warning("Caught exception when attempting to save settings.");
1570 App::load_settings()
1575 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1576 setlocale(LC_NUMERIC, "C");
1578 std::string filename=get_config_file("accelrc");
1579 Gtk::AccelMap::load(filename);
1582 bool window_size_broken = false;
1584 std::string filename=get_config_file("recentfiles");
1585 std::string filename_window_size=filename+std::string("_window_size");
1587 std::ifstream file(filename.c_str());
1588 std::ifstream file_window_size(filename_window_size.c_str());
1590 if(!file_window_size)
1591 window_size_broken = true;
1595 std::string recent_file;
1596 std::string recent_file_window_size;
1597 getline(file,recent_file);
1598 if(!window_size_broken)
1599 getline(file_window_size,recent_file_window_size);
1600 if(!recent_file.empty())
1602 if(!window_size_broken && !file_window_size)
1603 window_size_broken = true;
1604 if(!window_size_broken)
1605 add_recent_file(recent_file,recent_file_window_size);
1607 add_recent_file(recent_file);
1610 if(!window_size_broken && file_window_size)
1611 window_size_broken = true;
1613 if(window_size_broken)
1615 recent_files_window_size.clear();
1616 recent_files_window_size.resize(recent_files.size());
1619 std::string filename=get_config_file("settings");
1620 if(!synfigapp::Main::settings().load_from_file(filename))
1622 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1623 //if(!synfigapp::Main::settings().load_from_file(filename))
1625 gamma.set_gamma(1.0/2.2);
1626 reset_initial_window_configuration();
1629 setlocale(LC_NUMERIC,old_locale);
1633 synfig::warning("Caught exception when attempting to load settings.");
1638 App::reset_initial_window_configuration()
1640 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1641 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1642 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1643 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1644 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1645 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1646 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1647 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1648 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1649 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1650 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1651 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1652 #ifdef SINGLE_THREADED
1653 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1655 synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
1656 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1660 App::shutdown_request(GdkEventAny*)
1664 //return !shutdown_in_progress;
1670 if(shutdown_in_progress)return;
1673 get_ui_interface()->task(_("Quit Request"));
1676 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1680 std::list<etl::handle<Instance> >::iterator iter;
1681 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1683 if(!(*iter)->safe_close())
1687 if((*iter)->synfigapp::Instance::get_action_count())
1689 handle<synfigapp::UIInterface> uim;
1690 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1692 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1693 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1695 case synfigapp::UIInterface::RESPONSE_NO:
1697 case synfigapp::UIInterface::RESPONSE_YES:
1700 case synfigapp::UIInterface::RESPONSE_CANCEL:
1709 if((*iter)->synfigapp::Instance::is_modified())
1711 handle<synfigapp::UIInterface> uim;
1712 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1714 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() );
1715 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1717 case synfigapp::UIInterface::RESPONSE_NO:
1719 case synfigapp::UIInterface::RESPONSE_YES:
1720 (*iter)->dialog_cvs_commit();
1722 case synfigapp::UIInterface::RESPONSE_CANCEL:
1731 // This next line causes things to crash for some reason
1735 shutdown_in_progress=true;
1737 instance_list.clear();
1739 while(studio::App::events_pending())studio::App::iteration(false);
1742 auto_recover->normal_shutdown();
1744 get_ui_interface()->task(_("Quit Request sent"));
1750 dialog_setup->refresh();
1751 dialog_setup->show();
1754 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1755 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1758 //#define USE_WIN32_FILE_DIALOGS 1
1761 #ifdef USE_WIN32_FILE_DIALOGS
1762 static OPENFILENAME ofn={};
1766 #include <gdk/gdkwin32.h>
1770 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1772 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1774 #ifdef USE_WIN32_FILE_DIALOGS
1775 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1777 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1778 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1779 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1781 ofn.lStructSize=sizeof(OPENFILENAME);
1782 ofn.hwndOwner = hWnd;
1783 ofn.hInstance = hInstance;
1784 ofn.lpstrFilter = szFilter;
1785 // ofn.lpstrCustomFilter=NULL;
1786 // ofn.nMaxCustFilter=0;
1787 // ofn.nFilterIndex=0;
1788 // ofn.lpstrFile=NULL;
1789 ofn.nMaxFile=MAX_PATH;
1790 // ofn.lpstrFileTitle=NULL;
1791 // ofn.lpstrInitialDir=NULL;
1792 // ofn.lpstrTitle=NULL;
1793 ofn.Flags=OFN_HIDEREADONLY;
1794 // ofn.nFileOffset=0;
1795 // ofn.nFileExtension=0;
1796 ofn.lpstrDefExt=TEXT("sif");
1797 // ofn.lCustData = 0l;
1799 // ofn.lpTemplateName=NULL;
1801 CHAR szFilename[MAX_PATH];
1803 strcpy(szFilename,filename.c_str());
1804 strcpy(szTitle,title.c_str());
1806 ofn.lpstrFile=szFilename;
1807 ofn.lpstrFileTitle=szTitle;
1809 if(GetOpenFileName(&ofn))
1811 filename=szFilename;
1817 synfig::String prev_path;
1819 if(!_preferences.get_value(preference, prev_path))
1822 prev_path = absolute_path(prev_path);
1824 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1826 dialog->set_current_folder(prev_path);
1827 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1828 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1830 if (filename.empty())
1831 dialog->set_filename(prev_path);
1832 else if (is_absolute_path(filename))
1833 dialog->set_filename(filename);
1835 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1837 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1838 filename = dialog->get_filename();
1839 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1840 _preferences.set_value(preference, dirname(filename));
1854 GtkWidget *fileselection;
1855 fileselection = gtk_file_selection_new(title.c_str());
1858 if(basename(filename)==filename)
1860 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1863 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1865 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1867 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1868 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1870 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1871 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1873 gtk_widget_show(fileselection);
1881 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1882 _preferences.set_value(preference,dirname(filename));
1886 gtk_widget_destroy(fileselection);
1889 gtk_widget_destroy(fileselection);
1896 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1898 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1900 #if USE_WIN32_FILE_DIALOGS
1901 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1903 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1904 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1905 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1907 ofn.lStructSize=sizeof(OPENFILENAME);
1908 ofn.hwndOwner = hWnd;
1909 ofn.hInstance = hInstance;
1910 ofn.lpstrFilter = szFilter;
1911 // ofn.lpstrCustomFilter=NULL;
1912 // ofn.nMaxCustFilter=0;
1913 // ofn.nFilterIndex=0;
1914 // ofn.lpstrFile=NULL;
1915 ofn.nMaxFile=MAX_PATH;
1916 // ofn.lpstrFileTitle=NULL;
1917 // ofn.lpstrInitialDir=NULL;
1918 // ofn.lpstrTitle=NULL;
1919 ofn.Flags=OFN_OVERWRITEPROMPT;
1920 // ofn.nFileOffset=0;
1921 // ofn.nFileExtension=0;
1922 ofn.lpstrDefExt=TEXT("sif");
1923 // ofn.lCustData = 0l;
1925 // ofn.lpTemplateName=NULL;
1927 CHAR szFilename[MAX_PATH];
1929 strcpy(szFilename,filename.c_str());
1930 strcpy(szTitle,title.c_str());
1932 ofn.lpstrFile=szFilename;
1933 ofn.lpstrFileTitle=szTitle;
1935 if(GetSaveFileName(&ofn))
1937 filename=szFilename;
1938 _preferences.set_value(preference,dirname(filename));
1943 synfig::String prev_path;
1945 if(!_preferences.get_value(preference, prev_path))
1948 prev_path = absolute_path(prev_path);
1950 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1952 dialog->set_current_folder(prev_path);
1953 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1954 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1956 Widget_Enum *file_type_enum = 0;
1957 if (preference == ANIMATION_DIR_PREFERENCE)
1959 file_type_enum = manage(new Widget_Enum());
1960 file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
1961 .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
1962 .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
1963 .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
1964 file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
1966 Gtk::HBox *hbox = manage(new Gtk::HBox);
1967 hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
1968 hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
1971 dialog->set_extra_widget(*hbox);
1974 if (filename.empty())
1975 dialog->set_filename(prev_path);
1978 std::string full_path;
1979 if (is_absolute_path(filename))
1980 full_path = filename;
1982 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1984 // select the file if it exists
1985 dialog->set_filename(full_path);
1987 // if the file doesn't exist, put its name into the filename box
1989 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1990 dialog->set_current_name(basename(filename));
1993 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1994 if (preference == ANIMATION_DIR_PREFERENCE)
1995 set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
1996 filename = dialog->get_filename();
1997 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
1998 _preferences.set_value(preference, dirname(filename));
2009 App::dialog_error_blocking(const std::string &title, const std::string &message)
2011 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2012 dialog.set_title(title);
2018 App::dialog_warning_blocking(const std::string &title, const std::string &message)
2020 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
2021 dialog.set_title(title);
2027 App::dialog_yes_no(const std::string &title, const std::string &message)
2032 true // use_separator
2034 Gtk::Label label(message);
2037 dialog.get_vbox()->pack_start(label);
2038 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2039 dialog.add_button(Gtk::StockID("gtk-no"),0);
2041 return dialog.run();
2045 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
2050 true // use_separator
2052 Gtk::Label label(message);
2055 dialog.get_vbox()->pack_start(label);
2056 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2057 dialog.add_button(Gtk::StockID("gtk-no"),0);
2058 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
2060 return dialog.run();
2064 App::dialog_not_implemented()
2066 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2067 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
2072 try_open_url(const std::string &url)
2075 return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
2077 gchar* argv[3] = {strdup(App::browser_command.c_str()), strdup(url.c_str()), NULL};
2079 GError* gerror = NULL;
2081 retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &gerror);
2087 error(_("Could not execute specified web browser: %s"), gerror->message);
2088 g_error_free(gerror);
2099 if (!try_open_url("http://synfig.org/Documentation"))
2101 Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
2102 dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
2103 dialog.set_title(_("Help"));
2109 App::open_url(const std::string &url)
2115 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
2120 true // use_separator
2122 Gtk::Label label(message);
2124 dialog.get_vbox()->pack_start(label);
2127 entry.set_text(text);
2129 entry.set_activates_default(true);
2130 dialog.get_vbox()->pack_start(entry);
2132 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
2133 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
2134 dialog.set_default_response(Gtk::RESPONSE_OK);
2135 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
2138 if(dialog.run()!=Gtk::RESPONSE_OK)
2141 text=entry.get_text();
2150 App::open(std::string filename)
2152 return open_as(filename,filename);
2155 // this is called from autorecover.cpp:
2156 // App::open_as(get_shadow_file_name(filename),filename)
2157 // other than that, 'filename' and 'as' are the same
2159 App::open_as(std::string filename,std::string as)
2162 char long_name[1024];
2163 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2169 OneMoment one_moment;
2171 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2172 if(canvas && get_instance(canvas))
2174 get_instance(canvas)->find_canvas_view(canvas)->present();
2175 info("%s is already open", filename.c_str());
2176 // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2181 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2183 add_recent_file(as);
2185 handle<Instance> instance(Instance::create(canvas));
2188 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2190 set_recent_file_window_size(instance);
2194 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)")))
2195 instance->dialog_cvs_update();
2200 dialog_error_blocking(_("Error"), x);
2205 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2216 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2218 String file_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
2219 canvas->set_name(file_name);
2220 file_name += ".sifz";
2222 canvas->rend_desc().set_frame_rate(24.0);
2223 canvas->rend_desc().set_time_start(0.0);
2224 canvas->rend_desc().set_time_end(5.0);
2225 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2226 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2227 canvas->rend_desc().set_tl(Vector(-4,2.25));
2228 canvas->rend_desc().set_br(Vector(4,-2.25));
2229 canvas->rend_desc().set_w(480);
2230 canvas->rend_desc().set_h(270);
2231 canvas->rend_desc().set_antialias(1);
2232 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2233 canvas->set_file_name(file_name);
2235 handle<Instance> instance = Instance::create(canvas);
2237 if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
2238 instance->find_canvas_view(canvas)->canvas_properties.present();
2242 App::dialog_open(string filename)
2244 if (filename.empty())
2247 while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
2249 // If the filename still has wildcards, then we should
2250 // continue looking for the file we want
2251 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2257 get_ui_interface()->error(_("Unable to open file"));
2262 App::set_selected_instance(etl::loose_handle<Instance> instance)
2264 /* if(get_selected_instance()==instance)
2266 selected_instance=instance;
2267 signal_instance_selected()(instance);
2273 selected_instance=instance;
2274 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2278 instance->focus(instance->get_canvas());
2281 set_selected_canvas_view(0);
2283 signal_instance_selected()(instance);
2287 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2289 selected_canvas_view=canvas_view;
2290 signal_canvas_view_focus()(selected_canvas_view);
2293 selected_instance=canvas_view->get_instance();
2294 signal_instance_selected()(canvas_view->get_instance());
2297 if(get_selected_canvas_view()==canvas_view)
2299 signal_canvas_view_focus()(selected_canvas_view);
2300 signal_instance_selected()(canvas_view->get_instance());
2303 selected_canvas_view=canvas_view;
2304 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2305 set_selected_instance(canvas_view->get_instance());
2306 signal_canvas_view_focus()(selected_canvas_view);
2310 etl::loose_handle<Instance>
2311 App::get_instance(etl::handle<synfig::Canvas> canvas)
2313 if(!canvas) return 0;
2314 canvas=canvas->get_root();
2316 std::list<etl::handle<Instance> >::iterator iter;
2317 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2319 if((*iter)->get_canvas()==canvas)
2335 if(selected_instance)
2336 selected_instance->undo();
2342 if(selected_instance)
2343 selected_instance->redo();
2347 studio::App::get_base_path()
2349 return app_base_path_;