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