1 /* === S Y N F I G ========================================================= */
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
10 ** Copyright (c) 2008 Gerald Young
12 ** This package is free software; you can redistribute it and/or
13 ** modify it under the terms of the GNU General Public License as
14 ** published by the Free Software Foundation; either version 2 of
15 ** the License, or (at your option) any later version.
17 ** This package is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ** General Public License for more details.
23 /* ========================================================================= */
25 /* === H E A D E R S ======================================================= */
44 #ifdef HAVE_SYS_ERRNO_H
45 #include <sys/errno.h>
47 #include <gtkmm/fileselection.h>
48 #include <gtkmm/dialog.h>
49 #include <gtkmm/messagedialog.h>
50 #include <gtkmm/label.h>
51 #include <gtkmm/stock.h>
52 #include <gtkmm/stockitem.h>
53 #include <gtkmm/iconsource.h>
54 #include <gtkmm/inputdialog.h>
55 #include <gtkmm/accelmap.h>
56 #include <gtkmm/uimanager.h>
60 #include <gdkmm/general.h>
62 #include <synfig/loadcanvas.h>
63 #include <synfig/savecanvas.h>
69 #include "canvasview.h"
70 #include "dialog_setup.h"
71 #include "dialog_gradient.h"
72 #include "dialog_color.h"
75 #include "onemoment.h"
77 #include "dockmanager.h"
79 #include "state_eyedrop.h"
80 #include "state_normal.h"
81 #include "state_draw.h"
82 #include "state_fill.h"
83 #include "state_bline.h"
84 #include "state_polygon.h"
85 #include "state_sketch.h"
86 #include "state_gradient.h"
87 #include "state_circle.h"
88 #include "state_rectangle.h"
89 #include "state_smoothmove.h"
90 #include "state_scale.h"
91 #include "state_width.h"
92 #include "state_rotate.h"
93 #include "state_zoom.h"
95 #include "devicetracker.h"
96 #include "dialog_tooloptions.h"
97 #include "widget_enum.h"
99 #include "autorecover.h"
101 #include <synfigapp/settings.h>
102 #include "dock_history.h"
103 #include "dock_canvases.h"
104 #include "dock_keyframes.h"
105 #include "dock_layers.h"
106 #include "dock_params.h"
107 #include "dock_metadata.h"
108 #include "dock_children.h"
109 #include "dock_info.h"
110 #include "dock_navigator.h"
111 #include "dock_layergroups.h"
112 #include "dock_timetrack.h"
113 #include "dock_curves.h"
115 #include "mod_palette/mod_palette.h"
116 #include "mod_mirror/mod_mirror.h"
118 #include <sys/stat.h>
124 #include "statemanager.h"
130 #include <gtkmm/accelmap.h>
131 #include <gtkmm/filechooser.h>
132 #include <gtkmm/filechooserdialog.h>
138 /* === U S I N G =========================================================== */
142 using namespace synfig;
143 using namespace studio;
145 /* === M A C R O S ========================================================= */
147 #ifndef SYNFIG_USER_APP_DIR
149 #define SYNFIG_USER_APP_DIR "Library/Synfig"
150 #elif defined(_WIN32)
151 #define SYNFIG_USER_APP_DIR "Synfig"
153 #define SYNFIG_USER_APP_DIR ".synfig"
158 #define DPM2DPI(x) (float(x)/39.3700787402f)
159 #define DPI2DPM(x) (float(x)*39.3700787402f)
165 # define IMAGE_DIR "share\\pixmaps"
170 # define IMAGE_DIR "/usr/local/share/pixmaps"
174 # define IMAGE_EXT "tif"
177 #include <synfigapp/main.h>
179 /* === S I G N A L S ======================================================= */
181 static sigc::signal<void> signal_present_all_;
183 App::signal_present_all() { return signal_present_all_; }
185 static sigc::signal<void> signal_recent_files_changed_;
187 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
189 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
190 sigc::signal<void,etl::loose_handle<CanvasView> >&
191 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
193 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
194 sigc::signal<void,etl::handle<Instance> >&
195 App::signal_instance_selected() { return signal_instance_selected_; }
197 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
198 sigc::signal<void,etl::handle<Instance> >&
199 App::signal_instance_created() { return signal_instance_created_; }
201 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
202 sigc::signal<void,etl::handle<Instance> >&
203 App::signal_instance_deleted() { return signal_instance_deleted_; }
205 /* === G L O B A L S ======================================================= */
207 static std::list<std::string> recent_files;
208 const std::list<std::string>& App::get_recent_files() { return recent_files; }
210 static std::list<std::string> recent_files_window_size;
212 int App::Busy::count;
213 bool App::shutdown_in_progress;
215 synfig::Gamma App::gamma;
217 Glib::RefPtr<studio::UIManager> App::ui_manager_;
219 synfig::Distance::System App::distance_system;
221 studio::Dialog_Setup* App::dialog_setup;
223 etl::handle< studio::ModPalette > mod_palette_;
224 //studio::Dialog_Palette* App::dialog_palette;
226 std::list<etl::handle<Instance> > App::instance_list;
228 static etl::handle<synfigapp::UIInterface> ui_interface_;
229 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
231 etl::handle<Instance> App::selected_instance;
232 etl::handle<CanvasView> App::selected_canvas_view;
234 studio::About *studio::App::about=NULL;
236 studio::Toolbox *studio::App::toolbox=NULL;
238 studio::AutoRecover *studio::App::auto_recover=NULL;
240 studio::IPC *ipc=NULL;
242 studio::DockManager* studio::App::dock_manager=0;
244 studio::DeviceTracker* studio::App::device_tracker=0;
246 studio::Dialog_Gradient* studio::App::dialog_gradient;
248 studio::Dialog_Color* studio::App::dialog_color;
250 Gtk::InputDialog* studio::App::dialog_input;
252 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
254 studio::Dock_History* dock_history;
255 studio::Dock_Canvases* dock_canvases;
256 studio::Dock_Keyframes* dock_keyframes;
257 studio::Dock_Layers* dock_layers;
258 studio::Dock_Params* dock_params;
259 studio::Dock_MetaData* dock_meta_data;
260 studio::Dock_Children* dock_children;
261 studio::Dock_Info* dock_info;
262 studio::Dock_LayerGroups* dock_layer_groups;
263 studio::Dock_Navigator* dock_navigator;
264 studio::Dock_Timetrack* dock_timetrack;
265 studio::Dock_Curves* dock_curves;
267 std::list< etl::handle< studio::Module > > module_list_;
269 bool studio::App::use_colorspace_gamma=true;
270 #ifdef SINGLE_THREADED
271 bool studio::App::single_threaded=false;
273 bool studio::App::restrict_radius_ducks=false;
274 String studio::App::browser_command("firefox");
276 static int max_recent_files_=25;
277 int studio::App::get_max_recent_files() { return max_recent_files_; }
278 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
280 static synfig::String app_base_path_;
285 really_delete_widget(Gtk::Widget *widget)
287 // synfig::info("really delete %p", (void*)widget);
292 // nasty workaround - when we've finished with a popup menu, we want to delete it
293 // attaching to the signal_hide() signal gets us here before the action on the menu has run,
294 // so schedule the real delete to happen in 50ms, giving the action a chance to run
296 delete_widget(Gtk::Widget *widget)
298 // synfig::info("delete %p", (void*)widget);
299 Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
302 }; // END of namespace studio
303 studio::StateManager* state_manager;
308 class GlobalUIInterface : public synfigapp::UIInterface
312 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
317 true // use_separator
319 Gtk::Label label(message);
322 dialog.get_vbox()->pack_start(label);
323 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
324 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
326 dialog.set_default_response(dflt);
328 return (Response)dialog.run();
330 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
335 true // use_separator
337 Gtk::Label label(message);
340 dialog.get_vbox()->pack_start(label);
341 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
342 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
343 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
345 dialog.set_default_response(dflt);
347 return (Response)dialog.run();
349 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
354 true // use_separator
356 Gtk::Label label(message);
359 dialog.get_vbox()->pack_start(label);
360 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
361 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
363 dialog.set_default_response(dflt);
365 return (Response)dialog.run();
369 task(const std::string &task)
371 std::cerr<<task<<std::endl;
372 while(studio::App::events_pending())studio::App::iteration(false);
377 error(const std::string &err)
379 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
386 warning(const std::string &err)
388 std::cerr<<"warning: "<<err<<std::endl;
389 while(studio::App::events_pending())studio::App::iteration(false);
394 amount_complete(int /*current*/, int /*total*/)
396 while(studio::App::events_pending())studio::App::iteration(false);
401 /* === P R O C E D U R E S ================================================= */
405 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
407 action_group_list.push_back(action_group);
408 Gtk::UIManager::insert_action_group(action_group, pos);
412 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
414 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
415 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
416 if(*iter==action_group)
418 action_group_list.erase(iter);
419 Gtk::UIManager::remove_action_group(action_group);
422 synfig::error("Unable to find action group");
426 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
428 ui_manager->insert_action_group(group,0);
430 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
431 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
433 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
435 if(*iter && (*iter)->get_name()!="menus")
437 synfig::info("Removing action group "+(*iter)->get_name());
438 ui_manager->remove_action_group(*iter);
441 ui_manager->insert_action_group(group,0);
443 for(;!prev_groups.empty();prev_groups.pop_front())
445 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
446 ui_manager->insert_action_group(prev_groups.front(),1);
450 class Preferences : public synfigapp::Settings
453 virtual bool get_value(const synfig::String& key, synfig::String& value)const
457 value=strprintf("%f %f %f %f",
458 App::gamma.get_gamma_r(),
459 App::gamma.get_gamma_g(),
460 App::gamma.get_gamma_b(),
461 App::gamma.get_black_level()
465 if(key=="time_format")
467 value=strprintf("%i",App::get_time_format());
470 if(key=="file_history.size")
472 value=strprintf("%i",App::get_max_recent_files());
475 if(key=="use_colorspace_gamma")
477 value=strprintf("%i",(int)App::use_colorspace_gamma);
480 if(key=="distance_system")
482 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
485 #ifdef SINGLE_THREADED
486 if(key=="single_threaded")
488 value=strprintf("%i",(int)App::single_threaded);
492 if(key=="auto_recover_backup_interval")
494 value=strprintf("%i",App::auto_recover->get_timeout());
497 if(key=="restrict_radius_ducks")
499 value=strprintf("%i",(int)App::restrict_radius_ducks);
502 if(key=="browser_command")
504 value=App::browser_command;
508 return synfigapp::Settings::get_value(key,value);
511 virtual bool set_value(const synfig::String& key,const synfig::String& value)
517 strscanf(value,"%f %f %f %f",
524 App::gamma.set_all(r,g,b,blk);
528 if(key=="time_format")
530 int i(atoi(value.c_str()));
531 App::set_time_format(static_cast<synfig::Time::Format>(i));
534 if(key=="auto_recover_backup_interval")
536 int i(atoi(value.c_str()));
537 App::auto_recover->set_timeout(i);
540 if(key=="file_history.size")
542 int i(atoi(value.c_str()));
543 App::set_max_recent_files(i);
546 if(key=="use_colorspace_gamma")
548 int i(atoi(value.c_str()));
549 App::use_colorspace_gamma=i;
552 if(key=="distance_system")
554 App::distance_system=Distance::ident_system(value);;
557 #ifdef SINGLE_THREADED
558 if(key=="single_threaded")
560 int i(atoi(value.c_str()));
561 App::single_threaded=i;
565 if(key=="restrict_radius_ducks")
567 int i(atoi(value.c_str()));
568 App::restrict_radius_ducks=i;
571 if(key=="browser_command")
573 App::browser_command=value;
577 return synfigapp::Settings::set_value(key,value);
580 virtual KeyList get_key_list()const
582 KeyList ret(synfigapp::Settings::get_key_list());
583 ret.push_back("gamma");
584 ret.push_back("time_format");
585 ret.push_back("distance_system");
586 ret.push_back("file_history.size");
587 ret.push_back("use_colorspace_gamma");
588 #ifdef SINGLE_THREADED
589 ret.push_back("single_threaded");
591 ret.push_back("auto_recover_backup_interval");
592 ret.push_back("restrict_radius_ducks");
593 ret.push_back("browser_command");
598 static ::Preferences _preferences;
603 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
605 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
607 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
609 menus_action_group->add( Gtk::Action::create("menu-file", _("_File")) );
610 menus_action_group->add( Gtk::Action::create("menu-edit", _("_Edit")) );
611 menus_action_group->add( Gtk::Action::create("menu-view", _("_View")) );
612 menus_action_group->add( Gtk::Action::create("menu-canvas", _("_Canvas")) );
613 menus_action_group->add( Gtk::Action::create("menu-layer", _("_Layer")) );
614 menus_action_group->add( Gtk::Action::create("menu-duck-mask", _("Show/Hide Ducks")) );
615 menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) );
616 menus_action_group->add( Gtk::Action::create("menu-lowres-pixel", _("Low-Res Pixel Size")) );
617 menus_action_group->add( Gtk::Action::create("menu-layer-new", _("New Layer")) );
618 menus_action_group->add( Gtk::Action::create("menu-keyframe", _("Keyframe")) );
619 menus_action_group->add( Gtk::Action::create("menu-group", _("Group")) );
620 menus_action_group->add( Gtk::Action::create("menu-state", _("State")) );
621 menus_action_group->add( Gtk::Action::create("menu-toolbox", _("Toolbox")) );
623 // Add the synfigapp actions...
624 synfigapp::Action::Book::iterator iter;
625 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
627 actions_action_group->add(Gtk::Action::create(
628 "action-"+iter->second.name,
629 get_action_stock_id(iter->second),
630 iter->second.local_name,iter->second.local_name
634 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
635 #define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock,label,label) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
636 #define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ group->add(action,sig); }
638 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
639 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
640 DEFINE_ACTION("new", Gtk::Stock::NEW);
641 DEFINE_ACTION("open", Gtk::Stock::OPEN);
642 DEFINE_ACTION("save", Gtk::Stock::SAVE);
643 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
644 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
645 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
646 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
647 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
648 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
649 DEFINE_ACTION("import", _("Import"));
650 DEFINE_ACTION("render", _("Render"));
651 DEFINE_ACTION("preview", _("Preview"));
652 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
653 DEFINE_ACTION("sound", _("Sound File"));
654 DEFINE_ACTION("options", _("Options"));
655 DEFINE_ACTION("close", _("Close View"));
656 DEFINE_ACTION("close-document", _("Close Document"));
657 DEFINE_ACTION("quit", Gtk::Stock::QUIT);
660 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
661 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
662 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
663 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
664 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
665 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
666 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
667 DEFINE_ACTION("properties", _("Properties"));
669 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
670 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
671 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
672 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
673 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
674 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
675 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
676 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
677 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
678 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
679 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
680 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
681 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
682 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
683 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
684 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
685 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
686 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
687 DEFINE_ACTION(strprintf("lowres-pixel-%d", *iter), strprintf(_("Set Low-Res pixel size to %d"), *iter));
688 DEFINE_ACTION("play", _("Play"));
689 // DEFINE_ACTION("pause", _("Pause"));
690 DEFINE_ACTION("stop", _("Stop"));
691 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
692 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
693 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
694 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
695 DEFINE_ACTION("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size"));
696 DEFINE_ACTION("increase-low-res-pixel-size", _("Increase Low-Res Pixel Size"));
697 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
698 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
699 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
700 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
701 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
702 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
703 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
704 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
705 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
706 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
707 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
708 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
709 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
710 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
711 DEFINE_ACTION("seek-end", _("Seek to End"));
713 DEFINE_ACTION("action-group_add", _("Add group"));
715 DEFINE_ACTION("canvas-new", _("New Canvas"));
717 DEFINE_ACTION("amount-inc", _("Increase Amount"));
718 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
723 // Set up synfigapp actions
725 synfigapp::Action::Book::iterator iter;
727 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
729 Gtk::StockID stock_id;
731 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
733 //Gtk::Image* image(manage(new Gtk::Image()));
734 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
735 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
736 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
737 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
738 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
739 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
740 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
741 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
742 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
743 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
745 actions_action_group->add(Gtk::Action::create(
746 "action-"+iter->second.name,
748 iter->second.local_name,iter->second.local_name
756 Glib::ustring ui_info =
758 " <popup name='menu-toolbox' action='menu-toolbox'>"
759 " <menu action='menu-file'>"
762 " <popup name='menu-main' action='menu-main'>"
763 " <menu action='menu-file'>"
764 " <menuitem action='new' />"
765 " <menuitem action='open' />"
766 " <menuitem action='save' />"
767 " <menuitem action='save-as' />"
768 " <menuitem action='revert' />"
769 " <separator name='bleh01'/>"
770 " <menuitem action='cvs-add' />"
771 " <menuitem action='cvs-update' />"
772 " <menuitem action='cvs-commit' />"
773 " <menuitem action='cvs-revert' />"
774 " <separator name='bleh02'/>"
775 " <menuitem action='import' />"
776 " <separator name='bleh03'/>"
777 " <menuitem action='render' />"
778 " <menuitem action='preview' />"
779 " <menuitem action='sound' />"
780 " <separator name='bleh04'/>"
781 " <menuitem action='options' />"
782 " <menuitem action='close' />"
783 " <menuitem action='close-document' />"
784 " <menuitem action='quit' />"
786 " <menu action='menu-edit'>"
787 " <menuitem action='undo'/>"
788 " <menuitem action='redo'/>"
789 " <separator name='bleh05'/>"
790 " <menuitem action='cut'/>"
791 " <menuitem action='copy'/>"
792 " <menuitem action='paste'/>"
793 " <separator name='bleh06'/>"
794 " <menuitem action='select-all-ducks'/>"
795 " <menuitem action='unselect-all-layers'/>"
796 " <separator name='bleh07'/>"
797 " <menuitem action='properties'/>"
799 " <menu action='menu-view'>"
800 " <menu action='menu-duck-mask'>"
801 " <menuitem action='mask-position-ducks' />"
802 " <menuitem action='mask-vertex-ducks' />"
803 " <menuitem action='mask-tangent-ducks' />"
804 " <menuitem action='mask-radius-ducks' />"
805 " <menuitem action='mask-width-ducks' />"
806 " <menuitem action='mask-angle-ducks' />"
808 " <menu action='menu-preview-quality'>"
809 " <menuitem action='quality-00' />"
810 " <menuitem action='quality-01' />"
811 " <menuitem action='quality-02' />"
812 " <menuitem action='quality-03' />"
813 " <menuitem action='quality-04' />"
814 " <menuitem action='quality-05' />"
815 " <menuitem action='quality-06' />"
816 " <menuitem action='quality-07' />"
817 " <menuitem action='quality-08' />"
818 " <menuitem action='quality-09' />"
819 " <menuitem action='quality-10' />"
821 " <menu action='menu-lowres-pixel'>"
822 " <menuitem action='decrease-low-res-pixel-size'/>"
823 " <menuitem action='increase-low-res-pixel-size'/>"
824 " <separator name='pixel-size-separator'/>"
827 for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
828 ui_info += strprintf(" <menuitem action='lowres-pixel-%d' />", *iter);
832 " <separator name='bleh08'/>"
833 " <menuitem action='play'/>"
834 //" <menuitem action='pause'/>"
835 " <menuitem action='stop'/>"
836 " <menuitem action='dialog-flipbook'/>"
837 " <separator name='bleh09'/>"
838 " <menuitem action='toggle-grid-show'/>"
839 " <menuitem action='toggle-grid-snap'/>"
840 " <menuitem action='toggle-guide-show'/>"
841 " <menuitem action='toggle-low-res'/>"
842 " <menuitem action='toggle-onion-skin'/>"
843 " <separator name='bleh10'/>"
844 " <menuitem action='canvas-zoom-in'/>"
845 " <menuitem action='canvas-zoom-out'/>"
846 " <menuitem action='canvas-zoom-fit'/>"
847 " <menuitem action='canvas-zoom-100'/>"
848 " <separator name='bleh11'/>"
849 " <menuitem action='time-zoom-in'/>"
850 " <menuitem action='time-zoom-out'/>"
851 " <separator name='bleh12'/>"
852 " <menuitem action='jump-next-keyframe'/>"
853 " <menuitem action='jump-prev-keyframe'/>"
854 " <menuitem action='seek-next-frame'/>"
855 " <menuitem action='seek-prev-frame'/>"
856 " <menuitem action='seek-next-second'/>"
857 " <menuitem action='seek-prev-second'/>"
858 " <menuitem action='seek-begin'/>"
859 " <menuitem action='seek-end'/>"
861 " <menu action='menu-canvas'>"
862 " <menuitem action='canvas-new'/>"
864 " <menu name='menu-state' action='menu-state'>"
866 " <menu action='menu-group'>"
867 " <menuitem action='action-group_add'/>"
869 " <menu action='menu-layer'>"
870 //" <menuitem action='cut'/>"
871 //" <menuitem action='copy'/>"
872 //" <menuitem action='paste'/>"
873 //" <separator name='bleh06'/>"
874 " <menu action='menu-layer-new'></menu>"
875 " <menuitem action='amount-inc'/>"
876 " <menuitem action='amount-dec'/>"
878 " <menu action='menu-keyframe'>"
879 " <menuitem action='keyframe-properties'/>"
886 " <menubar name='MenuBar'>"
887 " <menu action='MenuFile'>"
888 " <menuitem action='New'/>"
889 " <menuitem action='Open'/>"
891 " <menuitem action='Quit'/>"
893 " <menu action='MenuEdit'>"
894 " <menuitem action='Cut'/>"
895 " <menuitem action='Copy'/>"
896 " <menuitem action='Paste'/>"
899 " <toolbar name='ToolBar'>"
900 " <toolitem action='Open'/>"
901 " <toolitem action='Quit'/>"
907 actions_action_group->set_sensitive(false);
908 App::ui_manager()->set_add_tearoffs(true);
909 App::ui_manager()->insert_action_group(menus_action_group,1);
910 App::ui_manager()->insert_action_group(actions_action_group,1);
911 App::ui_manager()->add_ui_from_string(ui_info);
913 //App::ui_manager()->get_accel_group()->unlock();
915 catch(const Glib::Error& ex)
917 synfig::error("building menus and toolbars failed: " + ex.what());
920 // Add default keyboard accelerators
921 #define ACCEL(path,accel) \
923 Gtk::AccelKey accel_key(accel,path); \
924 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
927 #define ACCEL2(accel) \
929 Gtk::AccelKey accel_key(accel); \
930 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
933 ACCEL("<Actions>//select-all-ducks","<Control>a");
934 ACCEL("<Actions>//unselect-all-layers","<Control>d");
935 ACCEL("<Actions>//render","F9");
936 ACCEL("<Actions>//preview","F11");
937 ACCEL("<Actions>//properties","F8");
938 ACCEL("<Actions>//options","F12");
939 ACCEL("<Actions>//import","<control>i");
940 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
941 ACCEL("<Actions>//toggle-grid-show","<Control>g");
942 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
943 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
944 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
945 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
946 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
947 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
948 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
949 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
951 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
952 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
954 ACCEL("<Actions>//quality-01","<Control>1");
955 ACCEL("<Actions>//quality-02","<Control>2");
956 ACCEL("<Actions>//quality-03","<Control>3");
957 ACCEL("<Actions>//quality-04","<Control>4");
958 ACCEL("<Actions>//quality-05","<Control>5");
959 ACCEL("<Actions>//quality-06","<Control>6");
960 ACCEL("<Actions>//quality-07","<Control>7");
961 ACCEL("<Actions>//quality-08","<Control>8");
962 ACCEL("<Actions>//quality-09","<Control>9");
963 ACCEL("<Actions>//quality-10","<Control>0");
964 ACCEL("<Actions>//undo","<Control>z");
965 ACCEL("<Actions>//redo","<Control>r");
966 ACCEL("<Actions>//action-layer_remove","Delete");
968 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
969 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
970 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
971 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
972 ACCEL("<Actions>//time-zoom-in","+");
973 ACCEL("<Actions>//time-zoom-out","_");
975 ACCEL2(Gtk::AccelKey('(',Gdk::CONTROL_MASK,"<Actions>//decrease-low-res-pixel-size"));
976 ACCEL2(Gtk::AccelKey(')',Gdk::CONTROL_MASK,"<Actions>//increase-low-res-pixel-size"));
978 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
979 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
981 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
982 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
983 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
984 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
985 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
986 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
987 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
988 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
989 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
990 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
991 ACCEL2(Gtk::AccelKey('o',Gdk::MOD1_MASK,"<Actions>//toggle-onion-skin"));
992 ACCEL("<Actions>//play", "<Control>p");
993 ACCEL("<Actions>//seek-begin","Home");
994 ACCEL("<Actions>//seek-end","End");
996 ACCEL("<Actions>//state-normal", "<Mod1>a");
997 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
998 ACCEL("<Actions>//state-scale", "<Mod1>d");
999 ACCEL("<Actions>//state-rotate", "<Mod1>s");
1001 ACCEL("<Actions>//state-bline", "<Mod1>b");
1002 ACCEL("<Actions>//state-circle", "<Mod1>c");
1003 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
1004 ACCEL("<Actions>//state-gradient", "<Mod1>g");
1006 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
1007 ACCEL("<Actions>//state-fill", "<Mod1>f");
1008 ACCEL("<Actions>//state-zoom", "<Mod1>z");
1009 ACCEL("<Actions>//state-polygon", "<Mod1>p");
1011 ACCEL("<Actions>//state-draw", "<Mod1>w");
1012 ACCEL("<Actions>//state-sketch", "<Mod1>k");
1013 ACCEL("<Actions>//state-width", "<Mod1>t");
1014 ACCEL("<Actions>//state-mirror", "<Mod1>m");
1016 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1022 #define mkdir(x,y) mkdir(x)
1025 /* === M E T H O D S ======================================================= */
1027 App::App(int *argc, char ***argv):
1028 Gtk::Main(argc,argv),
1029 IconController(etl::dirname((*argv)[0]))
1031 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1034 ui_interface_=new GlobalUIInterface();
1038 // don't call thread_init() if threads are already initialized
1039 // on some machines bonobo_init() initialized threads before we get here
1040 if (!g_thread_supported())
1041 Glib::thread_init();
1043 distance_system=Distance::SYSTEM_UNITS;
1045 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1048 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1052 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1058 if(!SYNFIG_CHECK_VERSION())
1060 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1061 dialog_error_blocking("Synfig Studio",
1062 "This copy of Synfig Studio was compiled against a\n"
1063 "different version of libsynfig than what is currently\n"
1064 "installed. Synfig Studio will now abort. Try downloading\n"
1065 "the latest version from the Synfig website at\n"
1066 "http://synfig.org/Download"
1070 Glib::set_application_name(_("Synfig Studio"));
1072 Splash splash_screen;
1073 splash_screen.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 //! \todo do we need locale_from_utf8() on non-Windows boxes too? (bug #1837445)
1332 return Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR));
1334 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1339 App::get_config_file(const synfig::String& file)
1341 return Glib::build_filename(get_user_app_directory(),file);
1344 #define SCALE_FACTOR (1280)
1345 //! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size
1347 App::set_recent_file_window_size(etl::handle<Instance> instance)
1349 int screen_w(Gdk::screen_width());
1350 int screen_h(Gdk::screen_height());
1352 const std::string &canvas_window_size = *recent_files_window_size.begin();
1354 if(canvas_window_size.empty())
1357 synfig::String::size_type current=0;
1358 bool seen_root(false), shown_non_root(false);
1360 while(current != synfig::String::npos)
1362 // find end of first field (canvas) or return
1363 synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
1364 if(separator == synfig::String::npos) break;
1367 synfig::Canvas::Handle canvas;
1369 canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current));
1371 catch(Exception::IDNotFound) {
1372 // can't find the canvas; skip to the next canvas or return
1373 separator = canvas_window_size.find_first_of('\t', current);
1374 if(separator == synfig::String::npos) return;
1375 current = separator+1;
1379 if (canvas->is_root())
1382 shown_non_root = true;
1384 // check that we have the tab character the ends this canvas' data or return
1385 current = separator+1;
1386 separator = canvas_window_size.find_first_of('\t', current);
1387 if(separator == synfig::String::npos) return;
1390 if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
1392 current = separator+1;
1396 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
1397 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
1398 x=x*screen_w/SCALE_FACTOR;
1399 y=y*screen_h/SCALE_FACTOR;
1400 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
1401 x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
1402 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
1403 y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
1405 if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
1406 if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
1408 CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
1409 canvasview->move(x,y);
1410 canvasview->resize(w*screen_w/SCALE_FACTOR,h*screen_h/SCALE_FACTOR);
1411 canvasview->present();
1413 current = separator+1;
1416 if (shown_non_root && !seen_root)
1417 instance->find_canvas_view(instance->get_canvas())->hide();
1421 App::add_recent_file(const etl::handle<Instance> instance)
1423 int screen_w(Gdk::screen_width());
1424 int screen_h(Gdk::screen_height());
1426 std::string canvas_window_size;
1428 const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
1429 Instance::CanvasViewList::const_iterator iter;
1431 for(iter=cview_list.begin();iter!=cview_list.end();iter++)
1433 if( !((*iter)->is_visible()) )
1436 etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
1437 int x_pos, y_pos, x_size, y_size;
1438 (*iter)->get_position(x_pos,y_pos);
1439 (*iter)->get_size(x_size,y_size);
1441 canvas_window_size += strprintf("%s %d %d %d %d\t",
1442 canvas->get_relative_id(canvas->get_root()).c_str(),
1443 x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h,
1444 x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
1447 add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
1452 App::add_recent_file(const std::string &file_name, const std::string &window_size)
1454 std::string filename(file_name);
1456 assert(!filename.empty());
1458 if(filename.empty())
1461 // Toss out any "hidden" files
1462 if(basename(filename)[0]=='.')
1465 // If we aren't an absolute path, turn ourselves into one
1466 if(!is_absolute_path(filename))
1467 filename=absolute_path(filename);
1469 std::string old_window_size;
1471 list<string>::iterator iter;
1472 list<string>::iterator iter_wsize;
1473 // Check to see if the file is already on the list.
1474 // If it is, then remove it from the list
1475 for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
1478 recent_files.erase(iter);
1479 old_window_size = *iter_wsize;
1480 recent_files_window_size.erase(iter_wsize);
1485 // Push the filename to the front of the list
1486 recent_files.push_front(filename);
1487 if(window_size.empty())
1488 recent_files_window_size.push_front(old_window_size);
1490 recent_files_window_size.push_front(window_size);
1492 // Clean out the files at the end of the list.
1493 while(recent_files.size()>(unsigned)get_max_recent_files())
1495 recent_files.pop_back();
1496 recent_files_window_size.pop_back();
1499 signal_recent_files_changed_();
1504 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1507 App::get_time_format()
1509 return _App_time_format;
1513 App::set_time_format(synfig::Time::Format x)
1520 App::save_settings()
1525 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1526 setlocale(LC_NUMERIC, "C");
1528 std::string filename=get_config_file("accelrc");
1529 Gtk::AccelMap::save(filename);
1532 std::string filename=get_config_file("recentfiles");
1534 std::ofstream file(filename.c_str());
1538 synfig::warning("Unable to save %s",filename.c_str());
1542 list<string>::reverse_iterator iter;
1544 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1548 std::string filename=get_config_file("recentfiles")+std::string("_window_size");
1550 std::ofstream file(filename.c_str());
1554 synfig::warning("Unable to save %s",filename.c_str());
1558 list<string>::reverse_iterator iter;
1560 for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
1564 std::string filename=get_config_file("settings");
1565 synfigapp::Main::settings().save_to_file(filename);
1566 setlocale(LC_NUMERIC,old_locale);
1570 synfig::warning("Caught exception when attempting to save settings.");
1575 App::load_settings()
1580 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1581 setlocale(LC_NUMERIC, "C");
1583 std::string filename=get_config_file("accelrc");
1584 Gtk::AccelMap::load(filename);
1587 bool window_size_broken = false;
1589 std::string filename=get_config_file("recentfiles");
1590 std::string filename_window_size=filename+std::string("_window_size");
1592 std::ifstream file(filename.c_str());
1593 std::ifstream file_window_size(filename_window_size.c_str());
1595 if(!file_window_size)
1596 window_size_broken = true;
1600 std::string recent_file;
1601 std::string recent_file_window_size;
1602 getline(file,recent_file);
1603 if(!window_size_broken)
1604 getline(file_window_size,recent_file_window_size);
1605 if(!recent_file.empty())
1607 if(!window_size_broken && !file_window_size)
1608 window_size_broken = true;
1609 if(!window_size_broken)
1610 add_recent_file(recent_file,recent_file_window_size);
1612 add_recent_file(recent_file);
1615 if(!window_size_broken && file_window_size)
1616 window_size_broken = true;
1618 if(window_size_broken)
1620 recent_files_window_size.clear();
1621 recent_files_window_size.resize(recent_files.size());
1624 std::string filename=get_config_file("settings");
1625 if(!synfigapp::Main::settings().load_from_file(filename))
1627 //std::string filename=Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),".synfigrc"));
1628 //if(!synfigapp::Main::settings().load_from_file(filename))
1630 gamma.set_gamma(1.0/2.2);
1631 reset_initial_window_configuration();
1634 setlocale(LC_NUMERIC,old_locale);
1638 synfig::warning("Caught exception when attempting to load settings.");
1643 App::reset_initial_window_configuration()
1645 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1646 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1647 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1648 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1649 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1650 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1651 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1652 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1653 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1654 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1655 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1656 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1657 #ifdef SINGLE_THREADED
1658 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1660 synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
1661 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1665 App::shutdown_request(GdkEventAny*)
1669 //return !shutdown_in_progress;
1675 if(shutdown_in_progress)return;
1678 get_ui_interface()->task(_("Quit Request"));
1681 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1685 std::list<etl::handle<Instance> >::iterator iter;
1686 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1688 if(!(*iter)->safe_close())
1692 if((*iter)->synfigapp::Instance::get_action_count())
1694 handle<synfigapp::UIInterface> uim;
1695 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1697 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1698 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1700 case synfigapp::UIInterface::RESPONSE_NO:
1702 case synfigapp::UIInterface::RESPONSE_YES:
1705 case synfigapp::UIInterface::RESPONSE_CANCEL:
1714 if((*iter)->synfigapp::Instance::is_modified())
1716 handle<synfigapp::UIInterface> uim;
1717 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1719 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() );
1720 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1722 case synfigapp::UIInterface::RESPONSE_NO:
1724 case synfigapp::UIInterface::RESPONSE_YES:
1725 (*iter)->dialog_cvs_commit();
1727 case synfigapp::UIInterface::RESPONSE_CANCEL:
1736 // This next line causes things to crash for some reason
1740 shutdown_in_progress=true;
1742 instance_list.clear();
1744 while(studio::App::events_pending())studio::App::iteration(false);
1747 auto_recover->normal_shutdown();
1749 get_ui_interface()->task(_("Quit Request sent"));
1755 dialog_setup->refresh();
1756 dialog_setup->show();
1759 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1760 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1763 //#define USE_WIN32_FILE_DIALOGS 1
1766 #ifdef USE_WIN32_FILE_DIALOGS
1767 static OPENFILENAME ofn={};
1771 #include <gdk/gdkwin32.h>
1775 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1777 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1779 #ifdef USE_WIN32_FILE_DIALOGS
1780 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1782 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1783 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1784 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1786 ofn.lStructSize=sizeof(OPENFILENAME);
1787 ofn.hwndOwner = hWnd;
1788 ofn.hInstance = hInstance;
1789 ofn.lpstrFilter = szFilter;
1790 // ofn.lpstrCustomFilter=NULL;
1791 // ofn.nMaxCustFilter=0;
1792 // ofn.nFilterIndex=0;
1793 // ofn.lpstrFile=NULL;
1794 ofn.nMaxFile=MAX_PATH;
1795 // ofn.lpstrFileTitle=NULL;
1796 // ofn.lpstrInitialDir=NULL;
1797 // ofn.lpstrTitle=NULL;
1798 ofn.Flags=OFN_HIDEREADONLY;
1799 // ofn.nFileOffset=0;
1800 // ofn.nFileExtension=0;
1801 ofn.lpstrDefExt=TEXT("sif");
1802 // ofn.lCustData = 0l;
1804 // ofn.lpTemplateName=NULL;
1806 CHAR szFilename[MAX_PATH];
1808 strcpy(szFilename,filename.c_str());
1809 strcpy(szTitle,title.c_str());
1811 ofn.lpstrFile=szFilename;
1812 ofn.lpstrFileTitle=szTitle;
1814 if(GetOpenFileName(&ofn))
1816 filename=szFilename;
1822 synfig::String prev_path;
1824 if(!_preferences.get_value(preference, prev_path))
1827 prev_path = absolute_path(prev_path);
1829 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1831 dialog->set_current_folder(prev_path);
1832 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1833 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1835 if (filename.empty())
1836 dialog->set_filename(prev_path);
1837 else if (is_absolute_path(filename))
1838 dialog->set_filename(filename);
1840 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1842 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1843 filename = dialog->get_filename();
1844 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1845 _preferences.set_value(preference, dirname(filename));
1859 GtkWidget *fileselection;
1860 fileselection = gtk_file_selection_new(title.c_str());
1863 if(basename(filename)==filename)
1865 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1868 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1870 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1872 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1873 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1875 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1876 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1878 gtk_widget_show(fileselection);
1886 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1887 _preferences.set_value(preference,dirname(filename));
1891 gtk_widget_destroy(fileselection);
1894 gtk_widget_destroy(fileselection);
1901 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1903 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1905 #if USE_WIN32_FILE_DIALOGS
1906 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1908 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1909 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1910 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1912 ofn.lStructSize=sizeof(OPENFILENAME);
1913 ofn.hwndOwner = hWnd;
1914 ofn.hInstance = hInstance;
1915 ofn.lpstrFilter = szFilter;
1916 // ofn.lpstrCustomFilter=NULL;
1917 // ofn.nMaxCustFilter=0;
1918 // ofn.nFilterIndex=0;
1919 // ofn.lpstrFile=NULL;
1920 ofn.nMaxFile=MAX_PATH;
1921 // ofn.lpstrFileTitle=NULL;
1922 // ofn.lpstrInitialDir=NULL;
1923 // ofn.lpstrTitle=NULL;
1924 ofn.Flags=OFN_OVERWRITEPROMPT;
1925 // ofn.nFileOffset=0;
1926 // ofn.nFileExtension=0;
1927 ofn.lpstrDefExt=TEXT("sif");
1928 // ofn.lCustData = 0l;
1930 // ofn.lpTemplateName=NULL;
1932 CHAR szFilename[MAX_PATH];
1934 strcpy(szFilename,filename.c_str());
1935 strcpy(szTitle,title.c_str());
1937 ofn.lpstrFile=szFilename;
1938 ofn.lpstrFileTitle=szTitle;
1940 if(GetSaveFileName(&ofn))
1942 filename=szFilename;
1943 _preferences.set_value(preference,dirname(filename));
1948 synfig::String prev_path;
1950 if(!_preferences.get_value(preference, prev_path))
1953 prev_path = absolute_path(prev_path);
1955 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1957 dialog->set_current_folder(prev_path);
1958 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1959 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1961 Widget_Enum *file_type_enum = 0;
1962 if (preference == ANIMATION_DIR_PREFERENCE)
1964 file_type_enum = manage(new Widget_Enum());
1965 file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
1966 .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
1967 .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
1968 .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
1969 file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
1971 Gtk::HBox *hbox = manage(new Gtk::HBox);
1972 hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
1973 hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
1976 dialog->set_extra_widget(*hbox);
1979 if (filename.empty())
1980 dialog->set_filename(prev_path);
1983 std::string full_path;
1984 if (is_absolute_path(filename))
1985 full_path = filename;
1987 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1989 // select the file if it exists
1990 dialog->set_filename(full_path);
1992 // if the file doesn't exist, put its name into the filename box
1994 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1995 dialog->set_current_name(basename(filename));
1998 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1999 if (preference == ANIMATION_DIR_PREFERENCE)
2000 set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
2001 filename = dialog->get_filename();
2002 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
2003 _preferences.set_value(preference, dirname(filename));
2014 App::dialog_error_blocking(const std::string &title, const std::string &message)
2016 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2017 dialog.set_title(title);
2023 App::dialog_warning_blocking(const std::string &title, const std::string &message)
2025 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
2026 dialog.set_title(title);
2032 App::dialog_yes_no(const std::string &title, const std::string &message)
2037 true // use_separator
2039 Gtk::Label label(message);
2042 dialog.get_vbox()->pack_start(label);
2043 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2044 dialog.add_button(Gtk::StockID("gtk-no"),0);
2046 return dialog.run();
2050 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
2055 true // use_separator
2057 Gtk::Label label(message);
2060 dialog.get_vbox()->pack_start(label);
2061 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2062 dialog.add_button(Gtk::StockID("gtk-no"),0);
2063 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
2065 return dialog.run();
2069 App::dialog_not_implemented()
2071 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2072 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
2077 try_open_url(const std::string &url)
2080 return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
2082 gchar* argv[3] = {strdup(App::browser_command.c_str()), strdup(url.c_str()), NULL};
2084 GError* gerror = NULL;
2086 retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &gerror);
2092 error(_("Could not execute specified web browser: %s"), gerror->message);
2093 g_error_free(gerror);
2104 if (!try_open_url("http://synfig.org/Documentation"))
2106 Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
2107 dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
2108 dialog.set_title(_("Help"));
2114 App::open_url(const std::string &url)
2120 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
2125 true // use_separator
2127 Gtk::Label label(message);
2129 dialog.get_vbox()->pack_start(label);
2132 entry.set_text(text);
2134 entry.set_activates_default(true);
2135 dialog.get_vbox()->pack_start(entry);
2137 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
2138 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
2139 dialog.set_default_response(Gtk::RESPONSE_OK);
2140 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
2143 if(dialog.run()!=Gtk::RESPONSE_OK)
2146 text=entry.get_text();
2155 App::open(std::string filename)
2157 return open_as(filename,filename);
2160 // this is called from autorecover.cpp:
2161 // App::open_as(get_shadow_file_name(filename),filename)
2162 // other than that, 'filename' and 'as' are the same
2164 App::open_as(std::string filename,std::string as)
2167 char long_name[1024];
2168 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2169 // when called from autorecover.cpp, filename doesn't exist, and so long_name is empty
2170 // don't use it if that's the case
2171 if (long_name[0] != '\0')
2177 OneMoment one_moment;
2179 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2180 if(canvas && get_instance(canvas))
2182 get_instance(canvas)->find_canvas_view(canvas)->present();
2183 info("%s is already open", filename.c_str());
2184 // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2189 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2191 if (as.find(DEFAULT_FILENAME_PREFIX) != 0)
2192 add_recent_file(as);
2194 handle<Instance> instance(Instance::create(canvas));
2197 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2199 set_recent_file_window_size(instance);
2203 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)")))
2204 instance->dialog_cvs_update();
2209 dialog_error_blocking(_("Error"), x);
2214 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2225 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2227 String file_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
2228 canvas->set_name(file_name);
2229 file_name += ".sifz";
2231 canvas->rend_desc().set_frame_rate(24.0);
2232 canvas->rend_desc().set_time_start(0.0);
2233 canvas->rend_desc().set_time_end(5.0);
2234 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2235 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2236 canvas->rend_desc().set_tl(Vector(-4,2.25));
2237 canvas->rend_desc().set_br(Vector(4,-2.25));
2238 canvas->rend_desc().set_w(480);
2239 canvas->rend_desc().set_h(270);
2240 canvas->rend_desc().set_antialias(1);
2241 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2242 canvas->set_file_name(file_name);
2244 handle<Instance> instance = Instance::create(canvas);
2246 if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES"))
2247 instance->find_canvas_view(canvas)->canvas_properties.present();
2251 App::dialog_open(string filename)
2253 if (filename.empty())
2256 while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE))
2258 // If the filename still has wildcards, then we should
2259 // continue looking for the file we want
2260 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2266 get_ui_interface()->error(_("Unable to open file"));
2271 App::set_selected_instance(etl::loose_handle<Instance> instance)
2273 /* if(get_selected_instance()==instance)
2275 selected_instance=instance;
2276 signal_instance_selected()(instance);
2282 selected_instance=instance;
2283 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2287 instance->focus(instance->get_canvas());
2290 set_selected_canvas_view(0);
2292 signal_instance_selected()(instance);
2296 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2298 selected_canvas_view=canvas_view;
2299 signal_canvas_view_focus()(selected_canvas_view);
2302 selected_instance=canvas_view->get_instance();
2303 signal_instance_selected()(canvas_view->get_instance());
2306 if(get_selected_canvas_view()==canvas_view)
2308 signal_canvas_view_focus()(selected_canvas_view);
2309 signal_instance_selected()(canvas_view->get_instance());
2312 selected_canvas_view=canvas_view;
2313 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2314 set_selected_instance(canvas_view->get_instance());
2315 signal_canvas_view_focus()(selected_canvas_view);
2319 etl::loose_handle<Instance>
2320 App::get_instance(etl::handle<synfig::Canvas> canvas)
2322 if(!canvas) return 0;
2323 canvas=canvas->get_root();
2325 std::list<etl::handle<Instance> >::iterator iter;
2326 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2328 if((*iter)->get_canvas()==canvas)
2344 if(selected_instance)
2345 selected_instance->undo();
2351 if(selected_instance)
2352 selected_instance->redo();
2356 studio::App::get_base_path()
2358 return app_base_path_;