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.set_can_self_destruct(false);
1074 splash_screen.show();
1076 shutdown_in_progress=false;
1077 SuperCallback synfig_init_cb(splash_screen.get_callback(),0,9000,10000);
1078 SuperCallback studio_init_cb(splash_screen.get_callback(),9000,10000,10000);
1080 // Initialize the Synfig library
1081 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1084 get_ui_interface()->error(_("Failed to initialize synfig!"));
1088 // add the preferences to the settings
1089 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1093 studio_init_cb.task(_("Init UI Manager..."));
1094 App::ui_manager_=studio::UIManager::create();
1097 studio_init_cb.task(_("Init Dock Manager..."));
1098 dock_manager=new studio::DockManager();
1100 studio_init_cb.task(_("Init State Manager..."));
1101 state_manager=new StateManager();
1103 studio_init_cb.task(_("Init Toolbox..."));
1104 toolbox=new studio::Toolbox();
1106 studio_init_cb.task(_("Init About Dialog..."));
1107 about=new studio::About();
1109 studio_init_cb.task(_("Init Tool Options..."));
1110 dialog_tool_options=new studio::Dialog_ToolOptions();
1111 dock_manager->register_dockable(*dialog_tool_options);
1113 studio_init_cb.task(_("Init History..."));
1114 dock_history=new studio::Dock_History();
1115 dock_manager->register_dockable(*dock_history);
1117 studio_init_cb.task(_("Init Canvases..."));
1118 dock_canvases=new studio::Dock_Canvases();
1119 dock_manager->register_dockable(*dock_canvases);
1121 studio_init_cb.task(_("Init Keyframes..."));
1122 dock_keyframes=new studio::Dock_Keyframes();
1123 dock_manager->register_dockable(*dock_keyframes);
1125 studio_init_cb.task(_("Init Layers..."));
1126 dock_layers=new studio::Dock_Layers();
1127 dock_manager->register_dockable(*dock_layers);
1129 studio_init_cb.task(_("Init Params..."));
1130 dock_params=new studio::Dock_Params();
1131 dock_manager->register_dockable(*dock_params);
1133 studio_init_cb.task(_("Init MetaData..."));
1134 dock_meta_data=new studio::Dock_MetaData();
1135 dock_manager->register_dockable(*dock_meta_data);
1137 studio_init_cb.task(_("Init Children..."));
1138 dock_children=new studio::Dock_Children();
1139 dock_manager->register_dockable(*dock_children);
1141 studio_init_cb.task(_("Init Info..."));
1142 dock_info = new studio::Dock_Info();
1143 dock_manager->register_dockable(*dock_info);
1145 studio_init_cb.task(_("Init Navigator..."));
1146 dock_navigator = new studio::Dock_Navigator();
1147 dock_manager->register_dockable(*dock_navigator);
1149 studio_init_cb.task(_("Init Timetrack..."));
1150 dock_timetrack = new studio::Dock_Timetrack();
1151 dock_manager->register_dockable(*dock_timetrack);
1153 studio_init_cb.task(_("Init Curve Editor..."));
1154 dock_curves = new studio::Dock_Curves();
1155 dock_manager->register_dockable(*dock_curves);
1157 studio_init_cb.task(_("Init Layer Groups..."));
1158 dock_layer_groups = new studio::Dock_LayerGroups();
1159 dock_manager->register_dockable(*dock_layer_groups);
1162 studio_init_cb.task(_("Init Color Dialog..."));
1163 dialog_color=new studio::Dialog_Color();
1165 studio_init_cb.task(_("Init Gradient Dialog..."));
1166 dialog_gradient=new studio::Dialog_Gradient();
1168 studio_init_cb.task(_("Init DeviceTracker..."));
1169 device_tracker=new studio::DeviceTracker();
1171 studio_init_cb.task(_("Init Tools..."));
1174 state_manager->add_state(&state_normal);
1175 state_manager->add_state(&state_smooth_move);
1176 state_manager->add_state(&state_scale);
1177 state_manager->add_state(&state_rotate);
1178 studio_init_cb.task(_("Init ModMirror...")); module_list_.push_back(new ModMirror()); module_list_.back()->start();
1181 state_manager->add_state(&state_bline);
1182 state_manager->add_state(&state_circle);
1183 state_manager->add_state(&state_rectangle);
1184 state_manager->add_state(&state_gradient);
1185 if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks
1188 if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw); // Enabled for now. Let's see whether they're good enough yet.
1189 if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
1190 state_manager->add_state(&state_fill);
1191 state_manager->add_state(&state_eyedrop);
1192 state_manager->add_state(&state_zoom);
1194 // Disabled by default - it doesn't work properly?
1195 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1197 studio_init_cb.task(_("Init ModPalette..."));
1198 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1200 studio_init_cb.task(_("Init Setup Dialog..."));
1201 dialog_setup=new studio::Dialog_Setup();
1203 studio_init_cb.task(_("Init Input Dialog..."));
1204 dialog_input=new Gtk::InputDialog();
1205 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1206 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1208 studio_init_cb.task(_("Init auto recovery..."));
1209 auto_recover=new AutoRecover();
1211 studio_init_cb.amount_complete(9250,10000);
1212 studio_init_cb.task(_("Loading Settings..."));
1214 studio_init_cb.task(_("Checking auto-recover..."));
1216 studio_init_cb.amount_complete(9900,10000);
1218 bool opened_any = false;
1219 if(auto_recover->recovery_needed())
1221 splash_screen.hide();
1222 if (get_ui_interface()->yes_no(_("Auto Recovery"),
1223 _("Synfig Studio seems to have crashed\n"
1224 "before you could save all your files.\n"
1225 "Would you like to re-open those files\n"
1226 "and recover your unsaved changes?")) ==
1227 synfigapp::UIInterface::RESPONSE_YES)
1229 int number_recovered;
1230 if(!auto_recover->recover(number_recovered))
1231 if (number_recovered)
1232 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1234 get_ui_interface()->error(_("Unable to recover from previous crash"));
1236 get_ui_interface()->error(
1237 _("Synfig Studio has attempted to recover\n"
1238 "from a previous crash. The files that it has\n"
1239 "recovered are NOT YET SAVED. It would be a good\n"
1240 "idea to review them and save them now."));
1242 if (number_recovered)
1245 splash_screen.show();
1248 // Look for any files given on the command line,
1249 // and load them if found.
1250 for(;*argc>=1;(*argc)--)
1251 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1253 studio_init_cb.task(_("Loading files..."));
1254 splash_screen.hide();
1255 open((*argv)[*argc]);
1257 splash_screen.show();
1260 // if no file was specified to be opened, create a new document to help new users get started more easily
1261 if (!opened_any && !getenv("SYNFIG_DISABLE_AUTOMATIC_DOCUMENT_CREATION"))
1264 studio_init_cb.task(_("Done."));
1265 studio_init_cb.amount_complete(10000,10000);
1271 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x);
1275 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1279 StateManager* App::get_state_manager() { return state_manager; }
1283 shutdown_in_progress=true;
1287 synfigapp::Main::settings().remove_domain("pref");
1289 selected_instance=0;
1291 // Unload all of the modules
1292 for(;!module_list_.empty();module_list_.pop_back())
1295 delete state_manager;
1299 delete auto_recover;
1305 // studio::App::iteration(false);
1309 // studio::App::iteration(false);
1311 // studio::App::iteration(false);
1313 delete dialog_setup;
1315 delete dialog_gradient;
1317 delete dialog_color;
1319 delete dialog_input;
1321 delete dock_manager;
1323 instance_list.clear();
1325 // studio::App::iteration(false);
1329 App::get_user_app_directory()
1331 //! \todo do we need locale_from_utf8() on non-Windows boxes too? (bug #1837445)
1333 return Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR));
1335 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1340 App::get_config_file(const synfig::String& file)
1342 return Glib::build_filename(get_user_app_directory(),file);
1345 #define SCALE_FACTOR (1280)
1346 //! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size
1348 App::set_recent_file_window_size(etl::handle<Instance> instance)
1350 int screen_w(Gdk::screen_width());
1351 int screen_h(Gdk::screen_height());
1353 const std::string &canvas_window_size = *recent_files_window_size.begin();
1355 if(canvas_window_size.empty())
1358 synfig::String::size_type current=0;
1359 bool seen_root(false), shown_non_root(false);
1361 while(current != synfig::String::npos)
1363 // find end of first field (canvas) or return
1364 synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current);
1365 if(separator == synfig::String::npos) break;
1368 synfig::Canvas::Handle canvas;
1370 canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current));
1372 catch(Exception::IDNotFound) {
1373 // can't find the canvas; skip to the next canvas or return
1374 separator = canvas_window_size.find_first_of('\t', current);
1375 if(separator == synfig::String::npos) return;
1376 current = separator+1;
1380 if (canvas->is_root())
1383 shown_non_root = true;
1385 // check that we have the tab character the ends this canvas' data or return
1386 current = separator+1;
1387 separator = canvas_window_size.find_first_of('\t', current);
1388 if(separator == synfig::String::npos) return;
1391 if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h))
1393 current = separator+1;
1397 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
1398 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
1399 x=x*screen_w/SCALE_FACTOR;
1400 y=y*screen_h/SCALE_FACTOR;
1401 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
1402 x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
1403 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
1404 y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
1406 if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0;
1407 if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0;
1409 CanvasView::Handle canvasview = instance->find_canvas_view(canvas);
1410 canvasview->move(x,y);
1411 canvasview->resize(w*screen_w/SCALE_FACTOR,h*screen_h/SCALE_FACTOR);
1412 canvasview->present();
1414 current = separator+1;
1417 if (shown_non_root && !seen_root)
1418 instance->find_canvas_view(instance->get_canvas())->hide();
1422 App::add_recent_file(const etl::handle<Instance> instance)
1424 int screen_w(Gdk::screen_width());
1425 int screen_h(Gdk::screen_height());
1427 std::string canvas_window_size;
1429 const Instance::CanvasViewList& cview_list = instance->canvas_view_list();
1430 Instance::CanvasViewList::const_iterator iter;
1432 for(iter=cview_list.begin();iter!=cview_list.end();iter++)
1434 if( !((*iter)->is_visible()) )
1437 etl::handle<synfig::Canvas> canvas = (*iter)->get_canvas();
1438 int x_pos, y_pos, x_size, y_size;
1439 (*iter)->get_position(x_pos,y_pos);
1440 (*iter)->get_size(x_size,y_size);
1442 canvas_window_size += strprintf("%s %d %d %d %d\t",
1443 canvas->get_relative_id(canvas->get_root()).c_str(),
1444 x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h,
1445 x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h);
1448 add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size);
1453 App::add_recent_file(const std::string &file_name, const std::string &window_size)
1455 std::string filename(file_name);
1457 assert(!filename.empty());
1459 if(filename.empty())
1462 // Toss out any "hidden" files
1463 if(basename(filename)[0]=='.')
1466 // If we aren't an absolute path, turn ourselves into one
1467 if(!is_absolute_path(filename))
1468 filename=absolute_path(filename);
1470 std::string old_window_size;
1472 list<string>::iterator iter;
1473 list<string>::iterator iter_wsize;
1474 // Check to see if the file is already on the list.
1475 // If it is, then remove it from the list
1476 for(iter=recent_files.begin(), iter_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++)
1479 recent_files.erase(iter);
1480 old_window_size = *iter_wsize;
1481 recent_files_window_size.erase(iter_wsize);
1486 // Push the filename to the front of the list
1487 recent_files.push_front(filename);
1488 if(window_size.empty())
1489 recent_files_window_size.push_front(old_window_size);
1491 recent_files_window_size.push_front(window_size);
1493 // Clean out the files at the end of the list.
1494 while(recent_files.size()>(unsigned)get_max_recent_files())
1496 recent_files.pop_back();
1497 recent_files_window_size.pop_back();
1500 signal_recent_files_changed_();
1505 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1508 App::get_time_format()
1510 return _App_time_format;
1514 App::set_time_format(synfig::Time::Format x)
1521 App::save_settings()
1526 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1527 setlocale(LC_NUMERIC, "C");
1529 std::string filename=get_config_file("accelrc");
1530 Gtk::AccelMap::save(filename);
1533 std::string filename=get_config_file("recentfiles");
1535 std::ofstream file(filename.c_str());
1539 synfig::warning("Unable to save %s",filename.c_str());
1543 list<string>::reverse_iterator iter;
1545 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1549 std::string filename=get_config_file("recentfiles")+std::string("_window_size");
1551 std::ofstream file(filename.c_str());
1555 synfig::warning("Unable to save %s",filename.c_str());
1559 list<string>::reverse_iterator iter;
1561 for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++)
1565 std::string filename=get_config_file("settings");
1566 synfigapp::Main::settings().save_to_file(filename);
1567 setlocale(LC_NUMERIC,old_locale);
1571 synfig::warning("Caught exception when attempting to save settings.");
1576 App::load_settings()
1581 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1582 setlocale(LC_NUMERIC, "C");
1584 std::string filename=get_config_file("accelrc");
1585 Gtk::AccelMap::load(filename);
1588 bool window_size_broken = false;
1590 std::string filename=get_config_file("recentfiles");
1591 std::string filename_window_size=filename+std::string("_window_size");
1593 std::ifstream file(filename.c_str());
1594 std::ifstream file_window_size(filename_window_size.c_str());
1596 if(!file_window_size)
1597 window_size_broken = true;
1601 std::string recent_file;
1602 std::string recent_file_window_size;
1603 getline(file,recent_file);
1604 if(!window_size_broken)
1605 getline(file_window_size,recent_file_window_size);
1606 if(!recent_file.empty())
1608 if(!window_size_broken && !file_window_size)
1609 window_size_broken = true;
1610 if(!window_size_broken)
1611 add_recent_file(recent_file,recent_file_window_size);
1613 add_recent_file(recent_file);
1616 if(!window_size_broken && file_window_size)
1617 window_size_broken = true;
1619 if(window_size_broken)
1621 recent_files_window_size.clear();
1622 recent_files_window_size.resize(recent_files.size());
1625 std::string filename=get_config_file("settings");
1626 if(!synfigapp::Main::settings().load_from_file(filename))
1628 //std::string filename=Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),".synfigrc"));
1629 //if(!synfigapp::Main::settings().load_from_file(filename))
1631 gamma.set_gamma(1.0/2.2);
1632 reset_initial_window_configuration();
1635 setlocale(LC_NUMERIC,old_locale);
1639 synfig::warning("Caught exception when attempting to load settings.");
1644 App::reset_initial_window_configuration()
1646 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1647 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1648 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1649 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1650 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1651 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1652 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1653 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1654 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1655 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1656 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1657 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1658 #ifdef SINGLE_THREADED
1659 synfigapp::Main::settings().set_value("pref.single_threaded","0");
1661 synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
1662 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1666 App::shutdown_request(GdkEventAny*)
1670 //return !shutdown_in_progress;
1676 if(shutdown_in_progress)return;
1679 get_ui_interface()->task(_("Quit Request"));
1682 dialog_error_blocking(_("Cannot quit!"),_("Tasks are currently running.\nPlease cancel the current tasks and try again"));
1686 std::list<etl::handle<Instance> >::iterator iter;
1687 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1689 if(!(*iter)->safe_close())
1693 if((*iter)->synfigapp::Instance::get_action_count())
1695 handle<synfigapp::UIInterface> uim;
1696 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1698 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1699 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1701 case synfigapp::UIInterface::RESPONSE_NO:
1703 case synfigapp::UIInterface::RESPONSE_YES:
1706 case synfigapp::UIInterface::RESPONSE_CANCEL:
1715 if((*iter)->synfigapp::Instance::is_modified())
1717 handle<synfigapp::UIInterface> uim;
1718 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1720 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() );
1721 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1723 case synfigapp::UIInterface::RESPONSE_NO:
1725 case synfigapp::UIInterface::RESPONSE_YES:
1726 (*iter)->dialog_cvs_commit();
1728 case synfigapp::UIInterface::RESPONSE_CANCEL:
1737 // This next line causes things to crash for some reason
1741 shutdown_in_progress=true;
1743 instance_list.clear();
1745 while(studio::App::events_pending())studio::App::iteration(false);
1748 auto_recover->normal_shutdown();
1750 get_ui_interface()->task(_("Quit Request sent"));
1756 dialog_setup->refresh();
1757 dialog_setup->show();
1760 gint Signal_Open_Ok(GtkWidget */*widget*/, int *val){*val=1;return 0;}
1761 gint Signal_Open_Cancel(GtkWidget */*widget*/, int *val){*val=2;return 0;}
1764 //#define USE_WIN32_FILE_DIALOGS 1
1767 #ifdef USE_WIN32_FILE_DIALOGS
1768 static OPENFILENAME ofn={};
1772 #include <gdk/gdkwin32.h>
1776 App::dialog_open_file(const std::string &title, std::string &filename, std::string preference)
1778 info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1780 #ifdef USE_WIN32_FILE_DIALOGS
1781 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1783 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1784 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1785 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1787 ofn.lStructSize=sizeof(OPENFILENAME);
1788 ofn.hwndOwner = hWnd;
1789 ofn.hInstance = hInstance;
1790 ofn.lpstrFilter = szFilter;
1791 // ofn.lpstrCustomFilter=NULL;
1792 // ofn.nMaxCustFilter=0;
1793 // ofn.nFilterIndex=0;
1794 // ofn.lpstrFile=NULL;
1795 ofn.nMaxFile=MAX_PATH;
1796 // ofn.lpstrFileTitle=NULL;
1797 // ofn.lpstrInitialDir=NULL;
1798 // ofn.lpstrTitle=NULL;
1799 ofn.Flags=OFN_HIDEREADONLY;
1800 // ofn.nFileOffset=0;
1801 // ofn.nFileExtension=0;
1802 ofn.lpstrDefExt=TEXT("sif");
1803 // ofn.lCustData = 0l;
1805 // ofn.lpTemplateName=NULL;
1807 CHAR szFilename[MAX_PATH];
1809 strcpy(szFilename,filename.c_str());
1810 strcpy(szTitle,title.c_str());
1812 ofn.lpstrFile=szFilename;
1813 ofn.lpstrFileTitle=szTitle;
1815 if(GetOpenFileName(&ofn))
1817 filename=szFilename;
1823 synfig::String prev_path;
1825 if(!_preferences.get_value(preference, prev_path))
1828 prev_path = absolute_path(prev_path);
1830 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_OPEN);
1832 dialog->set_current_folder(prev_path);
1833 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1834 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1836 if (filename.empty())
1837 dialog->set_filename(prev_path);
1838 else if (is_absolute_path(filename))
1839 dialog->set_filename(filename);
1841 dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
1843 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
1844 filename = dialog->get_filename();
1845 info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str());
1846 _preferences.set_value(preference, dirname(filename));
1860 GtkWidget *fileselection;
1861 fileselection = gtk_file_selection_new(title.c_str());
1864 if(basename(filename)==filename)
1866 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
1869 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1871 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1873 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1874 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1876 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1877 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1879 gtk_widget_show(fileselection);
1887 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1888 _preferences.set_value(preference,dirname(filename));
1892 gtk_widget_destroy(fileselection);
1895 gtk_widget_destroy(fileselection);
1902 App::dialog_save_file(const std::string &title, std::string &filename, std::string preference)
1904 info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str());
1906 #if USE_WIN32_FILE_DIALOGS
1907 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1909 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1910 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1911 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1913 ofn.lStructSize=sizeof(OPENFILENAME);
1914 ofn.hwndOwner = hWnd;
1915 ofn.hInstance = hInstance;
1916 ofn.lpstrFilter = szFilter;
1917 // ofn.lpstrCustomFilter=NULL;
1918 // ofn.nMaxCustFilter=0;
1919 // ofn.nFilterIndex=0;
1920 // ofn.lpstrFile=NULL;
1921 ofn.nMaxFile=MAX_PATH;
1922 // ofn.lpstrFileTitle=NULL;
1923 // ofn.lpstrInitialDir=NULL;
1924 // ofn.lpstrTitle=NULL;
1925 ofn.Flags=OFN_OVERWRITEPROMPT;
1926 // ofn.nFileOffset=0;
1927 // ofn.nFileExtension=0;
1928 ofn.lpstrDefExt=TEXT("sif");
1929 // ofn.lCustData = 0l;
1931 // ofn.lpTemplateName=NULL;
1933 CHAR szFilename[MAX_PATH];
1935 strcpy(szFilename,filename.c_str());
1936 strcpy(szTitle,title.c_str());
1938 ofn.lpstrFile=szFilename;
1939 ofn.lpstrFileTitle=szTitle;
1941 if(GetSaveFileName(&ofn))
1943 filename=szFilename;
1944 _preferences.set_value(preference,dirname(filename));
1949 synfig::String prev_path;
1951 if(!_preferences.get_value(preference, prev_path))
1954 prev_path = absolute_path(prev_path);
1956 Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(title, Gtk::FILE_CHOOSER_ACTION_SAVE);
1958 dialog->set_current_folder(prev_path);
1959 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1960 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1962 Widget_Enum *file_type_enum = 0;
1963 if (preference == ANIMATION_DIR_PREFERENCE)
1965 file_type_enum = manage(new Widget_Enum());
1966 file_type_enum->set_param_desc(ParamDesc().set_hint("enum")
1967 .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", strprintf("0.61.08 (%s)", _("current")))
1968 .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07")
1969 .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older"))));
1970 file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version
1972 Gtk::HBox *hbox = manage(new Gtk::HBox);
1973 hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0);
1974 hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0);
1977 dialog->set_extra_widget(*hbox);
1980 if (filename.empty())
1981 dialog->set_filename(prev_path);
1984 std::string full_path;
1985 if (is_absolute_path(filename))
1986 full_path = filename;
1988 full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename;
1990 // select the file if it exists
1991 dialog->set_filename(full_path);
1993 // if the file doesn't exist, put its name into the filename box
1995 if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT)
1996 dialog->set_current_name(basename(filename));
1999 if(dialog->run() == GTK_RESPONSE_ACCEPT) {
2000 if (preference == ANIMATION_DIR_PREFERENCE)
2001 set_file_version(synfig::ReleaseVersion(file_type_enum->get_value()));
2002 filename = dialog->get_filename();
2003 info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str());
2004 _preferences.set_value(preference, dirname(filename));
2015 App::dialog_error_blocking(const std::string &title, const std::string &message)
2017 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2018 dialog.set_title(title);
2024 App::dialog_warning_blocking(const std::string &title, const std::string &message)
2026 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
2027 dialog.set_title(title);
2033 App::dialog_yes_no(const std::string &title, const std::string &message)
2038 true // use_separator
2040 Gtk::Label label(message);
2043 dialog.get_vbox()->pack_start(label);
2044 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2045 dialog.add_button(Gtk::StockID("gtk-no"),0);
2047 return dialog.run();
2051 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
2056 true // use_separator
2058 Gtk::Label label(message);
2061 dialog.get_vbox()->pack_start(label);
2062 dialog.add_button(Gtk::StockID("gtk-yes"),1);
2063 dialog.add_button(Gtk::StockID("gtk-no"),0);
2064 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
2066 return dialog.run();
2070 App::dialog_not_implemented()
2072 Gtk::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
2073 dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented."));
2078 try_open_url(const std::string &url)
2081 return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW);
2083 gchar* argv[3] = {strdup(App::browser_command.c_str()), strdup(url.c_str()), NULL};
2085 GError* gerror = NULL;
2087 retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &gerror);
2093 error(_("Could not execute specified web browser: %s"), gerror->message);
2094 g_error_free(gerror);
2105 if (!try_open_url("http://synfig.org/Documentation"))
2107 Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true);
2108 dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://www.synfig.org/Documentation"));
2109 dialog.set_title(_("Help"));
2115 App::open_url(const std::string &url)
2121 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
2126 true // use_separator
2128 Gtk::Label label(message);
2130 dialog.get_vbox()->pack_start(label);
2133 entry.set_text(text);
2135 entry.set_activates_default(true);
2136 dialog.get_vbox()->pack_start(entry);
2138 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
2139 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
2140 dialog.set_default_response(Gtk::RESPONSE_OK);
2141 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
2144 if(dialog.run()!=Gtk::RESPONSE_OK)
2147 text=entry.get_text();
2156 App::open(std::string filename)
2158 return open_as(filename,filename);
2161 // this is called from autorecover.cpp:
2162 // App::open_as(get_shadow_file_name(filename),filename)
2163 // other than that, 'filename' and 'as' are the same
2165 App::open_as(std::string filename,std::string as)
2168 char long_name[1024];
2169 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2170 // when called from autorecover.cpp, filename doesn't exist, and so long_name is empty
2171 // don't use it if that's the case
2172 if (long_name[0] != '\0')
2178 OneMoment one_moment;
2180 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2181 if(canvas && get_instance(canvas))
2183 get_instance(canvas)->find_canvas_view(canvas)->present();
2184 info("%s is already open", filename.c_str());
2185 // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2190 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
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_;