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
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
38 #ifdef HAVE_SYS_ERRNO_H
39 #include <sys/errno.h>
41 #include <gtkmm/fileselection.h>
42 #include <gtkmm/dialog.h>
43 #include <gtkmm/messagedialog.h>
44 #include <gtkmm/label.h>
45 #include <gtkmm/stock.h>
46 #include <gtkmm/stockitem.h>
47 #include <gtkmm/iconsource.h>
48 #include <gtkmm/inputdialog.h>
49 #include <gtkmm/accelmap.h>
50 #include <gtkmm/uimanager.h>
54 #include <gdkmm/general.h>
56 #include <synfig/loadcanvas.h>
57 #include <synfig/savecanvas.h>
63 #include "canvasview.h"
64 #include "dialog_setup.h"
65 #include "dialog_gradient.h"
66 #include "dialog_color.h"
69 #include "onemoment.h"
71 #include "dockmanager.h"
73 #include "state_eyedrop.h"
74 #include "state_normal.h"
75 #include "state_draw.h"
76 #include "state_fill.h"
77 #include "state_bline.h"
78 #include "state_polygon.h"
79 #include "state_sketch.h"
80 #include "state_gradient.h"
81 #include "state_circle.h"
82 #include "state_rectangle.h"
83 #include "state_smoothmove.h"
84 #include "state_scale.h"
85 #include "state_width.h"
86 #include "state_rotate.h"
87 #include "state_zoom.h"
89 #include "devicetracker.h"
90 #include "dialog_tooloptions.h"
91 #include "widget_enum.h"
93 #include "autorecover.h"
95 #include <synfigapp/settings.h>
96 #include "dock_history.h"
97 #include "dock_canvases.h"
98 #include "dock_keyframes.h"
99 #include "dock_layers.h"
100 #include "dock_params.h"
101 #include "dock_metadata.h"
102 #include "dock_children.h"
103 #include "dock_info.h"
104 #include "dock_navigator.h"
105 #include "dock_layergroups.h"
106 #include "dock_timetrack.h"
107 #include "dock_curves.h"
109 #include "mod_palette/mod_palette.h"
110 #include "mod_mirror/mod_mirror.h"
112 #include <sys/stat.h>
118 #include "statemanager.h"
125 #define _WIN32_WINNT 0x0500
128 #include <gtkmm/accelmap.h>
129 #include <gtkmm/filechooser.h>
130 #include <gtkmm/filechooserdialog.h>
136 /* === U S I N G =========================================================== */
140 using namespace synfig;
141 using namespace studio;
143 /* === M A C R O S ========================================================= */
145 #ifndef SYNFIG_USER_APP_DIR
147 #define SYNFIG_USER_APP_DIR "Library/Synfig"
148 #elif defined(_WIN32)
149 #define SYNFIG_USER_APP_DIR "Synfig"
151 #define SYNFIG_USER_APP_DIR ".synfig"
156 #define DPM2DPI(x) (float(x)/39.3700787402f)
157 #define DPI2DPM(x) (float(x)*39.3700787402f)
163 # define IMAGE_DIR "share\\pixmaps"
168 # define IMAGE_DIR "/usr/local/share/pixmaps"
172 # define IMAGE_EXT "tif"
175 #include <synfigapp/main.h>
177 /* === S I G N A L S ======================================================= */
179 static sigc::signal<void> signal_present_all_;
181 App::signal_present_all() { return signal_present_all_; }
183 static sigc::signal<void> signal_recent_files_changed_;
185 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
187 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
188 sigc::signal<void,etl::loose_handle<CanvasView> >&
189 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
191 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
192 sigc::signal<void,etl::handle<Instance> >&
193 App::signal_instance_selected() { return signal_instance_selected_; }
195 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
196 sigc::signal<void,etl::handle<Instance> >&
197 App::signal_instance_created() { return signal_instance_created_; }
199 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
200 sigc::signal<void,etl::handle<Instance> >&
201 App::signal_instance_deleted() { return signal_instance_deleted_; }
203 /* === G L O B A L S ======================================================= */
205 static std::list<std::string> recent_files;
206 const std::list<std::string>& App::get_recent_files() { return recent_files; }
208 static std::list<std::string> recent_files_window_size;
210 int App::Busy::count;
211 bool App::shutdown_in_progress;
213 synfig::Gamma App::gamma;
215 Glib::RefPtr<studio::UIManager> App::ui_manager_;
217 synfig::Distance::System App::distance_system;
219 studio::Dialog_Setup* App::dialog_setup;
221 etl::handle< studio::ModPalette > mod_palette_;
222 //studio::Dialog_Palette* App::dialog_palette;
224 std::list<etl::handle<Instance> > App::instance_list;
226 static etl::handle<synfigapp::UIInterface> ui_interface_;
227 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
229 etl::handle<Instance> App::selected_instance;
230 etl::handle<CanvasView> App::selected_canvas_view;
232 studio::About *studio::App::about=NULL;
234 studio::Toolbox *studio::App::toolbox=NULL;
236 studio::AutoRecover *studio::App::auto_recover=NULL;
238 studio::IPC *ipc=NULL;
240 studio::DockManager* studio::App::dock_manager=0;
242 studio::DeviceTracker* studio::App::device_tracker=0;
244 studio::Dialog_Gradient* studio::App::dialog_gradient;
246 studio::Dialog_Color* studio::App::dialog_color;
248 Gtk::InputDialog* studio::App::dialog_input;
250 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
252 studio::Dock_History* dock_history;
253 studio::Dock_Canvases* dock_canvases;
254 studio::Dock_Keyframes* dock_keyframes;
255 studio::Dock_Layers* dock_layers;
256 studio::Dock_Params* dock_params;
257 studio::Dock_MetaData* dock_meta_data;
258 studio::Dock_Children* dock_children;
259 studio::Dock_Info* dock_info;
260 studio::Dock_LayerGroups* dock_layer_groups;
261 studio::Dock_Navigator* dock_navigator;
262 studio::Dock_Timetrack* dock_timetrack;
263 studio::Dock_Curves* dock_curves;
265 std::list< etl::handle< studio::Module > > module_list_;
267 bool studio::App::use_colorspace_gamma=true;
268 #ifdef SINGLE_THREADED
269 bool studio::App::single_threaded=false;
271 bool studio::App::restrict_radius_ducks=false;
272 String studio::App::browser_command("firefox");
274 static int max_recent_files_=25;
275 int studio::App::get_max_recent_files() { return max_recent_files_; }
276 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
278 static synfig::String app_base_path_;
283 really_delete_widget(Gtk::Widget *widget)
285 // synfig::info("really delete %p", (void*)widget);
290 // nasty workaround - when we've finished with a popup menu, we want to delete it
291 // attaching to the signal_hide() signal gets us here before the action on the menu has run,
292 // so schedule the real delete to happen in 50ms, giving the action a chance to run
294 delete_widget(Gtk::Widget *widget)
296 // synfig::info("delete %p", (void*)widget);
297 Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
300 }; // END of namespace studio
301 studio::StateManager* state_manager;
306 class GlobalUIInterface : public synfigapp::UIInterface
310 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
315 true // use_separator
317 Gtk::Label label(message);
320 dialog.get_vbox()->pack_start(label);
321 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
322 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
324 dialog.set_default_response(dflt);
326 return (Response)dialog.run();
328 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
333 true // use_separator
335 Gtk::Label label(message);
338 dialog.get_vbox()->pack_start(label);
339 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
340 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
341 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
343 dialog.set_default_response(dflt);
345 return (Response)dialog.run();
347 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
352 true // use_separator
354 Gtk::Label label(message);
357 dialog.get_vbox()->pack_start(label);
358 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
359 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
361 dialog.set_default_response(dflt);
363 return (Response)dialog.run();
367 task(const std::string &task)
369 std::cerr<<task<<std::endl;
370 while(studio::App::events_pending())studio::App::iteration(false);
375 error(const std::string &err)
377 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
384 warning(const std::string &err)
386 std::cerr<<"warning: "<<err<<std::endl;
387 while(studio::App::events_pending())studio::App::iteration(false);
392 amount_complete(int /*current*/, int /*total*/)
394 while(studio::App::events_pending())studio::App::iteration(false);
399 /* === P R O C E D U R E S ================================================= */
403 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
405 action_group_list.push_back(action_group);
406 Gtk::UIManager::insert_action_group(action_group, pos);
410 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
412 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
413 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
414 if(*iter==action_group)
416 action_group_list.erase(iter);
417 Gtk::UIManager::remove_action_group(action_group);
420 synfig::error("Unable to find action group");
424 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
426 ui_manager->insert_action_group(group,0);
428 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
429 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
431 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
433 if(*iter && (*iter)->get_name()!="menus")
435 synfig::info("Removing action group "+(*iter)->get_name());
436 ui_manager->remove_action_group(*iter);
439 ui_manager->insert_action_group(group,0);
441 for(;!prev_groups.empty();prev_groups.pop_front())
443 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
444 ui_manager->insert_action_group(prev_groups.front(),1);
448 class Preferences : public synfigapp::Settings
451 virtual bool get_value(const synfig::String& key, synfig::String& value)const
455 value=strprintf("%f %f %f %f",
456 App::gamma.get_gamma_r(),
457 App::gamma.get_gamma_g(),
458 App::gamma.get_gamma_b(),
459 App::gamma.get_black_level()
463 if(key=="time_format")
465 value=strprintf("%i",App::get_time_format());
468 if(key=="file_history.size")
470 value=strprintf("%i",App::get_max_recent_files());
473 if(key=="use_colorspace_gamma")
475 value=strprintf("%i",(int)App::use_colorspace_gamma);
478 if(key=="distance_system")
480 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
483 #ifdef SINGLE_THREADED
484 if(key=="single_threaded")
486 value=strprintf("%i",(int)App::single_threaded);
490 if(key=="auto_recover_backup_interval")
492 value=strprintf("%i",App::auto_recover->get_timeout());
495 if(key=="restrict_radius_ducks")
497 value=strprintf("%i",(int)App::restrict_radius_ducks);
500 if(key=="browser_command")
502 value=App::browser_command;
506 return synfigapp::Settings::get_value(key,value);
509 virtual bool set_value(const synfig::String& key,const synfig::String& value)
515 strscanf(value,"%f %f %f %f",
522 App::gamma.set_all(r,g,b,blk);
526 if(key=="time_format")
528 int i(atoi(value.c_str()));
529 App::set_time_format(static_cast<synfig::Time::Format>(i));
532 if(key=="auto_recover_backup_interval")
534 int i(atoi(value.c_str()));
535 App::auto_recover->set_timeout(i);
538 if(key=="file_history.size")
540 int i(atoi(value.c_str()));
541 App::set_max_recent_files(i);
544 if(key=="use_colorspace_gamma")
546 int i(atoi(value.c_str()));
547 App::use_colorspace_gamma=i;
550 if(key=="distance_system")
552 App::distance_system=Distance::ident_system(value);;
555 #ifdef SINGLE_THREADED
556 if(key=="single_threaded")
558 int i(atoi(value.c_str()));
559 App::single_threaded=i;
563 if(key=="restrict_radius_ducks")
565 int i(atoi(value.c_str()));
566 App::restrict_radius_ducks=i;
569 if(key=="browser_command")
571 App::browser_command=value;
575 return synfigapp::Settings::set_value(key,value);
578 virtual KeyList get_key_list()const
580 KeyList ret(synfigapp::Settings::get_key_list());
581 ret.push_back("gamma");
582 ret.push_back("time_format");
583 ret.push_back("distance_system");
584 ret.push_back("file_history.size");
585 ret.push_back("use_colorspace_gamma");
586 #ifdef SINGLE_THREADED
587 ret.push_back("single_threaded");
589 ret.push_back("auto_recover_backup_interval");
590 ret.push_back("restrict_radius_ducks");
591 ret.push_back("browser_command");
596 static ::Preferences _preferences;
601 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
603 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
605 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
607 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
608 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
609 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
610 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
611 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
612 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
613 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
614 menus_action_group->add( Gtk::Action::create("menu-lowres-pixel", _("Low-Res Pixel Size")) );
615 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
616 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
617 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
618 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
619 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
621 // Add the synfigapp actions...
622 synfigapp::Action::Book::iterator iter;
623 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
625 actions_action_group->add(Gtk::Action::create(
626 "action-"+iter->second.name,
627 get_action_stock_id(iter->second),
628 iter->second.local_name,iter->second.local_name
632 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
633 #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); }
634 #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); }
636 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
637 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
638 DEFINE_ACTION("new", Gtk::Stock::NEW);
639 DEFINE_ACTION("open", Gtk::Stock::OPEN);
640 DEFINE_ACTION("save", Gtk::Stock::SAVE);
641 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
642 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
643 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
644 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
645 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
646 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
647 DEFINE_ACTION("import", _("Import"));
648 DEFINE_ACTION("render", _("Render"));
649 DEFINE_ACTION("preview", _("Preview"));
650 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
651 DEFINE_ACTION("sound", _("Sound File"));
652 DEFINE_ACTION("options", _("Options"));
653 DEFINE_ACTION("close", _("Close View"));
654 DEFINE_ACTION("close-document", _("Close Document"));
655 DEFINE_ACTION("quit", Gtk::Stock::QUIT);
658 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
659 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
660 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
661 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
662 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
663 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
664 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
665 DEFINE_ACTION("properties", _("Properties"));
667 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
668 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
669 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
670 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
671 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
672 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
673 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
674 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
675 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
676 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
677 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
678 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
679 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
680 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
681 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
682 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
683 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
684 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
685 DEFINE_ACTION(strprintf("lowres-pixel-%d", *iter), strprintf(_("Set Low-Res pixel size to %d"), *iter));
686 DEFINE_ACTION("play", _("Play"));
687 // DEFINE_ACTION("pause", _("Pause"));
688 DEFINE_ACTION("stop", _("Stop"));
689 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
690 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
691 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
692 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
693 DEFINE_ACTION("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size"));
694 DEFINE_ACTION("increase-low-res-pixel-size", _("Increase Low-Res Pixel Size"));
695 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
696 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
697 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
698 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
699 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
700 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
701 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
702 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
703 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
704 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
705 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
706 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
707 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
708 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
709 DEFINE_ACTION("seek-end", _("Seek to End"));
711 DEFINE_ACTION("action-group_add", _("Add group"));
713 DEFINE_ACTION("canvas-new", _("New Canvas"));
715 DEFINE_ACTION("amount-inc", _("Increase Amount"));
716 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
721 // Set up synfigapp actions
723 synfigapp::Action::Book::iterator iter;
725 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
727 Gtk::StockID stock_id;
729 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
731 //Gtk::Image* image(manage(new Gtk::Image()));
732 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
733 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
734 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
735 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
736 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
737 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
738 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
739 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
740 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
741 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
743 actions_action_group->add(Gtk::Action::create(
744 "action-"+iter->second.name,
746 iter->second.local_name,iter->second.local_name
754 Glib::ustring ui_info =
756 " <popup name='menu-toolbox' action='menu-toolbox'>"
757 " <menu action='menu-file'>"
760 " <popup name='menu-main' action='menu-main'>"
761 " <menu action='menu-file'>"
762 " <menuitem action='new' />"
763 " <menuitem action='open' />"
764 " <menuitem action='save' />"
765 " <menuitem action='save-as' />"
766 " <menuitem action='revert' />"
767 " <separator name='bleh01'/>"
768 " <menuitem action='cvs-add' />"
769 " <menuitem action='cvs-update' />"
770 " <menuitem action='cvs-commit' />"
771 " <menuitem action='cvs-revert' />"
772 " <separator name='bleh02'/>"
773 " <menuitem action='import' />"
774 " <separator name='bleh03'/>"
775 " <menuitem action='render' />"
776 " <menuitem action='preview' />"
777 " <menuitem action='sound' />"
778 " <separator name='bleh04'/>"
779 " <menuitem action='options' />"
780 " <menuitem action='close' />"
781 " <menuitem action='close-document' />"
782 " <menuitem action='quit' />"
784 " <menu action='menu-edit'>"
785 " <menuitem action='undo'/>"
786 " <menuitem action='redo'/>"
787 " <separator name='bleh05'/>"
788 " <menuitem action='cut'/>"
789 " <menuitem action='copy'/>"
790 " <menuitem action='paste'/>"
791 " <separator name='bleh06'/>"
792 " <menuitem action='select-all-ducks'/>"
793 " <menuitem action='unselect-all-layers'/>"
794 " <separator name='bleh07'/>"
795 " <menuitem action='properties'/>"
797 " <menu action='menu-view'>"
798 " <menu action='menu-duck-mask'>"
799 " <menuitem action='mask-position-ducks' />"
800 " <menuitem action='mask-vertex-ducks' />"
801 " <menuitem action='mask-tangent-ducks' />"
802 " <menuitem action='mask-radius-ducks' />"
803 " <menuitem action='mask-width-ducks' />"
804 " <menuitem action='mask-angle-ducks' />"
806 " <menu action='menu-preview-quality'>"
807 " <menuitem action='quality-00' />"
808 " <menuitem action='quality-01' />"
809 " <menuitem action='quality-02' />"
810 " <menuitem action='quality-03' />"
811 " <menuitem action='quality-04' />"
812 " <menuitem action='quality-05' />"
813 " <menuitem action='quality-06' />"
814 " <menuitem action='quality-07' />"
815 " <menuitem action='quality-08' />"
816 " <menuitem action='quality-09' />"
817 " <menuitem action='quality-10' />"
819 " <menu action='menu-lowres-pixel'>"
820 " <menuitem action='decrease-low-res-pixel-size'/>"
821 " <menuitem action='increase-low-res-pixel-size'/>"
822 " <separator name='pixel-size-separator'/>"
825 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
826 ui_info += strprintf(" <menuitem action='lowres-pixel-%d' />", *iter);
830 " <separator name='bleh08'/>"
831 " <menuitem action='play'/>"
832 //" <menuitem action='pause'/>"
833 " <menuitem action='stop'/>"
834 " <menuitem action='dialog-flipbook'/>"
835 " <separator name='bleh09'/>"
836 " <menuitem action='toggle-grid-show'/>"
837 " <menuitem action='toggle-grid-snap'/>"
838 " <menuitem action='toggle-guide-show'/>"
839 " <menuitem action='toggle-low-res'/>"
840 " <menuitem action='toggle-onion-skin'/>"
841 " <separator name='bleh10'/>"
842 " <menuitem action='canvas-zoom-in'/>"
843 " <menuitem action='canvas-zoom-out'/>"
844 " <menuitem action='canvas-zoom-fit'/>"
845 " <menuitem action='canvas-zoom-100'/>"
846 " <separator name='bleh11'/>"
847 " <menuitem action='time-zoom-in'/>"
848 " <menuitem action='time-zoom-out'/>"
849 " <separator name='bleh12'/>"
850 " <menuitem action='jump-next-keyframe'/>"
851 " <menuitem action='jump-prev-keyframe'/>"
852 " <menuitem action='seek-next-frame'/>"
853 " <menuitem action='seek-prev-frame'/>"
854 " <menuitem action='seek-next-second'/>"
855 " <menuitem action='seek-prev-second'/>"
856 " <menuitem action='seek-begin'/>"
857 " <menuitem action='seek-end'/>"
859 " <menu action='menu-canvas'>"
860 " <menuitem action='canvas-new'/>"
862 " <menu name='menu-state' action='menu-state'>"
864 " <menu action='menu-group'>"
865 " <menuitem action='action-group_add'/>"
867 " <menu action='menu-layer'>"
868 //" <menuitem action='cut'/>"
869 //" <menuitem action='copy'/>"
870 //" <menuitem action='paste'/>"
871 //" <separator name='bleh06'/>"
872 " <menu action='menu-layer-new'></menu>"
873 " <menuitem action='amount-inc'/>"
874 " <menuitem action='amount-dec'/>"
876 " <menu action='menu-keyframe'>"
877 " <menuitem action='keyframe-properties'/>"
884 " <menubar name='MenuBar'>"
885 " <menu action='MenuFile'>"
886 " <menuitem action='New'/>"
887 " <menuitem action='Open'/>"
889 " <menuitem action='Quit'/>"
891 " <menu action='MenuEdit'>"
892 " <menuitem action='Cut'/>"
893 " <menuitem action='Copy'/>"
894 " <menuitem action='Paste'/>"
897 " <toolbar name='ToolBar'>"
898 " <toolitem action='Open'/>"
899 " <toolitem action='Quit'/>"
905 actions_action_group->set_sensitive(false);
906 App::ui_manager()->set_add_tearoffs(true);
907 App::ui_manager()->insert_action_group(menus_action_group,1);
908 App::ui_manager()->insert_action_group(actions_action_group,1);
909 App::ui_manager()->add_ui_from_string(ui_info);
911 //App::ui_manager()->get_accel_group()->unlock();
913 catch(const Glib::Error& ex)
915 synfig::error("building menus and toolbars failed: " + ex.what());
918 // Add default keyboard accelerators
919 #define ACCEL(path,accel) \
921 Gtk::AccelKey accel_key(accel,path); \
922 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
925 #define ACCEL2(accel) \
927 Gtk::AccelKey accel_key(accel); \
928 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
931 ACCEL("<Actions>//select-all-ducks","<Control>a");
932 ACCEL("<Actions>//unselect-all-layers","<Control>d");
933 ACCEL("<Actions>//render","F9");
934 ACCEL("<Actions>//preview","F11");
935 ACCEL("<Actions>//properties","F8");
936 ACCEL("<Actions>//options","F12");
937 ACCEL("<Actions>//import","<control>i");
938 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
939 ACCEL("<Actions>//toggle-grid-show","<Control>g");
940 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
941 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
942 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
943 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
944 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
945 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
946 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
947 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
949 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
950 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
952 ACCEL("<Actions>//quality-01","<Control>1");
953 ACCEL("<Actions>//quality-02","<Control>2");
954 ACCEL("<Actions>//quality-03","<Control>3");
955 ACCEL("<Actions>//quality-04","<Control>4");
956 ACCEL("<Actions>//quality-05","<Control>5");
957 ACCEL("<Actions>//quality-06","<Control>6");
958 ACCEL("<Actions>//quality-07","<Control>7");
959 ACCEL("<Actions>//quality-08","<Control>8");
960 ACCEL("<Actions>//quality-09","<Control>9");
961 ACCEL("<Actions>//quality-10","<Control>0");
962 ACCEL("<Actions>//undo","<Control>z");
963 ACCEL("<Actions>//redo","<Control>r");
964 ACCEL("<Actions>//action-layer_remove","Delete");
966 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
967 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
968 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
969 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
970 ACCEL("<Actions>//time-zoom-in","+");
971 ACCEL("<Actions>//time-zoom-out","_");
973 ACCEL2(Gtk::AccelKey('(',Gdk::CONTROL_MASK,"<Actions>//decrease-low-res-pixel-size"));
974 ACCEL2(Gtk::AccelKey(')',Gdk::CONTROL_MASK,"<Actions>//increase-low-res-pixel-size"));
976 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
977 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
979 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
980 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
981 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
982 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
983 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
984 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
985 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
986 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
987 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
988 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
989 ACCEL2(Gtk::AccelKey('o',Gdk::MOD1_MASK,"<Actions>//toggle-onion-skin"));
990 ACCEL("<Actions>//play", "<Control>p");
991 ACCEL("<Actions>//seek-begin","Home");
992 ACCEL("<Actions>//seek-end","End");
994 ACCEL("<Actions>//state-normal", "<Mod1>a");
995 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
996 ACCEL("<Actions>//state-scale", "<Mod1>d");
997 ACCEL("<Actions>//state-rotate", "<Mod1>s");
999 ACCEL("<Actions>//state-bline", "<Mod1>b");
1000 ACCEL("<Actions>//state-circle", "<Mod1>c");
1001 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
1002 ACCEL("<Actions>//state-gradient", "<Mod1>g");
1004 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
1005 ACCEL("<Actions>//state-fill", "<Mod1>f");
1006 ACCEL("<Actions>//state-zoom", "<Mod1>z");
1007 ACCEL("<Actions>//state-polygon", "<Mod1>p");
1009 ACCEL("<Actions>//state-draw", "<Mod1>w");
1010 ACCEL("<Actions>//state-sketch", "<Mod1>k");
1011 ACCEL("<Actions>//state-width", "<Mod1>t");
1012 ACCEL("<Actions>//state-mirror", "<Mod1>m");
1014 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1020 #define mkdir(x,y) mkdir(x)
1023 /* === M E T H O D S ======================================================= */
1025 App::App(int *argc, char ***argv):
1026 Gtk::Main(argc,argv),
1027 IconController(etl::dirname((*argv)[0]))
1029 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1032 ui_interface_=new GlobalUIInterface();
1036 // don't call thread_init() if threads are already initialized
1037 // on some machines bonobo_init() initialized threads before we get here
1038 if (!g_thread_supported())
1039 Glib::thread_init();
1041 distance_system=Distance::SYSTEM_UNITS;
1043 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1046 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1050 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1056 if(!SYNFIG_CHECK_VERSION())
1058 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1059 dialog_error_blocking("Synfig Studio",
1060 "This copy of Synfig Studio was compiled against a\n"
1061 "different version of libsynfig than what is currently\n"
1062 "installed. Synfig Studio will now abort. Try downloading\n"
1063 "the latest version from the Synfig website at\n"
1064 "http://synfig.org/Download"
1068 Glib::set_application_name(_("Synfig Studio"));
1070 Splash splash_screen;
1071 splash_screen.set_can_self_destruct(false);
1072 splash_screen.show();
1074 shutdown_in_progress=false;
1075 SuperCallback synfig_init_cb(splash_screen.get_callback(),0,9000,10000);
1076 SuperCallback studio_init_cb(splash_screen.get_callback(),9000,10000,10000);
1078 // Initialize the Synfig library
1079 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1082 get_ui_interface()->error(_("Failed to initialize synfig!"));
1086 // add the preferences to the settings
1087 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1091 studio_init_cb.task(_("Init UI Manager..."));
1092 App::ui_manager_=studio::UIManager::create();
1095 studio_init_cb.task(_("Init Dock Manager..."));
1096 dock_manager=new studio::DockManager();
1098 studio_init_cb.task(_("Init State Manager..."));
1099 state_manager=new StateManager();
1101 studio_init_cb.task(_("Init Toolbox..."));
1102 toolbox=new studio::Toolbox();
1104 studio_init_cb.task(_("Init About Dialog..."));
1105 about=new studio::About();
1107 studio_init_cb.task(_("Init Tool Options..."));
1108 dialog_tool_options=new studio::Dialog_ToolOptions();
1109 dock_manager->register_dockable(*dialog_tool_options);
1111 studio_init_cb.task(_("Init History..."));
1112 dock_history=new studio::Dock_History();
1113 dock_manager->register_dockable(*dock_history);
1115 studio_init_cb.task(_("Init Canvases..."));
1116 dock_canvases=new studio::Dock_Canvases();
1117 dock_manager->register_dockable(*dock_canvases);
1119 studio_init_cb.task(_("Init Keyframes..."));
1120 dock_keyframes=new studio::Dock_Keyframes();
1121 dock_manager->register_dockable(*dock_keyframes);
1123 studio_init_cb.task(_("Init Layers..."));
1124 dock_layers=new studio::Dock_Layers();
1125 dock_manager->register_dockable(*dock_layers);
1127 studio_init_cb.task(_("Init Params..."));
1128 dock_params=new studio::Dock_Params();
1129 dock_manager->register_dockable(*dock_params);
1131 studio_init_cb.task(_("Init MetaData..."));
1132 dock_meta_data=new studio::Dock_MetaData();
1133 dock_manager->register_dockable(*dock_meta_data);
1135 studio_init_cb.task(_("Init Children..."));
1136 dock_children=new studio::Dock_Children();
1137 dock_manager->register_dockable(*dock_children);
1139 studio_init_cb.task(_("Init Info..."));
1140 dock_info = new studio::Dock_Info();
1141 dock_manager->register_dockable(*dock_info);
1143 studio_init_cb.task(_("Init Navigator..."));
1144 dock_navigator = new studio::Dock_Navigator();
1145 dock_manager->register_dockable(*dock_navigator);
1147 studio_init_cb.task(_("Init Timetrack..."));
1148 dock_timetrack = new studio::Dock_Timetrack();
1149 dock_manager->register_dockable(*dock_timetrack);
1151 studio_init_cb.task(_("Init Curve Editor..."));
1152 dock_curves = new studio::Dock_Curves();
1153 dock_manager->register_dockable(*dock_curves);
1155 studio_init_cb.task(_("Init Layer Groups..."));
1156 dock_layer_groups = new studio::Dock_LayerGroups();
1157 dock_manager->register_dockable(*dock_layer_groups);
1160 studio_init_cb.task(_("Init Color Dialog..."));
1161 dialog_color=new studio::Dialog_Color();
1163 studio_init_cb.task(_("Init Gradient Dialog..."));
1164 dialog_gradient=new studio::Dialog_Gradient();
1166 studio_init_cb.task(_("Init DeviceTracker..."));
1167 device_tracker=new studio::DeviceTracker();
1169 studio_init_cb.task(_("Init Tools..."));
1172 state_manager->add_state(&state_normal);
1173 state_manager->add_state(&state_smooth_move);
1174 state_manager->add_state(&state_scale);
1175 state_manager->add_state(&state_rotate);
1176 studio_init_cb.task(_("Init ModMirror...")); module_list_.push_back(new ModMirror()); module_list_.back()->start();
1179 state_manager->add_state(&state_bline);
1180 state_manager->add_state(&state_circle);
1181 state_manager->add_state(&state_rectangle);
1182 state_manager->add_state(&state_gradient);
1183 if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks
1186 if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw); // Enabled for now. Let's see whether they're good enough yet.
1187 if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
1188 state_manager->add_state(&state_fill);
1189 state_manager->add_state(&state_eyedrop);
1190 state_manager->add_state(&state_zoom);
1192 // Disabled by default - it doesn't work properly?
1193 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1195 studio_init_cb.task(_("Init ModPalette..."));
1196 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1198 studio_init_cb.task(_("Init Setup Dialog..."));
1199 dialog_setup=new studio::Dialog_Setup();
1201 studio_init_cb.task(_("Init Input Dialog..."));
1202 dialog_input=new Gtk::InputDialog();
1203 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1204 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1206 studio_init_cb.task(_("Init auto recovery..."));
1207 auto_recover=new AutoRecover();
1209 studio_init_cb.amount_complete(9250,10000);
1210 studio_init_cb.task(_("Loading Settings..."));
1212 studio_init_cb.task(_("Checking auto-recover..."));
1214 studio_init_cb.amount_complete(9900,10000);
1216 bool opened_any = false;
1217 if(auto_recover->recovery_needed())
1219 splash_screen.hide();
1220 if (get_ui_interface()->yes_no(_("Auto Recovery"),
1221 _("Synfig Studio seems to have crashed\n"
1222 "before you could save all your files.\n"
1223 "Would you like to re-open those files\n"
1224 "and recover your unsaved changes?")) ==
1225 synfigapp::UIInterface::RESPONSE_YES)
1227 int number_recovered;
1228 if(!auto_recover->recover(number_recovered))
1229 if (number_recovered)
1230 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1232 get_ui_interface()->error(_("Unable to recover from previous crash"));
1234 get_ui_interface()->error(
1235 _("Synfig Studio has attempted to recover\n"
1236 "from a previous crash. The files that it has\n"
1237 "recovered are NOT YET SAVED. It would be a good\n"
1238 "idea to review them and save them now."));
1240 if (number_recovered)
1243 splash_screen.show();
1246 // Look for any files given on the command line,
1247 // and load them if found.
1248 for(;*argc>=1;(*argc)--)
1249 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1251 studio_init_cb.task(_("Loading files..."));
1252 splash_screen.hide();
1253 open((*argv)[*argc]);
1255 splash_screen.show();
1258 // if no file was specified to be opened, create a new document to help new users get started more easily
1259 if (!opened_any && !getenv("SYNFIG_DISABLE_AUTOMATIC_DOCUMENT_CREATION"))
1262 studio_init_cb.task(_("Done."));
1263 studio_init_cb.amount_complete(10000,10000);
1269 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1273 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1277 StateManager* App::get_state_manager() { return state_manager; }
1281 shutdown_in_progress=true;
1285 synfigapp::Main::settings().remove_domain("pref");
1287 selected_instance=0;
1289 // Unload all of the modules
1290 for(;!module_list_.empty();module_list_.pop_back())
1293 delete state_manager;
1297 delete auto_recover;
1303 // studio::App::iteration(false);
1307 // studio::App::iteration(false);
1309 // studio::App::iteration(false);
1311 delete dialog_setup;
1313 delete dialog_gradient;
1315 delete dialog_color;
1317 delete dialog_input;
1319 delete dock_manager;
1321 instance_list.clear();
1323 // studio::App::iteration(false);
1327 App::get_user_app_directory()
1329 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1333 App::get_config_file(const synfig::String& file)
1335 return Glib::build_filename(get_user_app_directory(),file);
1338 #define SCALE_FACTOR (1280)
1339 //! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size
1341 App::set_recent_file_window_size(etl::handle<Instance> instance)
1343 int screen_w(Gdk::screen_width());
1344 int screen_h(Gdk::screen_height());
1346 const std::string &canvas_window_size = *recent_files_window_size.begin();
1348 if(canvas_window_size.empty())
1351 synfig::String::size_type current=0;
1353 while(current != synfig::String::npos)
1355 // find end of first field (canvas) or return
1356 synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
1357 if(separator == synfig::String::npos) return;
1360 synfig::Canvas::Handle canvas;
1362 canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current));
1364 catch(Exception::IDNotFound) {
1365 // can't find the canvas; skip to the next canvas or return
1366 separator = canvas_window_size.find_first_of('\t', current);
1367 if(separator == synfig::String::npos) return;
1368 current = separator+1;
1372 CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
1373 canvasview->present();
1375 // check that we have the tab character the ends this canvas' data or return
1376 current = separator+1;
1377 separator = canvas_window_size.find_first_of('\t', current);
1378 if(separator == synfig::String::npos) return;
1381 if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
1383 current = separator+1;
1387 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
1388 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
1389 x=x*screen_w/SCALE_FACTOR;
1390 y=y*screen_h/SCALE_FACTOR;
1391 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
1392 x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
1393 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
1394 y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
1395 canvasview->move(x,y);
1397 if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
1398 if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
1399 w=w*screen_w/SCALE_FACTOR;
1400 h=h*screen_h/SCALE_FACTOR;
1401 canvasview->set_default_size(w,h);
1402 canvasview->set_size_request(w,h);
1404 current = separator+1;
1409 App::add_recent_file(const etl::handle<Instance> instance)
1411 int screen_w(Gdk::screen_width());
1412 int screen_h(Gdk::screen_height());
1414 std::string canvas_window_size;
1416 const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
1417 Instance::CanvasViewList::const_iterator iter;
1419 for(iter=cview_list.begin();iter!=cview_list.end();iter++)
1421 if( !((*iter)->is_visible()) )
1424 etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
1425 int x_pos, y_pos, x_size, y_size;
1426 (*iter)->get_position(x_pos,y_pos);
1427 (*iter)->get_size(x_size,y_size);
1429 canvas_window_size += strprintf("%s %d %d %d %d\t",
1430 canvas->get_relative_id(canvas->get_root()).c_str(),
1431 x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h,
1432 x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
1435 add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
1440 App::add_recent_file(const std::string &file_name, const std::string &window_size)
1442 std::string filename(file_name);
1444 assert(!filename.empty());
1446 if(filename.empty())
1449 // Toss out any "hidden" files
1450 if(basename(filename)[0]=='.')
1453 // If we aren't an absolute path, turn ourselves into one
1454 if(!is_absolute_path(filename))
1455 filename=absolute_path(filename);
1457 std::string old_window_size;
1459 list<string>::iterator iter;
1460 list<string>::iterator iter_wsize;
1461 // Check to see if the file is already on the list.
1462 // If it is, then remove it from the list
1463 for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
1466 recent_files.erase(iter);
1467 old_window_size = *iter_wsize;
1468 recent_files_window_size.erase(iter_wsize);
1473 // Push the filename to the front of the list
1474 recent_files.push_front(filename);
1475 if(window_size.empty())
1476 recent_files_window_size.push_front(old_window_size);
1478 recent_files_window_size.push_front(window_size);
1480 // Clean out the files at the end of the list.
1481 while(recent_files.size()>(unsigned)get_max_recent_files())
1483 recent_files.pop_back();
1484 recent_files_window_size.pop_back();
1487 signal_recent_files_changed_();
1492 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1495 App::get_time_format()
1497 return _App_time_format;
1501 App::set_time_format(synfig::Time::Format x)
1508 App::save_settings()
1513 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1514 setlocale(LC_NUMERIC, "C");
1516 std::string filename=get_config_file("accelrc");
1517 Gtk::AccelMap::save(filename);
1520 std::string filename=get_config_file("recentfiles");
1522 std::ofstream file(filename.c_str());
1526 synfig::warning("Unable to save %s",filename.c_str());
1530 list<string>::reverse_iterator iter;
1532 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1536 std::string filename=get_config_file("recentfiles")+std::string("_window_size");
1538 std::ofstream file(filename.c_str());
1542 synfig::warning("Unable to save %s",filename.c_str());
1546 list<string>::reverse_iterator iter;
1548 for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
1552 std::string filename=get_config_file("settings");
1553 synfigapp::Main::settings().save_to_file(filename);
1554 setlocale(LC_NUMERIC,old_locale);
1558 synfig::warning("Caught exception when attempting to save settings.");
1563 App::load_settings()
1568 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1569 setlocale(LC_NUMERIC, "C");
1571 std::string filename=get_config_file("accelrc");
1572 Gtk::AccelMap::load(filename);
1575 bool window_size_broken = false;
1577 std::string filename=get_config_file("recentfiles");
1578 std::string filename_window_size=filename+std::string("_window_size");
1580 std::ifstream file(filename.c_str());
1581 std::ifstream file_window_size(filename_window_size.c_str());
1583 if(!file_window_size)
1584 window_size_broken = true;
1588 std::string recent_file;
1589 std::string recent_file_window_size;
1590 getline(file,recent_file);
1591 if(!window_size_broken)
1592 getline(file_window_size,recent_file_window_size);
1593 if(!recent_file.empty())
1595 if(!window_size_broken && !file_window_size)
1596 window_size_broken = true;
1597 if(!window_size_broken)
1598 add_recent_file(recent_file,recent_file_window_size);
1600 add_recent_file(recent_file);
1603 if(!window_size_broken && file_window_size)
1604 window_size_broken = true;
1606 if(window_size_broken)
1608 recent_files_window_size.clear();
1609 recent_files_window_size.resize(recent_files.size());
1612 std::string filename=get_config_file("settings");
1613 if(!synfigapp::Main::settings().load_from_file(filename))
1615 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1616 //if(!synfigapp::Main::settings().load_from_file(filename))
1618 gamma.set_gamma(1.0/2.2);
1619 reset_initial_window_configuration();
1622 setlocale(LC_NUMERIC,old_locale);
1626 synfig::warning("Caught exception when attempting to load settings.");
1631 App::reset_initial_window_configuration()
1633 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1634 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1635 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1636 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1637 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1638 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1639 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1640 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1641 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1642 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1643 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1644 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1645 #ifdef SINGLE_THREADED
1646 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1648 synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
1649 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1653 App::shutdown_request(GdkEventAny*)
1657 //return !shutdown_in_progress;
1663 if(shutdown_in_progress)return;
1666 get_ui_interface()->task(_("Quit Request"));
1669 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1673 std::list<etl::handle<Instance> >::iterator iter;
1674 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1676 if(!(*iter)->safe_close())
1680 if((*iter)->synfigapp::Instance::get_action_count())
1682 handle<synfigapp::UIInterface> uim;
1683 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1685 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1686 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1688 case synfigapp::UIInterface::RESPONSE_NO:
1690 case synfigapp::UIInterface::RESPONSE_YES:
1693 case synfigapp::UIInterface::RESPONSE_CANCEL:
1702 if((*iter)->synfigapp::Instance::is_modified())
1704 handle<synfigapp::UIInterface> uim;
1705 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1707 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() );
1708 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1710 case synfigapp::UIInterface::RESPONSE_NO:
1712 case synfigapp::UIInterface::RESPONSE_YES:
1713 (*iter)->dialog_cvs_commit();
1715 case synfigapp::UIInterface::RESPONSE_CANCEL:
1724 // This next line causes things to crash for some reason
1728 shutdown_in_progress=true;
1730 instance_list.clear();
1732 while(studio::App::events_pending())studio::App::iteration(false);
1735 auto_recover->normal_shutdown();
1737 get_ui_interface()->task(_("Quit Request sent"));
1743 dialog_setup->refresh();
1744 dialog_setup->show();
1747 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1748 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1751 //#define USE_WIN32_FILE_DIALOGS 1
1754 #ifdef USE_WIN32_FILE_DIALOGS
1755 static OPENFILENAME ofn={};
1759 #include <gdk/gdkwin32.h>
1763 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1765 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1767 #ifdef USE_WIN32_FILE_DIALOGS
1768 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1770 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1771 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1772 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1774 ofn.lStructSize=sizeof(OPENFILENAME);
1775 ofn.hwndOwner = hWnd;
1776 ofn.hInstance = hInstance;
1777 ofn.lpstrFilter = szFilter;
1778 // ofn.lpstrCustomFilter=NULL;
1779 // ofn.nMaxCustFilter=0;
1780 // ofn.nFilterIndex=0;
1781 // ofn.lpstrFile=NULL;
1782 ofn.nMaxFile=MAX_PATH;
1783 // ofn.lpstrFileTitle=NULL;
1784 // ofn.lpstrInitialDir=NULL;
1785 // ofn.lpstrTitle=NULL;
1786 ofn.Flags=OFN_HIDEREADONLY;
1787 // ofn.nFileOffset=0;
1788 // ofn.nFileExtension=0;
1789 ofn.lpstrDefExt=TEXT("sif");
1790 // ofn.lCustData = 0l;
1792 // ofn.lpTemplateName=NULL;
1794 CHAR szFilename[MAX_PATH];
1796 strcpy(szFilename,filename.c_str());
1797 strcpy(szTitle,title.c_str());
1799 ofn.lpstrFile=szFilename;
1800 ofn.lpstrFileTitle=szTitle;
1802 if(GetOpenFileName(&ofn))
1804 filename=szFilename;
1810 synfig::String prev_path;
1812 if(!_preferences.get_value(preference, prev_path))
1815 prev_path = absolute_path(prev_path);
1817 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1819 dialog->set_current_folder(prev_path);
1820 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1821 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1823 if (filename.empty())
1824 dialog->set_filename(prev_path);
1825 else if (is_absolute_path(filename))
1826 dialog->set_filename(filename);
1828 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1830 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1831 filename = dialog->get_filename();
1832 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1833 _preferences.set_value(preference, dirname(filename));
1847 GtkWidget *fileselection;
1848 fileselection = gtk_file_selection_new(title.c_str());
1851 if(basename(filename)==filename)
1853 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1856 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1858 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1860 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1861 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1863 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1864 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1866 gtk_widget_show(fileselection);
1874 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1875 _preferences.set_value(preference,dirname(filename));
1879 gtk_widget_destroy(fileselection);
1882 gtk_widget_destroy(fileselection);
1889 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1891 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1893 #if USE_WIN32_FILE_DIALOGS
1894 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1896 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1897 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1898 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1900 ofn.lStructSize=sizeof(OPENFILENAME);
1901 ofn.hwndOwner = hWnd;
1902 ofn.hInstance = hInstance;
1903 ofn.lpstrFilter = szFilter;
1904 // ofn.lpstrCustomFilter=NULL;
1905 // ofn.nMaxCustFilter=0;
1906 // ofn.nFilterIndex=0;
1907 // ofn.lpstrFile=NULL;
1908 ofn.nMaxFile=MAX_PATH;
1909 // ofn.lpstrFileTitle=NULL;
1910 // ofn.lpstrInitialDir=NULL;
1911 // ofn.lpstrTitle=NULL;
1912 ofn.Flags=OFN_OVERWRITEPROMPT;
1913 // ofn.nFileOffset=0;
1914 // ofn.nFileExtension=0;
1915 ofn.lpstrDefExt=TEXT("sif");
1916 // ofn.lCustData = 0l;
1918 // ofn.lpTemplateName=NULL;
1920 CHAR szFilename[MAX_PATH];
1922 strcpy(szFilename,filename.c_str());
1923 strcpy(szTitle,title.c_str());
1925 ofn.lpstrFile=szFilename;
1926 ofn.lpstrFileTitle=szTitle;
1928 if(GetSaveFileName(&ofn))
1930 filename=szFilename;
1931 _preferences.set_value(preference,dirname(filename));
1936 synfig::String prev_path;
1938 if(!_preferences.get_value(preference, prev_path))
1941 prev_path = absolute_path(prev_path);
1943 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1945 dialog->set_current_folder(prev_path);
1946 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1947 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1949 Widget_Enum *file_type_enum = 0;
1950 if (preference == ANIMATION_DIR_PREFERENCE)
1952 file_type_enum = manage(new Widget_Enum());
1953 file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
1954 .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
1955 .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
1956 .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
1957 file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
1959 Gtk::HBox *hbox = manage(new Gtk::HBox);
1960 hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
1961 hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
1964 dialog->set_extra_widget(*hbox);
1967 if (filename.empty())
1968 dialog->set_filename(prev_path);
1971 std::string full_path;
1972 if (is_absolute_path(filename))
1973 full_path = filename;
1975 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1977 // select the file if it exists
1978 dialog->set_filename(full_path);
1980 // if the file doesn't exist, put its name into the filename box
1982 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1983 dialog->set_current_name(basename(filename));
1986 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1987 if (preference == ANIMATION_DIR_PREFERENCE)
1988 set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
1989 filename = dialog->get_filename();
1990 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
1991 _preferences.set_value(preference, dirname(filename));
2002 App::dialog_error_blocking(const std::string &title, const std::string &message)
2004 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2005 dialog.set_title(title);
2011 App::dialog_warning_blocking(const std::string &title, const std::string &message)
2013 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
2014 dialog.set_title(title);
2020 App::dialog_yes_no(const std::string &title, const std::string &message)
2025 true // use_separator
2027 Gtk::Label label(message);
2030 dialog.get_vbox()->pack_start(label);
2031 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2032 dialog.add_button(Gtk::StockID("gtk-no"),0);
2034 return dialog.run();
2038 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
2043 true // use_separator
2045 Gtk::Label label(message);
2048 dialog.get_vbox()->pack_start(label);
2049 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2050 dialog.add_button(Gtk::StockID("gtk-no"),0);
2051 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
2053 return dialog.run();
2057 App::dialog_not_implemented()
2059 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2060 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
2065 try_open_url(const std::string &url)
2068 return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
2070 gchar* argv[3] = {strdup(App::browser_command.c_str()), strdup(url.c_str()), NULL};
2072 GError* gerror = NULL;
2074 retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &gerror);
2080 error(_("Could not execute specified web browser: %s"), gerror->message);
2081 g_error_free(gerror);
2092 if (!try_open_url("http://synfig.org/Documentation"))
2094 Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
2095 dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
2096 dialog.set_title(_("Help"));
2102 App::open_url(const std::string &url)
2108 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
2113 true // use_separator
2115 Gtk::Label label(message);
2117 dialog.get_vbox()->pack_start(label);
2120 entry.set_text(text);
2122 entry.set_activates_default(true);
2123 dialog.get_vbox()->pack_start(entry);
2125 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
2126 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
2127 dialog.set_default_response(Gtk::RESPONSE_OK);
2128 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
2131 if(dialog.run()!=Gtk::RESPONSE_OK)
2134 text=entry.get_text();
2143 App::open(std::string filename)
2145 return open_as(filename,filename);
2148 // this is called from autorecover.cpp:
2149 // App::open_as(get_shadow_file_name(filename),filename)
2150 // other than that, 'filename' and 'as' are the same
2152 App::open_as(std::string filename,std::string as)
2155 char long_name[1024];
2156 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2162 OneMoment one_moment;
2164 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2165 if(canvas && get_instance(canvas))
2167 get_instance(canvas)->find_canvas_view(canvas)->present();
2168 info("%s is already open", filename.c_str());
2169 // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2174 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2176 add_recent_file(as);
2178 handle<Instance> instance(Instance::create(canvas));
2181 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2183 set_recent_file_window_size(instance);
2187 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)")))
2188 instance->dialog_cvs_update();
2193 dialog_error_blocking(_("Error"), x);
2198 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2209 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2211 String file_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
2212 canvas->set_name(file_name);
2213 file_name += ".sifz";
2215 canvas->rend_desc().set_frame_rate(24.0);
2216 canvas->rend_desc().set_time_start(0.0);
2217 canvas->rend_desc().set_time_end(5.0);
2218 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2219 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2220 canvas->rend_desc().set_tl(Vector(-4,2.25));
2221 canvas->rend_desc().set_br(Vector(4,-2.25));
2222 canvas->rend_desc().set_w(480);
2223 canvas->rend_desc().set_h(270);
2224 canvas->rend_desc().set_antialias(1);
2225 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2226 canvas->set_file_name(file_name);
2228 handle<Instance> instance = Instance::create(canvas);
2230 if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
2231 instance->find_canvas_view(canvas)->canvas_properties.present();
2235 App::dialog_open(string filename)
2237 if (filename.empty())
2240 while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
2242 // If the filename still has wildcards, then we should
2243 // continue looking for the file we want
2244 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2250 get_ui_interface()->error(_("Unable to open file"));
2255 App::set_selected_instance(etl::loose_handle<Instance> instance)
2257 /* if(get_selected_instance()==instance)
2259 selected_instance=instance;
2260 signal_instance_selected()(instance);
2266 selected_instance=instance;
2267 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2271 instance->focus(instance->get_canvas());
2274 set_selected_canvas_view(0);
2276 signal_instance_selected()(instance);
2280 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2282 selected_canvas_view=canvas_view;
2283 signal_canvas_view_focus()(selected_canvas_view);
2286 selected_instance=canvas_view->get_instance();
2287 signal_instance_selected()(canvas_view->get_instance());
2290 if(get_selected_canvas_view()==canvas_view)
2292 signal_canvas_view_focus()(selected_canvas_view);
2293 signal_instance_selected()(canvas_view->get_instance());
2296 selected_canvas_view=canvas_view;
2297 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2298 set_selected_instance(canvas_view->get_instance());
2299 signal_canvas_view_focus()(selected_canvas_view);
2303 etl::loose_handle<Instance>
2304 App::get_instance(etl::handle<synfig::Canvas> canvas)
2306 if(!canvas) return 0;
2307 canvas=canvas->get_root();
2309 std::list<etl::handle<Instance> >::iterator iter;
2310 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2312 if((*iter)->get_canvas()==canvas)
2328 if(selected_instance)
2329 selected_instance->undo();
2335 if(selected_instance)
2336 selected_instance->redo();
2340 studio::App::get_base_path()
2342 return app_base_path_;