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;
1354 while(current != synfig::String::npos)
1356 // find end of first field (canvas) or return
1357 synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
1358 if(separator == synfig::String::npos) return;
1361 synfig::Canvas::Handle canvas;
1363 canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current));
1365 catch(Exception::IDNotFound) {
1366 // can't find the canvas; skip to the next canvas or return
1367 separator = canvas_window_size.find_first_of('\t', current);
1368 if(separator == synfig::String::npos) return;
1369 current = separator+1;
1373 CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
1374 canvasview->present();
1376 // check that we have the tab character the ends this canvas' data or return
1377 current = separator+1;
1378 separator = canvas_window_size.find_first_of('\t', current);
1379 if(separator == synfig::String::npos) return;
1382 if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
1384 current = separator+1;
1388 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
1389 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
1390 x=x*screen_w/SCALE_FACTOR;
1391 y=y*screen_h/SCALE_FACTOR;
1392 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
1393 x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
1394 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
1395 y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
1396 canvasview->move(x,y);
1398 if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
1399 if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
1400 w=w*screen_w/SCALE_FACTOR;
1401 h=h*screen_h/SCALE_FACTOR;
1402 canvasview->set_default_size(w,h);
1403 canvasview->set_size_request(w,h);
1405 current = separator+1;
1410 App::add_recent_file(const etl::handle<Instance> instance)
1412 int screen_w(Gdk::screen_width());
1413 int screen_h(Gdk::screen_height());
1415 std::string canvas_window_size;
1417 const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
1418 Instance::CanvasViewList::const_iterator iter;
1420 for(iter=cview_list.begin();iter!=cview_list.end();iter++)
1422 if( !((*iter)->is_visible()) )
1425 etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
1426 int x_pos, y_pos, x_size, y_size;
1427 (*iter)->get_position(x_pos,y_pos);
1428 (*iter)->get_size(x_size,y_size);
1430 canvas_window_size += strprintf("%s %d %d %d %d\t",
1431 canvas->get_relative_id(canvas->get_root()).c_str(),
1432 x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h,
1433 x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
1436 add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
1441 App::add_recent_file(const std::string &file_name, const std::string &window_size)
1443 std::string filename(file_name);
1445 assert(!filename.empty());
1447 if(filename.empty())
1450 // Toss out any "hidden" files
1451 if(basename(filename)[0]=='.')
1454 // If we aren't an absolute path, turn ourselves into one
1455 if(!is_absolute_path(filename))
1456 filename=absolute_path(filename);
1458 std::string old_window_size;
1460 list<string>::iterator iter;
1461 list<string>::iterator iter_wsize;
1462 // Check to see if the file is already on the list.
1463 // If it is, then remove it from the list
1464 for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
1467 recent_files.erase(iter);
1468 old_window_size = *iter_wsize;
1469 recent_files_window_size.erase(iter_wsize);
1474 // Push the filename to the front of the list
1475 recent_files.push_front(filename);
1476 if(window_size.empty())
1477 recent_files_window_size.push_front(old_window_size);
1479 recent_files_window_size.push_front(window_size);
1481 // Clean out the files at the end of the list.
1482 while(recent_files.size()>(unsigned)get_max_recent_files())
1484 recent_files.pop_back();
1485 recent_files_window_size.pop_back();
1488 signal_recent_files_changed_();
1493 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1496 App::get_time_format()
1498 return _App_time_format;
1502 App::set_time_format(synfig::Time::Format x)
1509 App::save_settings()
1514 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1515 setlocale(LC_NUMERIC, "C");
1517 std::string filename=get_config_file("accelrc");
1518 Gtk::AccelMap::save(filename);
1521 std::string filename=get_config_file("recentfiles");
1523 std::ofstream file(filename.c_str());
1527 synfig::warning("Unable to save %s",filename.c_str());
1531 list<string>::reverse_iterator iter;
1533 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1537 std::string filename=get_config_file("recentfiles")+std::string("_window_size");
1539 std::ofstream file(filename.c_str());
1543 synfig::warning("Unable to save %s",filename.c_str());
1547 list<string>::reverse_iterator iter;
1549 for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
1553 std::string filename=get_config_file("settings");
1554 synfigapp::Main::settings().save_to_file(filename);
1555 setlocale(LC_NUMERIC,old_locale);
1559 synfig::warning("Caught exception when attempting to save settings.");
1564 App::load_settings()
1569 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1570 setlocale(LC_NUMERIC, "C");
1572 std::string filename=get_config_file("accelrc");
1573 Gtk::AccelMap::load(filename);
1576 bool window_size_broken = false;
1578 std::string filename=get_config_file("recentfiles");
1579 std::string filename_window_size=filename+std::string("_window_size");
1581 std::ifstream file(filename.c_str());
1582 std::ifstream file_window_size(filename_window_size.c_str());
1584 if(!file_window_size)
1585 window_size_broken = true;
1589 std::string recent_file;
1590 std::string recent_file_window_size;
1591 getline(file,recent_file);
1592 if(!window_size_broken)
1593 getline(file_window_size,recent_file_window_size);
1594 if(!recent_file.empty())
1596 if(!window_size_broken && !file_window_size)
1597 window_size_broken = true;
1598 if(!window_size_broken)
1599 add_recent_file(recent_file,recent_file_window_size);
1601 add_recent_file(recent_file);
1604 if(!window_size_broken && file_window_size)
1605 window_size_broken = true;
1607 if(window_size_broken)
1609 recent_files_window_size.clear();
1610 recent_files_window_size.resize(recent_files.size());
1613 std::string filename=get_config_file("settings");
1614 if(!synfigapp::Main::settings().load_from_file(filename))
1616 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1617 //if(!synfigapp::Main::settings().load_from_file(filename))
1619 gamma.set_gamma(1.0/2.2);
1620 reset_initial_window_configuration();
1623 setlocale(LC_NUMERIC,old_locale);
1627 synfig::warning("Caught exception when attempting to load settings.");
1632 App::reset_initial_window_configuration()
1634 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1635 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1636 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1637 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1638 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1639 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1640 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1641 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1642 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1643 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1644 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1645 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1646 #ifdef SINGLE_THREADED
1647 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1649 synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
1650 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1654 App::shutdown_request(GdkEventAny*)
1658 //return !shutdown_in_progress;
1664 if(shutdown_in_progress)return;
1667 get_ui_interface()->task(_("Quit Request"));
1670 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1674 std::list<etl::handle<Instance> >::iterator iter;
1675 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1677 if(!(*iter)->safe_close())
1681 if((*iter)->synfigapp::Instance::get_action_count())
1683 handle<synfigapp::UIInterface> uim;
1684 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1686 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1687 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1689 case synfigapp::UIInterface::RESPONSE_NO:
1691 case synfigapp::UIInterface::RESPONSE_YES:
1694 case synfigapp::UIInterface::RESPONSE_CANCEL:
1703 if((*iter)->synfigapp::Instance::is_modified())
1705 handle<synfigapp::UIInterface> uim;
1706 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1708 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() );
1709 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1711 case synfigapp::UIInterface::RESPONSE_NO:
1713 case synfigapp::UIInterface::RESPONSE_YES:
1714 (*iter)->dialog_cvs_commit();
1716 case synfigapp::UIInterface::RESPONSE_CANCEL:
1725 // This next line causes things to crash for some reason
1729 shutdown_in_progress=true;
1731 instance_list.clear();
1733 while(studio::App::events_pending())studio::App::iteration(false);
1736 auto_recover->normal_shutdown();
1738 get_ui_interface()->task(_("Quit Request sent"));
1744 dialog_setup->refresh();
1745 dialog_setup->show();
1748 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1749 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1752 //#define USE_WIN32_FILE_DIALOGS 1
1755 #ifdef USE_WIN32_FILE_DIALOGS
1756 static OPENFILENAME ofn={};
1760 #include <gdk/gdkwin32.h>
1764 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1766 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1768 #ifdef USE_WIN32_FILE_DIALOGS
1769 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1771 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1772 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1773 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1775 ofn.lStructSize=sizeof(OPENFILENAME);
1776 ofn.hwndOwner = hWnd;
1777 ofn.hInstance = hInstance;
1778 ofn.lpstrFilter = szFilter;
1779 // ofn.lpstrCustomFilter=NULL;
1780 // ofn.nMaxCustFilter=0;
1781 // ofn.nFilterIndex=0;
1782 // ofn.lpstrFile=NULL;
1783 ofn.nMaxFile=MAX_PATH;
1784 // ofn.lpstrFileTitle=NULL;
1785 // ofn.lpstrInitialDir=NULL;
1786 // ofn.lpstrTitle=NULL;
1787 ofn.Flags=OFN_HIDEREADONLY;
1788 // ofn.nFileOffset=0;
1789 // ofn.nFileExtension=0;
1790 ofn.lpstrDefExt=TEXT("sif");
1791 // ofn.lCustData = 0l;
1793 // ofn.lpTemplateName=NULL;
1795 CHAR szFilename[MAX_PATH];
1797 strcpy(szFilename,filename.c_str());
1798 strcpy(szTitle,title.c_str());
1800 ofn.lpstrFile=szFilename;
1801 ofn.lpstrFileTitle=szTitle;
1803 if(GetOpenFileName(&ofn))
1805 filename=szFilename;
1811 synfig::String prev_path;
1813 if(!_preferences.get_value(preference, prev_path))
1816 prev_path = absolute_path(prev_path);
1818 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1820 dialog->set_current_folder(prev_path);
1821 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1822 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1824 if (filename.empty())
1825 dialog->set_filename(prev_path);
1826 else if (is_absolute_path(filename))
1827 dialog->set_filename(filename);
1829 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1831 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1832 filename = dialog->get_filename();
1833 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1834 _preferences.set_value(preference, dirname(filename));
1848 GtkWidget *fileselection;
1849 fileselection = gtk_file_selection_new(title.c_str());
1852 if(basename(filename)==filename)
1854 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1857 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1859 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1861 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1862 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1864 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1865 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1867 gtk_widget_show(fileselection);
1875 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1876 _preferences.set_value(preference,dirname(filename));
1880 gtk_widget_destroy(fileselection);
1883 gtk_widget_destroy(fileselection);
1890 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1892 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1894 #if USE_WIN32_FILE_DIALOGS
1895 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1897 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1898 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1899 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1901 ofn.lStructSize=sizeof(OPENFILENAME);
1902 ofn.hwndOwner = hWnd;
1903 ofn.hInstance = hInstance;
1904 ofn.lpstrFilter = szFilter;
1905 // ofn.lpstrCustomFilter=NULL;
1906 // ofn.nMaxCustFilter=0;
1907 // ofn.nFilterIndex=0;
1908 // ofn.lpstrFile=NULL;
1909 ofn.nMaxFile=MAX_PATH;
1910 // ofn.lpstrFileTitle=NULL;
1911 // ofn.lpstrInitialDir=NULL;
1912 // ofn.lpstrTitle=NULL;
1913 ofn.Flags=OFN_OVERWRITEPROMPT;
1914 // ofn.nFileOffset=0;
1915 // ofn.nFileExtension=0;
1916 ofn.lpstrDefExt=TEXT("sif");
1917 // ofn.lCustData = 0l;
1919 // ofn.lpTemplateName=NULL;
1921 CHAR szFilename[MAX_PATH];
1923 strcpy(szFilename,filename.c_str());
1924 strcpy(szTitle,title.c_str());
1926 ofn.lpstrFile=szFilename;
1927 ofn.lpstrFileTitle=szTitle;
1929 if(GetSaveFileName(&ofn))
1931 filename=szFilename;
1932 _preferences.set_value(preference,dirname(filename));
1937 synfig::String prev_path;
1939 if(!_preferences.get_value(preference, prev_path))
1942 prev_path = absolute_path(prev_path);
1944 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1946 dialog->set_current_folder(prev_path);
1947 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1948 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1950 Widget_Enum *file_type_enum = 0;
1951 if (preference == ANIMATION_DIR_PREFERENCE)
1953 file_type_enum = manage(new Widget_Enum());
1954 file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
1955 .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
1956 .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
1957 .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
1958 file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
1960 Gtk::HBox *hbox = manage(new Gtk::HBox);
1961 hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
1962 hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
1965 dialog->set_extra_widget(*hbox);
1968 if (filename.empty())
1969 dialog->set_filename(prev_path);
1972 std::string full_path;
1973 if (is_absolute_path(filename))
1974 full_path = filename;
1976 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1978 // select the file if it exists
1979 dialog->set_filename(full_path);
1981 // if the file doesn't exist, put its name into the filename box
1983 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1984 dialog->set_current_name(basename(filename));
1987 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1988 if (preference == ANIMATION_DIR_PREFERENCE)
1989 set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
1990 filename = dialog->get_filename();
1991 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
1992 _preferences.set_value(preference, dirname(filename));
2003 App::dialog_error_blocking(const std::string &title, const std::string &message)
2005 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2006 dialog.set_title(title);
2012 App::dialog_warning_blocking(const std::string &title, const std::string &message)
2014 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
2015 dialog.set_title(title);
2021 App::dialog_yes_no(const std::string &title, const std::string &message)
2026 true // use_separator
2028 Gtk::Label label(message);
2031 dialog.get_vbox()->pack_start(label);
2032 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2033 dialog.add_button(Gtk::StockID("gtk-no"),0);
2035 return dialog.run();
2039 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
2044 true // use_separator
2046 Gtk::Label label(message);
2049 dialog.get_vbox()->pack_start(label);
2050 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2051 dialog.add_button(Gtk::StockID("gtk-no"),0);
2052 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
2054 return dialog.run();
2058 App::dialog_not_implemented()
2060 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2061 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
2066 try_open_url(const std::string &url)
2069 return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
2071 gchar* argv[3] = {strdup(App::browser_command.c_str()), strdup(url.c_str()), NULL};
2073 GError* gerror = NULL;
2075 retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &gerror);
2081 error(_("Could not execute specified web browser: %s"), gerror->message);
2082 g_error_free(gerror);
2093 if (!try_open_url("http://synfig.org/Documentation"))
2095 Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
2096 dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
2097 dialog.set_title(_("Help"));
2103 App::open_url(const std::string &url)
2109 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
2114 true // use_separator
2116 Gtk::Label label(message);
2118 dialog.get_vbox()->pack_start(label);
2121 entry.set_text(text);
2123 entry.set_activates_default(true);
2124 dialog.get_vbox()->pack_start(entry);
2126 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
2127 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
2128 dialog.set_default_response(Gtk::RESPONSE_OK);
2129 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
2132 if(dialog.run()!=Gtk::RESPONSE_OK)
2135 text=entry.get_text();
2144 App::open(std::string filename)
2146 return open_as(filename,filename);
2149 // this is called from autorecover.cpp:
2150 // App::open_as(get_shadow_file_name(filename),filename)
2151 // other than that, 'filename' and 'as' are the same
2153 App::open_as(std::string filename,std::string as)
2156 char long_name[1024];
2157 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2163 OneMoment one_moment;
2165 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2166 if(canvas && get_instance(canvas))
2168 get_instance(canvas)->find_canvas_view(canvas)->present();
2169 info("%s is already open", filename.c_str());
2170 // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2175 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2177 add_recent_file(as);
2179 handle<Instance> instance(Instance::create(canvas));
2182 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2184 set_recent_file_window_size(instance);
2188 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)")))
2189 instance->dialog_cvs_update();
2194 dialog_error_blocking(_("Error"), x);
2199 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2210 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2212 String file_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
2213 canvas->set_name(file_name);
2214 file_name += ".sifz";
2216 canvas->rend_desc().set_frame_rate(24.0);
2217 canvas->rend_desc().set_time_start(0.0);
2218 canvas->rend_desc().set_time_end(5.0);
2219 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2220 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2221 canvas->rend_desc().set_tl(Vector(-4,2.25));
2222 canvas->rend_desc().set_br(Vector(4,-2.25));
2223 canvas->rend_desc().set_w(480);
2224 canvas->rend_desc().set_h(270);
2225 canvas->rend_desc().set_antialias(1);
2226 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2227 canvas->set_file_name(file_name);
2229 handle<Instance> instance = Instance::create(canvas);
2231 if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
2232 instance->find_canvas_view(canvas)->canvas_properties.present();
2236 App::dialog_open(string filename)
2238 if (filename.empty())
2241 while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
2243 // If the filename still has wildcards, then we should
2244 // continue looking for the file we want
2245 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2251 get_ui_interface()->error(_("Unable to open file"));
2256 App::set_selected_instance(etl::loose_handle<Instance> instance)
2258 /* if(get_selected_instance()==instance)
2260 selected_instance=instance;
2261 signal_instance_selected()(instance);
2267 selected_instance=instance;
2268 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2272 instance->focus(instance->get_canvas());
2275 set_selected_canvas_view(0);
2277 signal_instance_selected()(instance);
2281 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2283 selected_canvas_view=canvas_view;
2284 signal_canvas_view_focus()(selected_canvas_view);
2287 selected_instance=canvas_view->get_instance();
2288 signal_instance_selected()(canvas_view->get_instance());
2291 if(get_selected_canvas_view()==canvas_view)
2293 signal_canvas_view_focus()(selected_canvas_view);
2294 signal_instance_selected()(canvas_view->get_instance());
2297 selected_canvas_view=canvas_view;
2298 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2299 set_selected_instance(canvas_view->get_instance());
2300 signal_canvas_view_focus()(selected_canvas_view);
2304 etl::loose_handle<Instance>
2305 App::get_instance(etl::handle<synfig::Canvas> canvas)
2307 if(!canvas) return 0;
2308 canvas=canvas->get_root();
2310 std::list<etl::handle<Instance> >::iterator iter;
2311 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2313 if((*iter)->get_canvas()==canvas)
2329 if(selected_instance)
2330 selected_instance->undo();
2336 if(selected_instance)
2337 selected_instance->redo();
2341 studio::App::get_base_path()
2343 return app_base_path_;