1 /* === S I N F G =========================================================== */
5 ** $Id: app.cpp,v 1.10 2005/01/17 06:31:12 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
34 #include <gtkmm/fileselection.h>
35 #include <gtkmm/dialog.h>
36 #include <gtkmm/label.h>
37 #include <gtkmm/stock.h>
38 #include <gtkmm/stockitem.h>
39 #include <gtkmm/iconsource.h>
40 #include <gtkmm/inputdialog.h>
41 #include <gtkmm/accelmap.h>
42 #include <gtkmm/uimanager.h>
46 #include <sinfg/loadcanvas.h>
51 #include "canvasview.h"
52 #include "dialog_setup.h"
53 #include "dialog_gradient.h"
54 #include "dialog_color.h"
57 #include "onemoment.h"
59 #include "dockmanager.h"
61 #include "state_eyedrop.h"
62 #include "state_normal.h"
63 #include "state_draw.h"
64 #include "state_fill.h"
65 #include "state_bline.h"
66 #include "state_polygon.h"
67 #include "state_sketch.h"
68 #include "state_gradient.h"
69 #include "state_circle.h"
70 #include "state_rectangle.h"
71 #include "state_smoothmove.h"
72 #include "state_scale.h"
73 #include "state_width.h"
74 #include "state_rotate.h"
75 #include "state_zoom.h"
77 #include "devicetracker.h"
78 #include "dialog_tooloptions.h"
80 #include "autorecover.h"
82 #include <sinfgapp/settings.h>
83 #include "dock_history.h"
84 #include "dock_canvases.h"
85 #include "dock_keyframes.h"
86 #include "dock_layers.h"
87 #include "dock_params.h"
88 #include "dock_metadata.h"
89 #include "dock_children.h"
90 #include "dock_info.h"
91 #include "dock_navigator.h"
92 #include "dock_layergroups.h"
93 #include "dock_timetrack.h"
94 #include "dock_curves.h"
96 #include "mod_palette/mod_palette.h"
97 #include "mod_mirror/mod_mirror.h"
105 #include "statemanager.h"
114 #include <gtkmm/accelmap.h>
118 /* === U S I N G =========================================================== */
122 using namespace sinfg;
123 using namespace studio;
125 /* === M A C R O S ========================================================= */
128 #define DPM2DPI(x) (float(x)/39.3700787402f)
129 #define DPI2DPM(x) (float(x)*39.3700787402f)
135 # define IMAGE_DIR "share\\pixmaps"
140 # define IMAGE_DIR "/usr/local/share/pixmaps"
144 # define IMAGE_EXT "tif"
147 #include <sinfgapp/main.h>
149 /* === S I G N A L S ======================================================= */
151 static sigc::signal<void> signal_present_all_;
153 App::signal_present_all() { return signal_present_all_; }
155 static sigc::signal<void> signal_recent_files_changed_;
157 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
159 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
160 sigc::signal<void,etl::loose_handle<CanvasView> >&
161 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
163 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
164 sigc::signal<void,etl::handle<Instance> >&
165 App::signal_instance_selected() { return signal_instance_selected_; }
167 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
168 sigc::signal<void,etl::handle<Instance> >&
169 App::signal_instance_created() { return signal_instance_created_; }
171 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
172 sigc::signal<void,etl::handle<Instance> >&
173 App::signal_instance_deleted() { return signal_instance_deleted_; }
175 /* === G L O B A L S ======================================================= */
177 static std::list<std::string> recent_files;
178 const std::list<std::string>& App::get_recent_files() { return recent_files; }
180 int App::Busy::count;
181 bool App::shutdown_in_progress;
183 sinfg::Gamma App::gamma;
185 Glib::RefPtr<studio::UIManager> App::ui_manager_;
187 sinfg::Distance::System App::distance_system;
189 studio::Dialog_Setup* App::dialog_setup;
191 etl::handle< studio::ModPalette > mod_palette_;
192 //studio::Dialog_Palette* App::dialog_palette;
194 std::list<etl::handle<Instance> > App::instance_list;
196 static etl::handle<sinfgapp::UIInterface> ui_interface_;
197 const etl::handle<sinfgapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
199 etl::handle<Instance> App::selected_instance;
200 etl::handle<CanvasView> App::selected_canvas_view;
202 studio::Toolbox *studio::App::toolbox=NULL;
204 studio::AutoRecover *studio::App::auto_recover=NULL;
206 studio::IPC *ipc=NULL;
208 studio::DockManager* studio::App::dock_manager=0;
210 studio::DeviceTracker* studio::App::device_tracker=0;
212 studio::Dialog_Gradient* studio::App::dialog_gradient;
214 studio::Dialog_Color* studio::App::dialog_color;
216 Gtk::InputDialog* studio::App::dialog_input;
218 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
220 studio::Dock_History* dock_history;
221 studio::Dock_Canvases* dock_canvases;
222 studio::Dock_Keyframes* dock_keyframes;
223 studio::Dock_Layers* dock_layers;
224 studio::Dock_Params* dock_params;
225 studio::Dock_MetaData* dock_meta_data;
226 studio::Dock_Children* dock_children;
227 studio::Dock_Info* dock_info;
228 studio::Dock_LayerGroups* dock_layer_groups;
229 studio::Dock_Navigator* dock_navigator;
230 studio::Dock_Timetrack* dock_timetrack;
231 studio::Dock_Curves* dock_curves;
233 std::list< etl::handle< studio::Module > > module_list_;
235 bool studio::App::use_colorspace_gamma=true;
237 static int max_recent_files_=25;
238 int studio::App::get_max_recent_files() { return max_recent_files_; }
239 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
241 static sinfg::String app_base_path_;
244 }; // END of namespace studio
245 studio::StateManager* state_manager;
250 class GlobalUIInterface : public sinfgapp::UIInterface
254 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
259 true // use_separator
261 Gtk::Label label(message);
264 dialog.get_vbox()->pack_start(label);
265 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
266 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
268 dialog.set_default_response(dflt);
270 return (Response)dialog.run();
272 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
277 true // use_separator
279 Gtk::Label label(message);
282 dialog.get_vbox()->pack_start(label);
283 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
284 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
285 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
287 dialog.set_default_response(dflt);
289 return (Response)dialog.run();
291 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
296 true // use_separator
298 Gtk::Label label(message);
301 dialog.get_vbox()->pack_start(label);
302 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
303 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
305 dialog.set_default_response(dflt);
307 return (Response)dialog.run();
311 task(const std::string &task)
313 std::cerr<<task<<std::endl;
314 while(studio::App::events_pending())studio::App::iteration(false);
319 error(const std::string &err)
324 true // use_separator
326 Gtk::Label label(err);
329 dialog.get_vbox()->pack_start(label);
330 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
337 warning(const std::string &err)
339 std::cerr<<"warning: "<<err<<std::endl;
340 while(studio::App::events_pending())studio::App::iteration(false);
345 amount_complete(int current, int total)
347 while(studio::App::events_pending())studio::App::iteration(false);
352 /* === P R O C E D U R E S ================================================= */
354 typedef unsigned char U8;
355 typedef unsigned short U16;
356 typedef unsigned long U32;
366 static inline U32 hash_U32(U32 i)
368 i=i*1664525+1013904223;
369 i=i*1664525+1013904223;
370 i=i*1664525+1013904223;
374 inline int v_unwind_key(V_KeyUnwound* unwound, const char* key)
377 unwound->element.serial=0;
378 unwound->element.checksum=0;
386 case '0': data=0; break;
387 case '1': data=1; break;
388 case '2': data=2; break;
389 case '3': data=3; break;
390 case '4': data=4; break;
391 case '5': data=5; break;
392 case '6': data=6; break;
393 case '7': data=7; break;
394 case '8': data=8; break;
395 case '9': data=9; break;
396 case 'a': case 'A': data=10; break;
397 case 'b': case 'B': data=11; break;
398 case 'c': case 'C': data=12; break;
399 case 'd': case 'D': data=13; break;
400 case 'e': case 'E': data=14; break;
401 case 'f': case 'F': data=15; break;
402 default: return 0; break;
405 unwound->element.checksum|=(((U32)data&3)<<bit);
406 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
411 inline int v_key_check(const char* key, U32* serial, U32 appid)
413 V_KeyUnwound unwound_key;
414 U32 appid_mask_a=hash_U32(appid);
415 U32 appid_mask_b=hash_U32(appid_mask_a);
417 if(!v_unwind_key(&unwound_key, key))
419 // Invalid characters in key
424 // Undo obfuscation pass
426 U32 next=hash_U32(unwound_key.raw[7]);
431 unwound_key.raw[i]^=(next>>24);
435 unwound_key.element.serial^=appid_mask_a;
436 unwound_key.element.checksum^=appid_mask_b;
438 *serial=unwound_key.element.serial;
440 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
444 int check_license(String basedir)
450 license_file="/usr/local/etc/.synfiglicense";
452 license_file=basedir+"\\etc\\.synfiglicense";
456 key=Glib::file_get_contents(license_file);
457 } catch (Glib::FileError) { }
459 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
461 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
465 if(!App::dialog_entry(
466 _("Synfig Studio Authentication"),
467 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
470 throw String("No License");
473 FILE* file=fopen(license_file.c_str(),"w");
476 fprintf(file,"%s",key.c_str());
480 sinfg::error("Unable to save license key!");
482 sinfg::info("License Authenticated -- Serial #%05d",serial);
488 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
490 action_group_list.push_back(action_group);
491 Gtk::UIManager::insert_action_group(action_group, pos);
495 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
497 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
498 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
499 if(*iter==action_group)
501 action_group_list.erase(iter);
502 Gtk::UIManager::remove_action_group(action_group);
505 sinfg::error("Unable to find action group");
509 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
511 ui_manager->insert_action_group(group,0);
514 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
515 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
518 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
521 if(*iter && (*iter)->get_name()!="menus")
523 sinfg::info("Removing action group "+(*iter)->get_name());
524 ui_manager->remove_action_group(*iter);
528 ui_manager->insert_action_group(group,0);
531 for(;!prev_groups.empty();prev_groups.pop_front())
533 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
534 ui_manager->insert_action_group(prev_groups.front(),1);
539 class Preferences : public sinfgapp::Settings
542 virtual bool get_value(const sinfg::String& key, sinfg::String& value)const
546 value=strprintf("%f %f %f %f",
547 App::gamma.get_gamma_r(),
548 App::gamma.get_gamma_g(),
549 App::gamma.get_gamma_b(),
550 App::gamma.get_black_level()
554 if(key=="time_format")
556 value=strprintf("%i",App::get_time_format());
559 if(key=="file_history.size")
561 value=strprintf("%i",App::get_max_recent_files());
564 if(key=="use_colorspace_gamma")
566 value=strprintf("%i",(int)App::use_colorspace_gamma);
569 if(key=="distance_system")
571 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
574 if(key=="auto_recover_backup_interval")
576 value=strprintf("%i",App::auto_recover->get_timeout());
580 return sinfgapp::Settings::get_value(key,value);
583 virtual bool set_value(const sinfg::String& key,const sinfg::String& value)
589 strscanf(value,"%f %f %f %f",
596 App::gamma.set_all(r,g,b,blk);
600 if(key=="time_format")
602 int i(atoi(value.c_str()));
603 App::set_time_format(static_cast<sinfg::Time::Format>(i));
606 if(key=="auto_recover_backup_interval")
608 int i(atoi(value.c_str()));
609 App::auto_recover->set_timeout(i);
612 if(key=="file_history.size")
614 int i(atoi(value.c_str()));
615 App::set_max_recent_files(i);
618 if(key=="use_colorspace_gamma")
620 int i(atoi(value.c_str()));
621 App::use_colorspace_gamma=i;
624 if(key=="distance_system")
626 App::distance_system=Distance::ident_system(value);;
630 return sinfgapp::Settings::set_value(key,value);
633 virtual KeyList get_key_list()const
635 KeyList ret(sinfgapp::Settings::get_key_list());
636 ret.push_back("gamma");
637 ret.push_back("time_format");
638 ret.push_back("distance_system");
639 ret.push_back("file_history.size");
640 ret.push_back("use_colorspace_gamma");
641 ret.push_back("auto_recover_backup_interval");
646 static Preferences _preferences;
651 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
653 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
655 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
657 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
658 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
659 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
660 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
661 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
662 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
663 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
664 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
665 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
666 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
667 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
668 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
670 // Add the sinfgapp actions...
671 sinfgapp::Action::Book::iterator iter;
672 for(iter=sinfgapp::Action::book().begin();iter!=sinfgapp::Action::book().end();++iter)
674 actions_action_group->add(Gtk::Action::create(
675 "action-"+iter->second.name,
676 get_action_stock_id(iter->second),
677 iter->second.local_name,iter->second.local_name
681 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
682 #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); }
683 #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); }
685 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
686 DEFINE_ACTION("about", Gtk::StockID("sinfg-about"));
687 DEFINE_ACTION("open", Gtk::Stock::OPEN);
688 DEFINE_ACTION("save", Gtk::Stock::SAVE);
689 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
690 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
691 DEFINE_ACTION("cvs-add", Gtk::StockID("sinfg-cvs_add"));
692 DEFINE_ACTION("cvs-update", Gtk::StockID("sinfg-cvs_update"));
693 DEFINE_ACTION("cvs-commit", Gtk::StockID("sinfg-cvs_commit"));
694 DEFINE_ACTION("cvs-revert", Gtk::StockID("sinfg-cvs_revert"));
695 DEFINE_ACTION("import", _("Import"));
696 DEFINE_ACTION("render", _("Render"));
697 DEFINE_ACTION("preview", _("Preview"));
698 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
699 DEFINE_ACTION("sound", _("Sound File"));
700 DEFINE_ACTION("options", _("Options"));
701 DEFINE_ACTION("close", _("Close"));
704 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
705 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
706 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
707 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
708 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
709 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
710 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
711 DEFINE_ACTION("properties", _("Properties"));
713 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
714 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
715 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
716 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
717 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
718 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
719 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
720 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
721 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
722 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
723 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
724 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
725 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
726 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
727 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
728 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
729 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
730 DEFINE_ACTION("play", _("Play"));
731 DEFINE_ACTION("pause", _("Pause"));
732 DEFINE_ACTION("stop", _("Stop"));
733 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
734 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
735 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
736 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
737 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
738 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
739 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
740 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
741 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
742 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
743 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
744 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
745 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
746 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
747 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
748 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
749 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
750 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
751 DEFINE_ACTION("seek-end", _("Seek to End"));
753 DEFINE_ACTION("action-group_add", _("Add group"));
755 DEFINE_ACTION("canvas-new", _("New Canvas"));
757 DEFINE_ACTION("amount-inc", _("Increase Amount"));
758 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
763 // Set up sinfgapp actions
765 sinfgapp::Action::Book::iterator iter;
767 for(iter=sinfgapp::Action::book().begin();iter!=sinfgapp::Action::book().end();++iter)
769 Gtk::StockID stock_id;
771 if(!(iter->second.category&sinfgapp::Action::CATEGORY_HIDDEN))
773 //Gtk::Image* image(manage(new Gtk::Image()));
774 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
775 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
776 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
777 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
778 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
779 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
780 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
781 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
782 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
783 else stock_id=Gtk::StockID("sinfg-"+iter->second.task);
785 actions_action_group->add(Gtk::Action::create(
786 "action-"+iter->second.name,
788 iter->second.local_name,iter->second.local_name
796 Glib::ustring ui_info =
798 " <popup name='menu-toolbox' action='menu-toolbox'>"
799 " <menu action='menu-file'>"
802 " <popup name='menu-main' action='menu-main'>"
803 " <menu action='menu-file'>"
804 " <menuitem action='save' />"
805 " <menuitem action='save-as' />"
806 " <menuitem action='revert' />"
807 " <separator name='bleh01'/>"
808 " <menuitem action='cvs-add' />"
809 " <menuitem action='cvs-update' />"
810 " <menuitem action='cvs-commit' />"
811 " <menuitem action='cvs-revert' />"
812 " <separator name='bleh02'/>"
813 " <menuitem action='import' />"
814 " <separator name='bleh03'/>"
815 " <menuitem action='render' />"
816 " <menuitem action='preview' />"
817 " <menuitem action='sound' />"
818 " <separator name='bleh04'/>"
819 " <menuitem action='options' />"
820 " <menuitem action='close' />"
822 " <menu action='menu-edit'>"
823 " <menuitem action='undo'/>"
824 " <menuitem action='redo'/>"
825 " <separator name='bleh05'/>"
826 " <menuitem action='cut'/>"
827 " <menuitem action='copy'/>"
828 " <menuitem action='paste'/>"
829 " <separator name='bleh06'/>"
830 " <menuitem action='select-all-ducks'/>"
831 " <menuitem action='unselect-all-layers'/>"
832 " <separator name='bleh07'/>"
833 " <menuitem action='properties'/>"
835 " <menu action='menu-view'>"
836 " <menu action='menu-duck-mask'>"
837 " <menuitem action='mask-position-ducks' />"
838 " <menuitem action='mask-vertex-ducks' />"
839 " <menuitem action='mask-tangent-ducks' />"
840 " <menuitem action='mask-radius-ducks' />"
841 " <menuitem action='mask-width-ducks' />"
842 " <menuitem action='mask-angle-ducks' />"
844 " <menu action='menu-preview-quality'>"
845 " <menuitem action='quality-00' />"
846 " <menuitem action='quality-01' />"
847 " <menuitem action='quality-02' />"
848 " <menuitem action='quality-03' />"
849 " <menuitem action='quality-04' />"
850 " <menuitem action='quality-05' />"
851 " <menuitem action='quality-06' />"
852 " <menuitem action='quality-07' />"
853 " <menuitem action='quality-08' />"
854 " <menuitem action='quality-09' />"
855 " <menuitem action='quality-10' />"
857 " <separator name='bleh08'/>"
858 " <menuitem action='play'/>"
859 " <menuitem action='pause'/>"
860 " <menuitem action='stop'/>"
861 " <menuitem action='dialog-flipbook'/>"
862 " <separator name='bleh09'/>"
863 " <menuitem action='toggle-grid-show'/>"
864 " <menuitem action='toggle-grid-snap'/>"
865 " <menuitem action='toggle-guide-show'/>"
866 " <menuitem action='toggle-low-res'/>"
867 " <menuitem action='toggle-onion-skin'/>"
868 " <separator name='bleh10'/>"
869 " <menuitem action='canvas-zoom-in'/>"
870 " <menuitem action='canvas-zoom-out'/>"
871 " <menuitem action='canvas-zoom-fit'/>"
872 " <menuitem action='canvas-zoom-100'/>"
873 " <separator name='bleh11'/>"
874 " <menuitem action='time-zoom-in'/>"
875 " <menuitem action='time-zoom-out'/>"
876 " <separator name='bleh12'/>"
877 " <menuitem action='jump-next-keyframe'/>"
878 " <menuitem action='jump-prev-keyframe'/>"
879 " <menuitem action='seek-next-frame'/>"
880 " <menuitem action='seek-prev-frame'/>"
881 " <menuitem action='seek-next-second'/>"
882 " <menuitem action='seek-prev-second'/>"
883 " <menuitem action='seek-begin'/>"
884 " <menuitem action='seek-end'/>"
886 " <menu action='menu-canvas'>"
887 " <menuitem action='canvas-new'/>"
888 " <menuitem action='amount-inc'/>"
889 " <menuitem action='amount-dec'/>"
891 " <menu name='menu-state' action='menu-state'>"
893 " <menu action='menu-group'>"
894 " <menuitem action='action-group_add'/>"
896 " <menu action='menu-layer'>"
897 //" <menuitem action='cut'/>"
898 //" <menuitem action='copy'/>"
899 //" <menuitem action='paste'/>"
900 //" <separator name='bleh06'/>"
901 " <menu action='menu-layer-new'></menu>"
903 " <menu action='menu-keyframe'>"
904 " <menuitem action='keyframe-properties'/>"
911 " <menubar name='MenuBar'>"
912 " <menu action='MenuFile'>"
913 " <menuitem action='New'/>"
914 " <menuitem action='Open'/>"
916 " <menuitem action='Quit'/>"
918 " <menu action='MenuEdit'>"
919 " <menuitem action='Cut'/>"
920 " <menuitem action='Copy'/>"
921 " <menuitem action='Paste'/>"
924 " <toolbar name='ToolBar'>"
925 " <toolitem action='Open'/>"
926 " <toolitem action='Quit'/>"
932 actions_action_group->set_sensitive(false);
933 App::ui_manager()->set_add_tearoffs(true);
934 App::ui_manager()->insert_action_group(menus_action_group,1);
935 App::ui_manager()->insert_action_group(actions_action_group,1);
936 App::ui_manager()->add_ui_from_string(ui_info);
938 //App::ui_manager()->get_accel_group()->unlock();
940 catch(const Glib::Error& ex)
942 sinfg::error("building menus and toolbars failed: " + ex.what());
945 // Add default keyboard accelerators
946 #define ACCEL(path,accel) { Gtk::AccelKey accel_key(accel,path); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
947 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
948 ACCEL("<Actions>//select-all-ducks","<Control>a");
949 ACCEL("<Actions>//unselect-all-layers","<Control>d");
950 ACCEL("<Actions>//render","F9");
951 ACCEL("<Actions>//preview","F11");
952 ACCEL("<Actions>//properties","F8");
953 ACCEL("<Actions>//options","F12");
954 ACCEL("<Actions>//import","<control>i");
955 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
956 ACCEL("<Actions>//toggle-grid-show","<Control>g");
957 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
958 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
959 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
960 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
961 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
962 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
963 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
964 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
967 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
968 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
970 ACCEL("<Actions>//quality-01","<Control>1");
971 ACCEL("<Actions>//quality-02","<Control>2");
972 ACCEL("<Actions>//quality-03","<Control>3");
973 ACCEL("<Actions>//quality-04","<Control>4");
974 ACCEL("<Actions>//quality-05","<Control>5");
975 ACCEL("<Actions>//quality-06","<Control>6");
976 ACCEL("<Actions>//quality-07","<Control>7");
977 ACCEL("<Actions>//quality-08","<Control>8");
978 ACCEL("<Actions>//quality-09","<Control>9");
979 ACCEL("<Actions>//quality-10","<Control>0");
980 ACCEL("<Actions>//undo","<Control>z");
981 ACCEL("<Actions>//redo","<Control>r");
982 ACCEL("<Actions>//action-layer_remove","Delete");
984 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
985 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
986 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
987 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
988 ACCEL("<Actions>//time-zoom-in","+");
989 ACCEL("<Actions>//time-zoom-out","_");
991 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
992 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
994 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
995 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
996 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
997 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
998 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
999 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1000 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1001 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1002 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1003 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1004 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1005 ACCEL("<Actions>//seek-begin","Home");
1006 ACCEL("<Actions>//seek-end","End");
1007 ACCEL("<Actions>//state-normal","<Mod1>a");
1008 ACCEL("<Actions>//state-rotate","<Mod1>s");
1009 ACCEL("<Actions>//state-scale","<Mod1>d");
1010 ACCEL("<Actions>//state-bline","<Mod1>b");
1011 ACCEL("<Actions>//state-fill","<Mod1>f");
1012 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1013 ACCEL("<Actions>//state-gradient","<Mod1>g");
1014 ACCEL("<Actions>//state-zoom","<Mod1>z");
1015 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1021 #define mkdir(x,y) mkdir(x)
1024 /* === M E T H O D S ======================================================= */
1026 App::App(int *argc, char ***argv):
1027 Gtk::Main(argc,argv),
1028 IconControler(etl::dirname((*argv)[0]))
1030 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1033 serial_=check_license(app_base_path_);
1036 ui_interface_=new GlobalUIInterface();
1040 Glib::thread_init();
1042 distance_system=Distance::SYSTEM_UNITS;
1044 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1047 sinfg::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1051 sinfg::info("Created directory \"%s\"",get_user_app_directory().c_str());
1059 if(!SINFG_CHECK_VERSION())
1061 cerr<<"FATAL: Sinfg Version Mismatch"<<endl;
1062 dialog_error_blocking("SINFG Studio",
1063 "This copy of SINFG Studio was compiled against a\n"
1064 "different version of libsinfg than what is currently\n"
1065 "installed. Sinfg Studio will now abort. Try downloading\n"
1066 "the latest version from the SINFG Development Website at\n"
1067 "http://dev.sinfg.com/ "
1072 catch(sinfg::SoftwareExpired)
1074 cerr<<"FATAL: Software Expired"<<endl;
1075 dialog_error_blocking("SINFG Studio",
1076 "This copy of SINFG Studio has expired.\n"
1077 "Please erase this copy, or download and\n"
1078 "install the latest copy from the SINFG\n"
1079 "Development Website at http://dev.sinfg.com/ ."
1083 Glib::set_application_name(_("SINFG Studio"));
1086 about_window.set_can_self_destruct(false);
1087 about_window.show();
1089 shutdown_in_progress=false;
1090 SuperCallback sinfg_init_cb(about_window.get_callback(),0,9000,10000);
1091 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1093 // Initialize the Sinfg library
1094 try { sinfgapp_main=etl::smart_ptr<sinfgapp::Main>(new sinfgapp::Main(etl::dirname((*argv)[0]),&sinfg_init_cb)); }
1097 get_ui_interface()->error("Failed to initialize sinfg!");
1101 // add the preferences to the settings
1102 sinfgapp::Main::settings().add_domain(&_preferences,"pref");
1106 studio_init_cb.task("Init UI Manager...");
1107 App::ui_manager_=studio::UIManager::create();
1110 studio_init_cb.task("Init Dock Manager...");
1111 dock_manager=new studio::DockManager();
1113 studio_init_cb.task("Init State Manager...");
1114 state_manager=new StateManager();
1116 studio_init_cb.task("Init Toolbox...");
1117 toolbox=new studio::Toolbox();
1119 studio_init_cb.task("Init Tool Options...");
1120 dialog_tool_options=new studio::Dialog_ToolOptions();
1121 dock_manager->register_dockable(*dialog_tool_options);
1123 studio_init_cb.task("Init History...");
1124 dock_history=new studio::Dock_History();
1125 dock_manager->register_dockable(*dock_history);
1127 studio_init_cb.task("Init Canvases...");
1128 dock_canvases=new studio::Dock_Canvases();
1129 dock_manager->register_dockable(*dock_canvases);
1131 studio_init_cb.task("Init Keyframes...");
1132 dock_keyframes=new studio::Dock_Keyframes();
1133 dock_manager->register_dockable(*dock_keyframes);
1135 studio_init_cb.task("Init Layers...");
1136 dock_layers=new studio::Dock_Layers();
1137 dock_manager->register_dockable(*dock_layers);
1139 studio_init_cb.task("Init Params...");
1140 dock_params=new studio::Dock_Params();
1141 dock_manager->register_dockable(*dock_params);
1143 studio_init_cb.task("Init MetaData...");
1144 dock_meta_data=new studio::Dock_MetaData();
1145 dock_manager->register_dockable(*dock_meta_data);
1147 studio_init_cb.task("Init Children...");
1148 dock_children=new studio::Dock_Children();
1149 dock_manager->register_dockable(*dock_children);
1151 studio_init_cb.task("Init Info...");
1152 dock_info = new studio::Dock_Info();
1153 dock_manager->register_dockable(*dock_info);
1155 studio_init_cb.task("Init Navigator...");
1156 dock_navigator = new studio::Dock_Navigator();
1157 dock_manager->register_dockable(*dock_navigator);
1159 studio_init_cb.task("Init Timetrack...");
1160 dock_timetrack = new studio::Dock_Timetrack();
1161 dock_manager->register_dockable(*dock_timetrack);
1163 studio_init_cb.task("Init Curve Editor...");
1164 dock_curves = new studio::Dock_Curves();
1165 dock_manager->register_dockable(*dock_curves);
1167 studio_init_cb.task("Init Layer Groups...");
1168 dock_layer_groups = new studio::Dock_LayerGroups();
1169 dock_manager->register_dockable(*dock_layer_groups);
1172 studio_init_cb.task("Init Color Dialog...");
1173 dialog_color=new studio::Dialog_Color();
1175 studio_init_cb.task("Init Gradient Dialog...");
1176 dialog_gradient=new studio::Dialog_Gradient();
1178 studio_init_cb.task("Init DeviceTracker...");
1179 device_tracker=new studio::DeviceTracker();
1181 studio_init_cb.task("Init Tools...");
1182 state_manager->add_state(&state_normal);
1183 state_manager->add_state(&state_smooth_move);
1184 state_manager->add_state(&state_scale);
1185 state_manager->add_state(&state_rotate);
1187 state_manager->add_state(&state_bline);
1188 state_manager->add_state(&state_polygon);
1189 state_manager->add_state(&state_circle);
1190 state_manager->add_state(&state_rectangle);
1192 state_manager->add_state(&state_draw);
1193 state_manager->add_state(&state_sketch);
1195 state_manager->add_state(&state_eyedrop);
1196 state_manager->add_state(&state_fill);
1198 state_manager->add_state(&state_width);
1199 state_manager->add_state(&state_gradient);
1201 state_manager->add_state(&state_zoom);
1203 studio_init_cb.task("Init ModPalette...");
1204 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1206 studio_init_cb.task("Init ModMirror...");
1207 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1210 studio_init_cb.task("Init Setup Dialog...");
1211 dialog_setup=new studio::Dialog_Setup();
1213 studio_init_cb.task("Init Input Dialog...");
1214 dialog_input=new Gtk::InputDialog();
1216 studio_init_cb.task("Init auto recovery...");
1217 auto_recover=new AutoRecover();
1219 studio_init_cb.amount_complete(9250,10000);
1220 studio_init_cb.task("Loading Settings...");
1222 studio_init_cb.task("Checking auto-recover...");
1224 studio_init_cb.amount_complete(9900,10000);
1226 if(auto_recover->recovery_needed())
1228 about_window.hide();
1230 get_ui_interface()->yes_no(
1232 "SINFG Studio seems to have crashed\n"
1233 "before you could save all your files.\n"
1234 "Would you like to re-open those files\n"
1235 "and recover your unsaved changes?"
1236 )==sinfgapp::UIInterface::RESPONSE_YES
1239 if(!auto_recover->recover())
1241 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1244 get_ui_interface()->error(
1245 _("SINFG Studio has attempted to recover\n"
1246 "from a previous crash. The files that it has\n"
1247 "recovered are NOT YET SAVED. It would be a good\n"
1248 "idea to review them and save them now.")
1251 about_window.show();
1254 // Look for any files given on the command line,
1255 // and load them if found.
1256 for(;*argc>=1;(*argc)--)
1257 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1259 studio_init_cb.task("Loading files...");
1260 about_window.hide();
1261 open((*argv)[*argc]);
1262 about_window.show();
1265 studio_init_cb.task("Done.");
1266 studio_init_cb.amount_complete(10000,10000);
1272 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1276 StateManager* App::get_state_manager() { return state_manager; }
1280 shutdown_in_progress=true;
1284 sinfgapp::Main::settings().remove_domain("pref");
1286 selected_instance=0;
1288 // Unload all of the modules
1289 for(;!module_list_.empty();module_list_.pop_back());
1291 delete state_manager;
1295 delete auto_recover;
1299 // studio::App::iteration(false);
1303 // studio::App::iteration(false);
1305 // studio::App::iteration(false);
1307 delete dialog_setup;
1309 delete dialog_gradient;
1311 delete dialog_color;
1313 delete dialog_input;
1315 delete dock_manager;
1317 instance_list.clear();
1319 // studio::App::iteration(false);
1323 App::get_user_app_directory()
1325 return Glib::build_filename(Glib::get_home_dir(),"sinfg");
1329 App::get_config_file(const sinfg::String& file)
1331 return Glib::build_filename(get_user_app_directory(),file);
1335 App::add_recent_file(const std::string &file_name)
1337 std::string filename(file_name);
1339 assert(!filename.empty());
1341 if(filename.empty())
1344 // Toss out any "hidden" files
1345 if(basename(filename)[0]=='.')
1348 // If we aren't an absolute path, turn outselves into one
1349 if(!is_absolute_path(filename))
1350 filename=absolute_path(filename);
1352 list<string>::iterator iter;
1353 // Check to see if the file is already on the list.
1354 // If it is, then remove it from the list
1355 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1358 recent_files.erase(iter);
1363 // Push the filename to the front of the list
1364 recent_files.push_front(filename);
1366 // Clean out the files at the end of the list.
1367 while(recent_files.size()>(unsigned)get_max_recent_files())
1368 recent_files.pop_back();
1370 signal_recent_files_changed_();
1375 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1378 App::get_time_format()
1380 return _App_time_format;
1384 App::set_time_format(sinfg::Time::Format x)
1391 App::save_settings()
1396 std::string filename=get_config_file("accelrc");
1397 Gtk::AccelMap::save(filename);
1400 std::string filename=get_config_file("recentfiles");
1402 std::ofstream file(filename.c_str());
1406 sinfg::warning("Unable to save %s",filename.c_str());
1410 list<string>::reverse_iterator iter;
1412 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1416 std::string filename=get_config_file("settings");
1417 sinfgapp::Main::settings().save_to_file(filename);
1421 sinfg::warning("Caught exception when attempting to save settings.");
1426 App::load_settings()
1431 std::string filename=get_config_file("accelrc");
1432 Gtk::AccelMap::load(filename);
1435 std::string filename=get_config_file("recentfiles");
1437 std::ifstream file(filename.c_str());
1441 std::string recent_file;
1442 getline(file,recent_file);
1443 if(!recent_file.empty())
1444 add_recent_file(recent_file);
1447 std::string filename=get_config_file("settings");
1448 if(!sinfgapp::Main::settings().load_from_file(filename))
1450 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".sinfgrc");
1451 //if(!sinfgapp::Main::settings().load_from_file(filename))
1453 gamma.set_gamma(1.0/2.2);
1454 sinfgapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1455 sinfgapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1456 sinfgapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1457 sinfgapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1458 sinfgapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1459 sinfgapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1460 sinfgapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1461 sinfgapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1462 sinfgapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1463 sinfgapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1464 sinfgapp::Main::settings().set_value("pref.distance_system","pt");
1465 sinfgapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1466 sinfgapp::Main::settings().set_value("window.toolbox.pos","4 4");
1473 sinfg::warning("Caught exception when attempting to load settings.");
1478 App::shutdown_request(GdkEventAny*)
1482 //return !shutdown_in_progress;
1488 if(shutdown_in_progress)return;
1491 get_ui_interface()->task("Quit Request");
1494 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1498 std::list<etl::handle<Instance> >::iterator iter;
1499 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1501 if(!(*iter)->safe_close())
1505 if((*iter)->sinfgapp::Instance::get_action_count())
1507 handle<sinfgapp::UIInterface> uim;
1508 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1510 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1511 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,sinfgapp::UIInterface::RESPONSE_YES))
1513 case sinfgapp::UIInterface::RESPONSE_NO:
1515 case sinfgapp::UIInterface::RESPONSE_YES:
1518 case sinfgapp::UIInterface::RESPONSE_CANCEL:
1527 if((*iter)->sinfgapp::Instance::is_modified())
1529 handle<sinfgapp::UIInterface> uim;
1530 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1532 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() );
1533 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,sinfgapp::UIInterface::RESPONSE_YES))
1535 case sinfgapp::UIInterface::RESPONSE_NO:
1537 case sinfgapp::UIInterface::RESPONSE_YES:
1538 (*iter)->dialog_cvs_commit();
1540 case sinfgapp::UIInterface::RESPONSE_CANCEL:
1549 // This next line causes things to crash for some reason
1553 shutdown_in_progress=true;
1555 instance_list.clear();
1557 while(studio::App::events_pending())studio::App::iteration(false);
1560 auto_recover->normal_shutdown();
1562 get_ui_interface()->task("Quit Request sent");
1568 dialog_setup->refresh();
1569 dialog_setup->show();
1572 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1573 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1576 //#define USE_WIN32_FILE_DIALOGS 1
1579 #ifdef USE_WIN32_FILE_DIALOGS
1580 static OPENFILENAME ofn={};
1584 #include <gdk/gdkwin32.h>
1588 App::dialog_open_file(const std::string &title, std::string &filename)
1590 #ifdef USE_WIN32_FILE_DIALOGS
1591 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1593 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1594 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1595 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1597 ofn.lStructSize=sizeof(OPENFILENAME);
1598 ofn.hwndOwner = hWnd;
1599 ofn.hInstance = hInstance;
1600 ofn.lpstrFilter = szFilter;
1601 // ofn.lpstrCustomFilter=NULL;
1602 // ofn.nMaxCustFilter=0;
1603 // ofn.nFilterIndex=0;
1604 // ofn.lpstrFile=NULL;
1605 ofn.nMaxFile=MAX_PATH;
1606 // ofn.lpstrFileTitle=NULL;
1607 // ofn.lpstrInitialDir=NULL;
1608 // ofn.lpstrTitle=NULL;
1609 ofn.Flags=OFN_HIDEREADONLY;
1610 // ofn.nFileOffset=0;
1611 // ofn.nFileExtension=0;
1612 ofn.lpstrDefExt=TEXT("sif");
1613 // ofn.lCustData = 0l;
1615 // ofn.lpTemplateName=NULL;
1617 CHAR szFilename[MAX_PATH];
1619 strcpy(szFilename,filename.c_str());
1620 strcpy(szTitle,title.c_str());
1622 ofn.lpstrFile=szFilename;
1623 ofn.lpstrFileTitle=szTitle;
1625 if(GetOpenFileName(&ofn))
1627 filename=szFilename;
1633 sinfg::String prev_path;
1634 if(!_preferences.get_value("curr_path",prev_path))
1641 GtkWidget *fileselection;
1642 fileselection = gtk_file_selection_new(title.c_str());
1645 if(basename(filename)==filename)
1647 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1650 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1652 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1654 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1655 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1657 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1658 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1660 gtk_widget_show(fileselection);
1668 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1669 _preferences.set_value("curr_path",dirname(filename));
1673 gtk_widget_destroy(fileselection);
1676 gtk_widget_destroy(fileselection);
1682 App::dialog_save_file(const std::string &title, std::string &filename)
1684 #ifdef USE_WIN32_FILE_DIALOGS
1685 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1687 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1688 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1689 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1691 ofn.lStructSize=sizeof(OPENFILENAME);
1692 ofn.hwndOwner = hWnd;
1693 ofn.hInstance = hInstance;
1694 ofn.lpstrFilter = szFilter;
1695 // ofn.lpstrCustomFilter=NULL;
1696 // ofn.nMaxCustFilter=0;
1697 // ofn.nFilterIndex=0;
1698 // ofn.lpstrFile=NULL;
1699 ofn.nMaxFile=MAX_PATH;
1700 // ofn.lpstrFileTitle=NULL;
1701 // ofn.lpstrInitialDir=NULL;
1702 // ofn.lpstrTitle=NULL;
1703 ofn.Flags=OFN_OVERWRITEPROMPT;
1704 // ofn.nFileOffset=0;
1705 // ofn.nFileExtension=0;
1706 ofn.lpstrDefExt=TEXT("sif");
1707 // ofn.lCustData = 0l;
1709 // ofn.lpTemplateName=NULL;
1711 CHAR szFilename[MAX_PATH];
1713 strcpy(szFilename,filename.c_str());
1714 strcpy(szTitle,title.c_str());
1716 ofn.lpstrFile=szFilename;
1717 ofn.lpstrFileTitle=szTitle;
1719 if(GetSaveFileName(&ofn))
1721 filename=szFilename;
1726 return dialog_open_file(title, filename);
1731 App::dialog_saveas_file(const std::string &title, std::string &filename)
1733 #if USE_WIN32_FILE_DIALOGS
1734 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1736 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1737 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1738 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1740 ofn.lStructSize=sizeof(OPENFILENAME);
1741 ofn.hwndOwner = hWnd;
1742 ofn.hInstance = hInstance;
1743 ofn.lpstrFilter = szFilter;
1744 // ofn.lpstrCustomFilter=NULL;
1745 // ofn.nMaxCustFilter=0;
1746 // ofn.nFilterIndex=0;
1747 // ofn.lpstrFile=NULL;
1748 ofn.nMaxFile=MAX_PATH;
1749 // ofn.lpstrFileTitle=NULL;
1750 // ofn.lpstrInitialDir=NULL;
1751 // ofn.lpstrTitle=NULL;
1752 ofn.Flags=OFN_OVERWRITEPROMPT;
1753 // ofn.nFileOffset=0;
1754 // ofn.nFileExtension=0;
1755 ofn.lpstrDefExt=TEXT("sif");
1756 // ofn.lCustData = 0l;
1758 // ofn.lpTemplateName=NULL;
1760 CHAR szFilename[MAX_PATH];
1762 strcpy(szFilename,filename.c_str());
1763 strcpy(szTitle,title.c_str());
1765 ofn.lpstrFile=szFilename;
1766 ofn.lpstrFileTitle=szTitle;
1768 if(GetSaveFileName(&ofn))
1770 filename=szFilename;
1775 return dialog_open_file(title, filename);
1780 App::dialog_error_blocking(const std::string &title, const std::string &message)
1785 true // use_separator
1787 Gtk::Label label(message);
1790 dialog.get_vbox()->pack_start(label);
1791 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1797 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1802 true // use_separator
1804 Gtk::Label label(message);
1807 dialog.get_vbox()->pack_start(label);
1808 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1814 App::dialog_yes_no(const std::string &title, const std::string &message)
1819 true // use_separator
1821 Gtk::Label label(message);
1824 dialog.get_vbox()->pack_start(label);
1825 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1826 dialog.add_button(Gtk::StockID("gtk-no"),0);
1828 return dialog.run();
1832 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1837 true // use_separator
1839 Gtk::Label label(message);
1842 dialog.get_vbox()->pack_start(label);
1843 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1844 dialog.add_button(Gtk::StockID("gtk-no"),0);
1845 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1847 return dialog.run();
1851 App::dialog_not_implemented()
1854 "Feature not available", // Title
1856 true // use_separator
1858 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1861 dialog.get_vbox()->pack_start(label);
1862 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1868 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1873 true // use_separator
1875 Gtk::Label label(message);
1877 dialog.get_vbox()->pack_start(label);
1880 entry.set_text(text);
1882 entry.set_activates_default(true);
1883 dialog.get_vbox()->pack_start(entry);
1885 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1886 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1887 dialog.set_default_response(Gtk::RESPONSE_OK);
1888 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1891 if(dialog.run()!=Gtk::RESPONSE_OK)
1894 text=entry.get_text();
1903 App::open(std::string filename)
1905 return open_as(filename,filename);
1909 App::open_as(std::string filename,std::string as)
1913 OneMoment one_moment;
1915 etl::handle<sinfg::Canvas> canvas(open_canvas_as(filename,as));
1916 if(canvas && get_instance(canvas))
1918 get_instance(canvas)->find_canvas_view(canvas)->present();
1919 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1922 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1924 add_recent_file(as);
1926 handle<Instance> instance(Instance::create(canvas));
1929 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1933 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)")))
1934 instance->dialog_cvs_update();
1938 dialog_error_blocking(_("Error"), x);
1943 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1947 _preferences.set_value("curr_path",dirname(as));
1956 handle<sinfg::Canvas> canvas=sinfg::Canvas::create();
1957 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
1959 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
1961 canvas->rend_desc().set_frame_rate(24.0);
1962 canvas->rend_desc().set_time_start(0.0);
1963 canvas->rend_desc().set_time_end(00.0);
1964 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1965 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1966 canvas->rend_desc().set_tl(Vector(-4,2.25));
1967 canvas->rend_desc().set_br(Vector(4,-2.25));
1968 canvas->rend_desc().set_w(480);
1969 canvas->rend_desc().set_h(270);
1970 canvas->rend_desc().set_antialias(1);
1971 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1972 canvas->set_file_name(file_name);
1974 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
1980 string filename="*.sif";
1982 while(dialog_open_file("Open", filename))
1984 // If the filename still has wildcards, then we should
1985 // continue looking for the file we want
1986 if(find(filename.begin(),filename.end(),'*')!=filename.end())
1992 get_ui_interface()->error(_("Unable to open file"));
1997 App::set_selected_instance(etl::loose_handle<Instance> instance)
1999 /* if(get_selected_instance()==instance)
2001 selected_instance=instance;
2002 signal_instance_selected()(instance);
2008 selected_instance=instance;
2009 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2013 instance->focus(instance->get_canvas());
2016 set_selected_canvas_view(0);
2018 signal_instance_selected()(instance);
2022 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2024 selected_canvas_view=canvas_view;
2025 signal_canvas_view_focus()(selected_canvas_view);
2028 selected_instance=canvas_view->get_instance();
2029 signal_instance_selected()(canvas_view->get_instance());
2032 if(get_selected_canvas_view()==canvas_view)
2034 signal_canvas_view_focus()(selected_canvas_view);
2035 signal_instance_selected()(canvas_view->get_instance());
2038 selected_canvas_view=canvas_view;
2039 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2040 set_selected_instance(canvas_view->get_instance());
2041 signal_canvas_view_focus()(selected_canvas_view);
2045 etl::loose_handle<Instance>
2046 App::get_instance(Canvas::Handle canvas)
2048 if(!canvas) return 0;
2049 canvas=canvas->get_root();
2051 std::list<etl::handle<Instance> >::iterator iter;
2052 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2054 if((*iter)->get_canvas()==canvas)
2063 (new class About())->show();
2069 if(selected_instance)
2070 selected_instance->undo();
2076 if(selected_instance)
2077 selected_instance->redo();
2081 studio::App::get_base_path()
2083 return app_base_path_;