1 /* === S I N F G =========================================================== */
5 ** $Id: app.cpp,v 1.11 2005/03/24 21:47:28 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;
375 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
376 #define endian_fix(x) (endian_fix_table[x])
378 #define endian_fix(x) (x)
381 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
384 unwound->element.serial=0;
385 unwound->element.checksum=0;
393 case '0': data=0; break;
394 case '1': data=1; break;
395 case '2': data=2; break;
396 case '3': data=3; break;
397 case '4': data=4; break;
398 case '5': data=5; break;
399 case '6': data=6; break;
400 case '7': data=7; break;
401 case '8': data=8; break;
402 case '9': data=9; break;
403 case 'a': case 'A': data=10; break;
404 case 'b': case 'B': data=11; break;
405 case 'c': case 'C': data=12; break;
406 case 'd': case 'D': data=13; break;
407 case 'e': case 'E': data=14; break;
408 case 'f': case 'F': data=15; break;
409 default: return 0; break;
412 unwound->element.checksum|=(((U32)data&3)<<bit);
413 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
418 int v_key_check(const char* key, U32* serial, U32 appid)
420 V_KeyUnwound unwound_key;
421 U32 appid_mask_a=hash_U32(appid);
422 U32 appid_mask_b=hash_U32(appid_mask_a);
424 if(!v_unwind_key(&unwound_key, key))
426 // Invalid characters in key
431 // Undo obfuscation pass
433 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
438 unwound_key.raw[endian_fix(i)]^=(next>>24);
442 unwound_key.element.serial^=appid_mask_a;
443 unwound_key.element.checksum^=appid_mask_b;
445 *serial=unwound_key.element.serial;
447 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
451 int check_license(String basedir)
457 license_file="/usr/local/etc/.synfiglicense";
459 license_file=basedir+"\\etc\\.synfiglicense";
463 key=Glib::file_get_contents(license_file);
464 } catch (Glib::FileError) { }
466 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
468 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
472 if(!App::dialog_entry(
473 _("Synfig Studio Authentication"),
474 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
477 throw String("No License");
480 FILE* file=fopen(license_file.c_str(),"w");
483 fprintf(file,"%s",key.c_str());
487 sinfg::error("Unable to save license key!");
489 sinfg::info("License Authenticated -- Serial #%05d",serial);
495 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
497 action_group_list.push_back(action_group);
498 Gtk::UIManager::insert_action_group(action_group, pos);
502 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
504 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
505 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
506 if(*iter==action_group)
508 action_group_list.erase(iter);
509 Gtk::UIManager::remove_action_group(action_group);
512 sinfg::error("Unable to find action group");
516 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
518 ui_manager->insert_action_group(group,0);
521 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
522 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
525 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
528 if(*iter && (*iter)->get_name()!="menus")
530 sinfg::info("Removing action group "+(*iter)->get_name());
531 ui_manager->remove_action_group(*iter);
535 ui_manager->insert_action_group(group,0);
538 for(;!prev_groups.empty();prev_groups.pop_front())
540 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
541 ui_manager->insert_action_group(prev_groups.front(),1);
546 class Preferences : public sinfgapp::Settings
549 virtual bool get_value(const sinfg::String& key, sinfg::String& value)const
553 value=strprintf("%f %f %f %f",
554 App::gamma.get_gamma_r(),
555 App::gamma.get_gamma_g(),
556 App::gamma.get_gamma_b(),
557 App::gamma.get_black_level()
561 if(key=="time_format")
563 value=strprintf("%i",App::get_time_format());
566 if(key=="file_history.size")
568 value=strprintf("%i",App::get_max_recent_files());
571 if(key=="use_colorspace_gamma")
573 value=strprintf("%i",(int)App::use_colorspace_gamma);
576 if(key=="distance_system")
578 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
581 if(key=="auto_recover_backup_interval")
583 value=strprintf("%i",App::auto_recover->get_timeout());
587 return sinfgapp::Settings::get_value(key,value);
590 virtual bool set_value(const sinfg::String& key,const sinfg::String& value)
596 strscanf(value,"%f %f %f %f",
603 App::gamma.set_all(r,g,b,blk);
607 if(key=="time_format")
609 int i(atoi(value.c_str()));
610 App::set_time_format(static_cast<sinfg::Time::Format>(i));
613 if(key=="auto_recover_backup_interval")
615 int i(atoi(value.c_str()));
616 App::auto_recover->set_timeout(i);
619 if(key=="file_history.size")
621 int i(atoi(value.c_str()));
622 App::set_max_recent_files(i);
625 if(key=="use_colorspace_gamma")
627 int i(atoi(value.c_str()));
628 App::use_colorspace_gamma=i;
631 if(key=="distance_system")
633 App::distance_system=Distance::ident_system(value);;
637 return sinfgapp::Settings::set_value(key,value);
640 virtual KeyList get_key_list()const
642 KeyList ret(sinfgapp::Settings::get_key_list());
643 ret.push_back("gamma");
644 ret.push_back("time_format");
645 ret.push_back("distance_system");
646 ret.push_back("file_history.size");
647 ret.push_back("use_colorspace_gamma");
648 ret.push_back("auto_recover_backup_interval");
653 static Preferences _preferences;
658 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
660 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
662 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
664 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
665 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
666 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
667 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
668 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
669 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
670 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
671 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
672 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
673 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
674 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
675 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
677 // Add the sinfgapp actions...
678 sinfgapp::Action::Book::iterator iter;
679 for(iter=sinfgapp::Action::book().begin();iter!=sinfgapp::Action::book().end();++iter)
681 actions_action_group->add(Gtk::Action::create(
682 "action-"+iter->second.name,
683 get_action_stock_id(iter->second),
684 iter->second.local_name,iter->second.local_name
688 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
689 #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); }
690 #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); }
692 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
693 DEFINE_ACTION("about", Gtk::StockID("sinfg-about"));
694 DEFINE_ACTION("open", Gtk::Stock::OPEN);
695 DEFINE_ACTION("save", Gtk::Stock::SAVE);
696 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
697 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
698 DEFINE_ACTION("cvs-add", Gtk::StockID("sinfg-cvs_add"));
699 DEFINE_ACTION("cvs-update", Gtk::StockID("sinfg-cvs_update"));
700 DEFINE_ACTION("cvs-commit", Gtk::StockID("sinfg-cvs_commit"));
701 DEFINE_ACTION("cvs-revert", Gtk::StockID("sinfg-cvs_revert"));
702 DEFINE_ACTION("import", _("Import"));
703 DEFINE_ACTION("render", _("Render"));
704 DEFINE_ACTION("preview", _("Preview"));
705 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
706 DEFINE_ACTION("sound", _("Sound File"));
707 DEFINE_ACTION("options", _("Options"));
708 DEFINE_ACTION("close", _("Close"));
711 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
712 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
713 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
714 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
715 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
716 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
717 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
718 DEFINE_ACTION("properties", _("Properties"));
720 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
721 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
722 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
723 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
724 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
725 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
726 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
727 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
728 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
729 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
730 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
731 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
732 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
733 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
734 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
735 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
736 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
737 DEFINE_ACTION("play", _("Play"));
738 DEFINE_ACTION("pause", _("Pause"));
739 DEFINE_ACTION("stop", _("Stop"));
740 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
741 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
742 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
743 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
744 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
745 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
746 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
747 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
748 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
749 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
750 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
751 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
752 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
753 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
754 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
755 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
756 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
757 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
758 DEFINE_ACTION("seek-end", _("Seek to End"));
760 DEFINE_ACTION("action-group_add", _("Add group"));
762 DEFINE_ACTION("canvas-new", _("New Canvas"));
764 DEFINE_ACTION("amount-inc", _("Increase Amount"));
765 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
770 // Set up sinfgapp actions
772 sinfgapp::Action::Book::iterator iter;
774 for(iter=sinfgapp::Action::book().begin();iter!=sinfgapp::Action::book().end();++iter)
776 Gtk::StockID stock_id;
778 if(!(iter->second.category&sinfgapp::Action::CATEGORY_HIDDEN))
780 //Gtk::Image* image(manage(new Gtk::Image()));
781 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
782 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
783 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
784 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
785 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
786 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
787 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
788 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
789 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
790 else stock_id=Gtk::StockID("sinfg-"+iter->second.task);
792 actions_action_group->add(Gtk::Action::create(
793 "action-"+iter->second.name,
795 iter->second.local_name,iter->second.local_name
803 Glib::ustring ui_info =
805 " <popup name='menu-toolbox' action='menu-toolbox'>"
806 " <menu action='menu-file'>"
809 " <popup name='menu-main' action='menu-main'>"
810 " <menu action='menu-file'>"
811 " <menuitem action='save' />"
812 " <menuitem action='save-as' />"
813 " <menuitem action='revert' />"
814 " <separator name='bleh01'/>"
815 " <menuitem action='cvs-add' />"
816 " <menuitem action='cvs-update' />"
817 " <menuitem action='cvs-commit' />"
818 " <menuitem action='cvs-revert' />"
819 " <separator name='bleh02'/>"
820 " <menuitem action='import' />"
821 " <separator name='bleh03'/>"
822 " <menuitem action='render' />"
823 " <menuitem action='preview' />"
824 " <menuitem action='sound' />"
825 " <separator name='bleh04'/>"
826 " <menuitem action='options' />"
827 " <menuitem action='close' />"
829 " <menu action='menu-edit'>"
830 " <menuitem action='undo'/>"
831 " <menuitem action='redo'/>"
832 " <separator name='bleh05'/>"
833 " <menuitem action='cut'/>"
834 " <menuitem action='copy'/>"
835 " <menuitem action='paste'/>"
836 " <separator name='bleh06'/>"
837 " <menuitem action='select-all-ducks'/>"
838 " <menuitem action='unselect-all-layers'/>"
839 " <separator name='bleh07'/>"
840 " <menuitem action='properties'/>"
842 " <menu action='menu-view'>"
843 " <menu action='menu-duck-mask'>"
844 " <menuitem action='mask-position-ducks' />"
845 " <menuitem action='mask-vertex-ducks' />"
846 " <menuitem action='mask-tangent-ducks' />"
847 " <menuitem action='mask-radius-ducks' />"
848 " <menuitem action='mask-width-ducks' />"
849 " <menuitem action='mask-angle-ducks' />"
851 " <menu action='menu-preview-quality'>"
852 " <menuitem action='quality-00' />"
853 " <menuitem action='quality-01' />"
854 " <menuitem action='quality-02' />"
855 " <menuitem action='quality-03' />"
856 " <menuitem action='quality-04' />"
857 " <menuitem action='quality-05' />"
858 " <menuitem action='quality-06' />"
859 " <menuitem action='quality-07' />"
860 " <menuitem action='quality-08' />"
861 " <menuitem action='quality-09' />"
862 " <menuitem action='quality-10' />"
864 " <separator name='bleh08'/>"
865 " <menuitem action='play'/>"
866 " <menuitem action='pause'/>"
867 " <menuitem action='stop'/>"
868 " <menuitem action='dialog-flipbook'/>"
869 " <separator name='bleh09'/>"
870 " <menuitem action='toggle-grid-show'/>"
871 " <menuitem action='toggle-grid-snap'/>"
872 " <menuitem action='toggle-guide-show'/>"
873 " <menuitem action='toggle-low-res'/>"
874 " <menuitem action='toggle-onion-skin'/>"
875 " <separator name='bleh10'/>"
876 " <menuitem action='canvas-zoom-in'/>"
877 " <menuitem action='canvas-zoom-out'/>"
878 " <menuitem action='canvas-zoom-fit'/>"
879 " <menuitem action='canvas-zoom-100'/>"
880 " <separator name='bleh11'/>"
881 " <menuitem action='time-zoom-in'/>"
882 " <menuitem action='time-zoom-out'/>"
883 " <separator name='bleh12'/>"
884 " <menuitem action='jump-next-keyframe'/>"
885 " <menuitem action='jump-prev-keyframe'/>"
886 " <menuitem action='seek-next-frame'/>"
887 " <menuitem action='seek-prev-frame'/>"
888 " <menuitem action='seek-next-second'/>"
889 " <menuitem action='seek-prev-second'/>"
890 " <menuitem action='seek-begin'/>"
891 " <menuitem action='seek-end'/>"
893 " <menu action='menu-canvas'>"
894 " <menuitem action='canvas-new'/>"
895 " <menuitem action='amount-inc'/>"
896 " <menuitem action='amount-dec'/>"
898 " <menu name='menu-state' action='menu-state'>"
900 " <menu action='menu-group'>"
901 " <menuitem action='action-group_add'/>"
903 " <menu action='menu-layer'>"
904 //" <menuitem action='cut'/>"
905 //" <menuitem action='copy'/>"
906 //" <menuitem action='paste'/>"
907 //" <separator name='bleh06'/>"
908 " <menu action='menu-layer-new'></menu>"
910 " <menu action='menu-keyframe'>"
911 " <menuitem action='keyframe-properties'/>"
918 " <menubar name='MenuBar'>"
919 " <menu action='MenuFile'>"
920 " <menuitem action='New'/>"
921 " <menuitem action='Open'/>"
923 " <menuitem action='Quit'/>"
925 " <menu action='MenuEdit'>"
926 " <menuitem action='Cut'/>"
927 " <menuitem action='Copy'/>"
928 " <menuitem action='Paste'/>"
931 " <toolbar name='ToolBar'>"
932 " <toolitem action='Open'/>"
933 " <toolitem action='Quit'/>"
939 actions_action_group->set_sensitive(false);
940 App::ui_manager()->set_add_tearoffs(true);
941 App::ui_manager()->insert_action_group(menus_action_group,1);
942 App::ui_manager()->insert_action_group(actions_action_group,1);
943 App::ui_manager()->add_ui_from_string(ui_info);
945 //App::ui_manager()->get_accel_group()->unlock();
947 catch(const Glib::Error& ex)
949 sinfg::error("building menus and toolbars failed: " + ex.what());
952 // Add default keyboard accelerators
953 #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()); }
954 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
955 ACCEL("<Actions>//select-all-ducks","<Control>a");
956 ACCEL("<Actions>//unselect-all-layers","<Control>d");
957 ACCEL("<Actions>//render","F9");
958 ACCEL("<Actions>//preview","F11");
959 ACCEL("<Actions>//properties","F8");
960 ACCEL("<Actions>//options","F12");
961 ACCEL("<Actions>//import","<control>i");
962 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
963 ACCEL("<Actions>//toggle-grid-show","<Control>g");
964 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
965 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
966 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
967 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
968 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
969 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
970 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
971 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
974 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
975 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
977 ACCEL("<Actions>//quality-01","<Control>1");
978 ACCEL("<Actions>//quality-02","<Control>2");
979 ACCEL("<Actions>//quality-03","<Control>3");
980 ACCEL("<Actions>//quality-04","<Control>4");
981 ACCEL("<Actions>//quality-05","<Control>5");
982 ACCEL("<Actions>//quality-06","<Control>6");
983 ACCEL("<Actions>//quality-07","<Control>7");
984 ACCEL("<Actions>//quality-08","<Control>8");
985 ACCEL("<Actions>//quality-09","<Control>9");
986 ACCEL("<Actions>//quality-10","<Control>0");
987 ACCEL("<Actions>//undo","<Control>z");
988 ACCEL("<Actions>//redo","<Control>r");
989 ACCEL("<Actions>//action-layer_remove","Delete");
991 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
992 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
993 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
994 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
995 ACCEL("<Actions>//time-zoom-in","+");
996 ACCEL("<Actions>//time-zoom-out","_");
998 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
999 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1001 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1002 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1003 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1004 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1005 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1006 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1007 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1008 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1009 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1010 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1011 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1012 ACCEL("<Actions>//seek-begin","Home");
1013 ACCEL("<Actions>//seek-end","End");
1014 ACCEL("<Actions>//state-normal","<Mod1>a");
1015 ACCEL("<Actions>//state-rotate","<Mod1>s");
1016 ACCEL("<Actions>//state-scale","<Mod1>d");
1017 ACCEL("<Actions>//state-bline","<Mod1>b");
1018 ACCEL("<Actions>//state-fill","<Mod1>f");
1019 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1020 ACCEL("<Actions>//state-gradient","<Mod1>g");
1021 ACCEL("<Actions>//state-zoom","<Mod1>z");
1022 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1028 #define mkdir(x,y) mkdir(x)
1031 /* === M E T H O D S ======================================================= */
1033 App::App(int *argc, char ***argv):
1034 Gtk::Main(argc,argv),
1035 IconControler(etl::dirname((*argv)[0]))
1037 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1040 serial_=check_license(app_base_path_);
1043 ui_interface_=new GlobalUIInterface();
1047 Glib::thread_init();
1049 distance_system=Distance::SYSTEM_UNITS;
1051 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1054 sinfg::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1058 sinfg::info("Created directory \"%s\"",get_user_app_directory().c_str());
1066 if(!SINFG_CHECK_VERSION())
1068 cerr<<"FATAL: Sinfg Version Mismatch"<<endl;
1069 dialog_error_blocking("SINFG Studio",
1070 "This copy of SINFG Studio was compiled against a\n"
1071 "different version of libsinfg than what is currently\n"
1072 "installed. Sinfg Studio will now abort. Try downloading\n"
1073 "the latest version from the SINFG Development Website at\n"
1074 "http://dev.sinfg.com/ "
1079 catch(sinfg::SoftwareExpired)
1081 cerr<<"FATAL: Software Expired"<<endl;
1082 dialog_error_blocking("SINFG Studio",
1083 "This copy of SINFG Studio has expired.\n"
1084 "Please erase this copy, or download and\n"
1085 "install the latest copy from the SINFG\n"
1086 "Development Website at http://dev.sinfg.com/ ."
1090 Glib::set_application_name(_("SINFG Studio"));
1093 about_window.set_can_self_destruct(false);
1094 about_window.show();
1096 shutdown_in_progress=false;
1097 SuperCallback sinfg_init_cb(about_window.get_callback(),0,9000,10000);
1098 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1100 // Initialize the Sinfg library
1101 try { sinfgapp_main=etl::smart_ptr<sinfgapp::Main>(new sinfgapp::Main(etl::dirname((*argv)[0]),&sinfg_init_cb)); }
1104 get_ui_interface()->error("Failed to initialize sinfg!");
1108 // add the preferences to the settings
1109 sinfgapp::Main::settings().add_domain(&_preferences,"pref");
1113 studio_init_cb.task("Init UI Manager...");
1114 App::ui_manager_=studio::UIManager::create();
1117 studio_init_cb.task("Init Dock Manager...");
1118 dock_manager=new studio::DockManager();
1120 studio_init_cb.task("Init State Manager...");
1121 state_manager=new StateManager();
1123 studio_init_cb.task("Init Toolbox...");
1124 toolbox=new studio::Toolbox();
1126 studio_init_cb.task("Init Tool Options...");
1127 dialog_tool_options=new studio::Dialog_ToolOptions();
1128 dock_manager->register_dockable(*dialog_tool_options);
1130 studio_init_cb.task("Init History...");
1131 dock_history=new studio::Dock_History();
1132 dock_manager->register_dockable(*dock_history);
1134 studio_init_cb.task("Init Canvases...");
1135 dock_canvases=new studio::Dock_Canvases();
1136 dock_manager->register_dockable(*dock_canvases);
1138 studio_init_cb.task("Init Keyframes...");
1139 dock_keyframes=new studio::Dock_Keyframes();
1140 dock_manager->register_dockable(*dock_keyframes);
1142 studio_init_cb.task("Init Layers...");
1143 dock_layers=new studio::Dock_Layers();
1144 dock_manager->register_dockable(*dock_layers);
1146 studio_init_cb.task("Init Params...");
1147 dock_params=new studio::Dock_Params();
1148 dock_manager->register_dockable(*dock_params);
1150 studio_init_cb.task("Init MetaData...");
1151 dock_meta_data=new studio::Dock_MetaData();
1152 dock_manager->register_dockable(*dock_meta_data);
1154 studio_init_cb.task("Init Children...");
1155 dock_children=new studio::Dock_Children();
1156 dock_manager->register_dockable(*dock_children);
1158 studio_init_cb.task("Init Info...");
1159 dock_info = new studio::Dock_Info();
1160 dock_manager->register_dockable(*dock_info);
1162 studio_init_cb.task("Init Navigator...");
1163 dock_navigator = new studio::Dock_Navigator();
1164 dock_manager->register_dockable(*dock_navigator);
1166 studio_init_cb.task("Init Timetrack...");
1167 dock_timetrack = new studio::Dock_Timetrack();
1168 dock_manager->register_dockable(*dock_timetrack);
1170 studio_init_cb.task("Init Curve Editor...");
1171 dock_curves = new studio::Dock_Curves();
1172 dock_manager->register_dockable(*dock_curves);
1174 studio_init_cb.task("Init Layer Groups...");
1175 dock_layer_groups = new studio::Dock_LayerGroups();
1176 dock_manager->register_dockable(*dock_layer_groups);
1179 studio_init_cb.task("Init Color Dialog...");
1180 dialog_color=new studio::Dialog_Color();
1182 studio_init_cb.task("Init Gradient Dialog...");
1183 dialog_gradient=new studio::Dialog_Gradient();
1185 studio_init_cb.task("Init DeviceTracker...");
1186 device_tracker=new studio::DeviceTracker();
1188 studio_init_cb.task("Init Tools...");
1189 state_manager->add_state(&state_normal);
1190 state_manager->add_state(&state_smooth_move);
1191 state_manager->add_state(&state_scale);
1192 state_manager->add_state(&state_rotate);
1194 state_manager->add_state(&state_bline);
1195 state_manager->add_state(&state_polygon);
1196 state_manager->add_state(&state_circle);
1197 state_manager->add_state(&state_rectangle);
1199 state_manager->add_state(&state_draw);
1200 state_manager->add_state(&state_sketch);
1202 state_manager->add_state(&state_eyedrop);
1203 state_manager->add_state(&state_fill);
1205 state_manager->add_state(&state_width);
1206 state_manager->add_state(&state_gradient);
1208 state_manager->add_state(&state_zoom);
1210 studio_init_cb.task("Init ModPalette...");
1211 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1213 studio_init_cb.task("Init ModMirror...");
1214 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1217 studio_init_cb.task("Init Setup Dialog...");
1218 dialog_setup=new studio::Dialog_Setup();
1220 studio_init_cb.task("Init Input Dialog...");
1221 dialog_input=new Gtk::InputDialog();
1223 studio_init_cb.task("Init auto recovery...");
1224 auto_recover=new AutoRecover();
1226 studio_init_cb.amount_complete(9250,10000);
1227 studio_init_cb.task("Loading Settings...");
1229 studio_init_cb.task("Checking auto-recover...");
1231 studio_init_cb.amount_complete(9900,10000);
1233 if(auto_recover->recovery_needed())
1235 about_window.hide();
1237 get_ui_interface()->yes_no(
1239 "SINFG Studio seems to have crashed\n"
1240 "before you could save all your files.\n"
1241 "Would you like to re-open those files\n"
1242 "and recover your unsaved changes?"
1243 )==sinfgapp::UIInterface::RESPONSE_YES
1246 if(!auto_recover->recover())
1248 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1251 get_ui_interface()->error(
1252 _("SINFG Studio has attempted to recover\n"
1253 "from a previous crash. The files that it has\n"
1254 "recovered are NOT YET SAVED. It would be a good\n"
1255 "idea to review them and save them now.")
1258 about_window.show();
1261 // Look for any files given on the command line,
1262 // and load them if found.
1263 for(;*argc>=1;(*argc)--)
1264 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1266 studio_init_cb.task("Loading files...");
1267 about_window.hide();
1268 open((*argv)[*argc]);
1269 about_window.show();
1272 studio_init_cb.task("Done.");
1273 studio_init_cb.amount_complete(10000,10000);
1279 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1283 StateManager* App::get_state_manager() { return state_manager; }
1287 shutdown_in_progress=true;
1291 sinfgapp::Main::settings().remove_domain("pref");
1293 selected_instance=0;
1295 // Unload all of the modules
1296 for(;!module_list_.empty();module_list_.pop_back());
1298 delete state_manager;
1302 delete auto_recover;
1306 // studio::App::iteration(false);
1310 // studio::App::iteration(false);
1312 // studio::App::iteration(false);
1314 delete dialog_setup;
1316 delete dialog_gradient;
1318 delete dialog_color;
1320 delete dialog_input;
1322 delete dock_manager;
1324 instance_list.clear();
1326 // studio::App::iteration(false);
1330 App::get_user_app_directory()
1332 return Glib::build_filename(Glib::get_home_dir(),"sinfg");
1336 App::get_config_file(const sinfg::String& file)
1338 return Glib::build_filename(get_user_app_directory(),file);
1342 App::add_recent_file(const std::string &file_name)
1344 std::string filename(file_name);
1346 assert(!filename.empty());
1348 if(filename.empty())
1351 // Toss out any "hidden" files
1352 if(basename(filename)[0]=='.')
1355 // If we aren't an absolute path, turn outselves into one
1356 if(!is_absolute_path(filename))
1357 filename=absolute_path(filename);
1359 list<string>::iterator iter;
1360 // Check to see if the file is already on the list.
1361 // If it is, then remove it from the list
1362 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1365 recent_files.erase(iter);
1370 // Push the filename to the front of the list
1371 recent_files.push_front(filename);
1373 // Clean out the files at the end of the list.
1374 while(recent_files.size()>(unsigned)get_max_recent_files())
1375 recent_files.pop_back();
1377 signal_recent_files_changed_();
1382 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1385 App::get_time_format()
1387 return _App_time_format;
1391 App::set_time_format(sinfg::Time::Format x)
1398 App::save_settings()
1403 std::string filename=get_config_file("accelrc");
1404 Gtk::AccelMap::save(filename);
1407 std::string filename=get_config_file("recentfiles");
1409 std::ofstream file(filename.c_str());
1413 sinfg::warning("Unable to save %s",filename.c_str());
1417 list<string>::reverse_iterator iter;
1419 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1423 std::string filename=get_config_file("settings");
1424 sinfgapp::Main::settings().save_to_file(filename);
1428 sinfg::warning("Caught exception when attempting to save settings.");
1433 App::load_settings()
1438 std::string filename=get_config_file("accelrc");
1439 Gtk::AccelMap::load(filename);
1442 std::string filename=get_config_file("recentfiles");
1444 std::ifstream file(filename.c_str());
1448 std::string recent_file;
1449 getline(file,recent_file);
1450 if(!recent_file.empty())
1451 add_recent_file(recent_file);
1454 std::string filename=get_config_file("settings");
1455 if(!sinfgapp::Main::settings().load_from_file(filename))
1457 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".sinfgrc");
1458 //if(!sinfgapp::Main::settings().load_from_file(filename))
1460 gamma.set_gamma(1.0/2.2);
1461 sinfgapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1462 sinfgapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1463 sinfgapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1464 sinfgapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1465 sinfgapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1466 sinfgapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1467 sinfgapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1468 sinfgapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1469 sinfgapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1470 sinfgapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1471 sinfgapp::Main::settings().set_value("pref.distance_system","pt");
1472 sinfgapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1473 sinfgapp::Main::settings().set_value("window.toolbox.pos","4 4");
1480 sinfg::warning("Caught exception when attempting to load settings.");
1485 App::shutdown_request(GdkEventAny*)
1489 //return !shutdown_in_progress;
1495 if(shutdown_in_progress)return;
1498 get_ui_interface()->task("Quit Request");
1501 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1505 std::list<etl::handle<Instance> >::iterator iter;
1506 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1508 if(!(*iter)->safe_close())
1512 if((*iter)->sinfgapp::Instance::get_action_count())
1514 handle<sinfgapp::UIInterface> uim;
1515 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1517 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1518 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,sinfgapp::UIInterface::RESPONSE_YES))
1520 case sinfgapp::UIInterface::RESPONSE_NO:
1522 case sinfgapp::UIInterface::RESPONSE_YES:
1525 case sinfgapp::UIInterface::RESPONSE_CANCEL:
1534 if((*iter)->sinfgapp::Instance::is_modified())
1536 handle<sinfgapp::UIInterface> uim;
1537 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1539 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() );
1540 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,sinfgapp::UIInterface::RESPONSE_YES))
1542 case sinfgapp::UIInterface::RESPONSE_NO:
1544 case sinfgapp::UIInterface::RESPONSE_YES:
1545 (*iter)->dialog_cvs_commit();
1547 case sinfgapp::UIInterface::RESPONSE_CANCEL:
1556 // This next line causes things to crash for some reason
1560 shutdown_in_progress=true;
1562 instance_list.clear();
1564 while(studio::App::events_pending())studio::App::iteration(false);
1567 auto_recover->normal_shutdown();
1569 get_ui_interface()->task("Quit Request sent");
1575 dialog_setup->refresh();
1576 dialog_setup->show();
1579 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1580 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1583 //#define USE_WIN32_FILE_DIALOGS 1
1586 #ifdef USE_WIN32_FILE_DIALOGS
1587 static OPENFILENAME ofn={};
1591 #include <gdk/gdkwin32.h>
1595 App::dialog_open_file(const std::string &title, std::string &filename)
1597 #ifdef USE_WIN32_FILE_DIALOGS
1598 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1600 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1601 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1602 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1604 ofn.lStructSize=sizeof(OPENFILENAME);
1605 ofn.hwndOwner = hWnd;
1606 ofn.hInstance = hInstance;
1607 ofn.lpstrFilter = szFilter;
1608 // ofn.lpstrCustomFilter=NULL;
1609 // ofn.nMaxCustFilter=0;
1610 // ofn.nFilterIndex=0;
1611 // ofn.lpstrFile=NULL;
1612 ofn.nMaxFile=MAX_PATH;
1613 // ofn.lpstrFileTitle=NULL;
1614 // ofn.lpstrInitialDir=NULL;
1615 // ofn.lpstrTitle=NULL;
1616 ofn.Flags=OFN_HIDEREADONLY;
1617 // ofn.nFileOffset=0;
1618 // ofn.nFileExtension=0;
1619 ofn.lpstrDefExt=TEXT("sif");
1620 // ofn.lCustData = 0l;
1622 // ofn.lpTemplateName=NULL;
1624 CHAR szFilename[MAX_PATH];
1626 strcpy(szFilename,filename.c_str());
1627 strcpy(szTitle,title.c_str());
1629 ofn.lpstrFile=szFilename;
1630 ofn.lpstrFileTitle=szTitle;
1632 if(GetOpenFileName(&ofn))
1634 filename=szFilename;
1640 sinfg::String prev_path;
1641 if(!_preferences.get_value("curr_path",prev_path))
1648 GtkWidget *fileselection;
1649 fileselection = gtk_file_selection_new(title.c_str());
1652 if(basename(filename)==filename)
1654 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1657 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1659 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1661 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1662 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1664 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1665 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1667 gtk_widget_show(fileselection);
1675 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1676 _preferences.set_value("curr_path",dirname(filename));
1680 gtk_widget_destroy(fileselection);
1683 gtk_widget_destroy(fileselection);
1689 App::dialog_save_file(const std::string &title, std::string &filename)
1691 #ifdef USE_WIN32_FILE_DIALOGS
1692 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1694 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1695 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1696 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1698 ofn.lStructSize=sizeof(OPENFILENAME);
1699 ofn.hwndOwner = hWnd;
1700 ofn.hInstance = hInstance;
1701 ofn.lpstrFilter = szFilter;
1702 // ofn.lpstrCustomFilter=NULL;
1703 // ofn.nMaxCustFilter=0;
1704 // ofn.nFilterIndex=0;
1705 // ofn.lpstrFile=NULL;
1706 ofn.nMaxFile=MAX_PATH;
1707 // ofn.lpstrFileTitle=NULL;
1708 // ofn.lpstrInitialDir=NULL;
1709 // ofn.lpstrTitle=NULL;
1710 ofn.Flags=OFN_OVERWRITEPROMPT;
1711 // ofn.nFileOffset=0;
1712 // ofn.nFileExtension=0;
1713 ofn.lpstrDefExt=TEXT("sif");
1714 // ofn.lCustData = 0l;
1716 // ofn.lpTemplateName=NULL;
1718 CHAR szFilename[MAX_PATH];
1720 strcpy(szFilename,filename.c_str());
1721 strcpy(szTitle,title.c_str());
1723 ofn.lpstrFile=szFilename;
1724 ofn.lpstrFileTitle=szTitle;
1726 if(GetSaveFileName(&ofn))
1728 filename=szFilename;
1733 return dialog_open_file(title, filename);
1738 App::dialog_saveas_file(const std::string &title, std::string &filename)
1740 #if USE_WIN32_FILE_DIALOGS
1741 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1743 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1744 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1745 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1747 ofn.lStructSize=sizeof(OPENFILENAME);
1748 ofn.hwndOwner = hWnd;
1749 ofn.hInstance = hInstance;
1750 ofn.lpstrFilter = szFilter;
1751 // ofn.lpstrCustomFilter=NULL;
1752 // ofn.nMaxCustFilter=0;
1753 // ofn.nFilterIndex=0;
1754 // ofn.lpstrFile=NULL;
1755 ofn.nMaxFile=MAX_PATH;
1756 // ofn.lpstrFileTitle=NULL;
1757 // ofn.lpstrInitialDir=NULL;
1758 // ofn.lpstrTitle=NULL;
1759 ofn.Flags=OFN_OVERWRITEPROMPT;
1760 // ofn.nFileOffset=0;
1761 // ofn.nFileExtension=0;
1762 ofn.lpstrDefExt=TEXT("sif");
1763 // ofn.lCustData = 0l;
1765 // ofn.lpTemplateName=NULL;
1767 CHAR szFilename[MAX_PATH];
1769 strcpy(szFilename,filename.c_str());
1770 strcpy(szTitle,title.c_str());
1772 ofn.lpstrFile=szFilename;
1773 ofn.lpstrFileTitle=szTitle;
1775 if(GetSaveFileName(&ofn))
1777 filename=szFilename;
1782 return dialog_open_file(title, filename);
1787 App::dialog_error_blocking(const std::string &title, const std::string &message)
1792 true // use_separator
1794 Gtk::Label label(message);
1797 dialog.get_vbox()->pack_start(label);
1798 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1804 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1809 true // use_separator
1811 Gtk::Label label(message);
1814 dialog.get_vbox()->pack_start(label);
1815 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1821 App::dialog_yes_no(const std::string &title, const std::string &message)
1826 true // use_separator
1828 Gtk::Label label(message);
1831 dialog.get_vbox()->pack_start(label);
1832 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1833 dialog.add_button(Gtk::StockID("gtk-no"),0);
1835 return dialog.run();
1839 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1844 true // use_separator
1846 Gtk::Label label(message);
1849 dialog.get_vbox()->pack_start(label);
1850 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1851 dialog.add_button(Gtk::StockID("gtk-no"),0);
1852 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1854 return dialog.run();
1858 App::dialog_not_implemented()
1861 "Feature not available", // Title
1863 true // use_separator
1865 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1868 dialog.get_vbox()->pack_start(label);
1869 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1875 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1880 true // use_separator
1882 Gtk::Label label(message);
1884 dialog.get_vbox()->pack_start(label);
1887 entry.set_text(text);
1889 entry.set_activates_default(true);
1890 dialog.get_vbox()->pack_start(entry);
1892 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1893 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1894 dialog.set_default_response(Gtk::RESPONSE_OK);
1895 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1898 if(dialog.run()!=Gtk::RESPONSE_OK)
1901 text=entry.get_text();
1910 App::open(std::string filename)
1912 return open_as(filename,filename);
1916 App::open_as(std::string filename,std::string as)
1920 OneMoment one_moment;
1922 etl::handle<sinfg::Canvas> canvas(open_canvas_as(filename,as));
1923 if(canvas && get_instance(canvas))
1925 get_instance(canvas)->find_canvas_view(canvas)->present();
1926 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1929 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1931 add_recent_file(as);
1933 handle<Instance> instance(Instance::create(canvas));
1936 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1940 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)")))
1941 instance->dialog_cvs_update();
1945 dialog_error_blocking(_("Error"), x);
1950 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1954 _preferences.set_value("curr_path",dirname(as));
1963 handle<sinfg::Canvas> canvas=sinfg::Canvas::create();
1964 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
1966 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
1968 canvas->rend_desc().set_frame_rate(24.0);
1969 canvas->rend_desc().set_time_start(0.0);
1970 canvas->rend_desc().set_time_end(00.0);
1971 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1972 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1973 canvas->rend_desc().set_tl(Vector(-4,2.25));
1974 canvas->rend_desc().set_br(Vector(4,-2.25));
1975 canvas->rend_desc().set_w(480);
1976 canvas->rend_desc().set_h(270);
1977 canvas->rend_desc().set_antialias(1);
1978 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1979 canvas->set_file_name(file_name);
1981 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
1987 string filename="*.sif";
1989 while(dialog_open_file("Open", filename))
1991 // If the filename still has wildcards, then we should
1992 // continue looking for the file we want
1993 if(find(filename.begin(),filename.end(),'*')!=filename.end())
1999 get_ui_interface()->error(_("Unable to open file"));
2004 App::set_selected_instance(etl::loose_handle<Instance> instance)
2006 /* if(get_selected_instance()==instance)
2008 selected_instance=instance;
2009 signal_instance_selected()(instance);
2015 selected_instance=instance;
2016 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2020 instance->focus(instance->get_canvas());
2023 set_selected_canvas_view(0);
2025 signal_instance_selected()(instance);
2029 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2031 selected_canvas_view=canvas_view;
2032 signal_canvas_view_focus()(selected_canvas_view);
2035 selected_instance=canvas_view->get_instance();
2036 signal_instance_selected()(canvas_view->get_instance());
2039 if(get_selected_canvas_view()==canvas_view)
2041 signal_canvas_view_focus()(selected_canvas_view);
2042 signal_instance_selected()(canvas_view->get_instance());
2045 selected_canvas_view=canvas_view;
2046 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2047 set_selected_instance(canvas_view->get_instance());
2048 signal_canvas_view_focus()(selected_canvas_view);
2052 etl::loose_handle<Instance>
2053 App::get_instance(Canvas::Handle canvas)
2055 if(!canvas) return 0;
2056 canvas=canvas->get_root();
2058 std::list<etl::handle<Instance> >::iterator iter;
2059 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2061 if((*iter)->get_canvas()==canvas)
2070 (new class About())->show();
2076 if(selected_instance)
2077 selected_instance->undo();
2083 if(selected_instance)
2084 selected_instance->redo();
2088 studio::App::get_base_path()
2090 return app_base_path_;