X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;ds=sidebyside;f=synfig-studio%2Ftags%2Fsynfigstudio_0_61_05%2Fsynfig-studio%2Fsrc%2Fgtkmm%2Fapp.cpp;fp=synfig-studio%2Ftags%2Fsynfigstudio_0_61_05%2Fsynfig-studio%2Fsrc%2Fgtkmm%2Fapp.cpp;h=14c962e64cde25987c06078e7c6af569b6a02746;hb=7ba2096dd58b21ba3a08b28b5a6f70795f6ea265;hp=0000000000000000000000000000000000000000;hpb=043865a2284e71de646b09cc0f22b5674b95a454;p=synfig.git diff --git a/synfig-studio/tags/synfigstudio_0_61_05/synfig-studio/src/gtkmm/app.cpp b/synfig-studio/tags/synfigstudio_0_61_05/synfig-studio/src/gtkmm/app.cpp new file mode 100644 index 0000000..14c962e --- /dev/null +++ b/synfig-studio/tags/synfigstudio_0_61_05/synfig-studio/src/gtkmm/app.cpp @@ -0,0 +1,2166 @@ +/* === S Y N F I G ========================================================= */ +/*! \file app.cpp +** \brief writeme +** +** $Id: app.cpp,v 1.11 2005/03/24 21:47:28 darco Exp $ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifdef HAVE_SYS_ERRNO_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "app.h" +#include "about.h" +#include "instance.h" +#include "canvasview.h" +#include "dialog_setup.h" +#include "dialog_gradient.h" +#include "dialog_color.h" +#include "toolbox.h" +#include "compview.h" +#include "onemoment.h" + +#include "dockmanager.h" + +#include "state_eyedrop.h" +#include "state_normal.h" +#include "state_draw.h" +#include "state_fill.h" +#include "state_bline.h" +#include "state_polygon.h" +#include "state_sketch.h" +#include "state_gradient.h" +#include "state_circle.h" +#include "state_rectangle.h" +#include "state_smoothmove.h" +#include "state_scale.h" +#include "state_width.h" +#include "state_rotate.h" +#include "state_zoom.h" + +#include "devicetracker.h" +#include "dialog_tooloptions.h" + +#include "autorecover.h" + +#include +#include "dock_history.h" +#include "dock_canvases.h" +#include "dock_keyframes.h" +#include "dock_layers.h" +#include "dock_params.h" +#include "dock_metadata.h" +#include "dock_children.h" +#include "dock_info.h" +#include "dock_navigator.h" +#include "dock_layergroups.h" +#include "dock_timetrack.h" +#include "dock_curves.h" + +#include "mod_palette/mod_palette.h" +#include "mod_mirror/mod_mirror.h" + +#include + +#include "ipc.h" + +#include "module.h" + +#include "statemanager.h" + +#ifdef WITH_FMOD +#include +#endif + +#ifdef WIN32 +#define _WIN32_WINNT 0x0500 +#include +#endif +#include +#include +#include + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +#ifndef SYNFIG_USER_APP_DIR +#ifdef __APPLE__ +#define SYNFIG_USER_APP_DIR "Library/Synfig" +#else +#define SYNFIG_USER_APP_DIR "Synfig" +#endif +#endif + +#ifndef DPM2DPI +#define DPM2DPI(x) (float(x)/39.3700787402f) +#define DPI2DPM(x) (float(x)*39.3700787402f) +#endif + +#ifdef WIN32 +# ifdef IMAGE_DIR +# undef IMAGE_DIR +# define IMAGE_DIR "share\\pixmaps" +# endif +#endif + +#ifndef IMAGE_DIR +# define IMAGE_DIR "/usr/local/share/pixmaps" +#endif + +#ifndef IMAGE_EXT +# define IMAGE_EXT "tif" +#endif + +#include + +/* === S I G N A L S ======================================================= */ + +static sigc::signal signal_present_all_; +sigc::signal& +App::signal_present_all() { return signal_present_all_; } + +static sigc::signal signal_recent_files_changed_; +sigc::signal& +App::signal_recent_files_changed() { return signal_recent_files_changed_; } + +static sigc::signal > signal_canvas_view_focus_; +sigc::signal >& +App::signal_canvas_view_focus() { return signal_canvas_view_focus_; } + +static sigc::signal > signal_instance_selected_; +sigc::signal >& +App::signal_instance_selected() { return signal_instance_selected_; } + +static sigc::signal > signal_instance_created_; +sigc::signal >& +App::signal_instance_created() { return signal_instance_created_; } + +static sigc::signal > signal_instance_deleted_; +sigc::signal >& +App::signal_instance_deleted() { return signal_instance_deleted_; } + +/* === G L O B A L S ======================================================= */ + +static std::list recent_files; +const std::list& App::get_recent_files() { return recent_files; } + +int App::Busy::count; +bool App::shutdown_in_progress; + +synfig::Gamma App::gamma; + +Glib::RefPtr App::ui_manager_; + +synfig::Distance::System App::distance_system; + +studio::Dialog_Setup* App::dialog_setup; + +etl::handle< studio::ModPalette > mod_palette_; +//studio::Dialog_Palette* App::dialog_palette; + +std::list > App::instance_list; + +static etl::handle ui_interface_; +const etl::handle& App::get_ui_interface() { return ui_interface_; } + +etl::handle App::selected_instance; +etl::handle App::selected_canvas_view; + +studio::Toolbox *studio::App::toolbox=NULL; + +studio::AutoRecover *studio::App::auto_recover=NULL; + +studio::IPC *ipc=NULL; + +studio::DockManager* studio::App::dock_manager=0; + +studio::DeviceTracker* studio::App::device_tracker=0; + +studio::Dialog_Gradient* studio::App::dialog_gradient; + +studio::Dialog_Color* studio::App::dialog_color; + +Gtk::InputDialog* studio::App::dialog_input; + +studio::Dialog_ToolOptions* studio::App::dialog_tool_options; + +studio::Dock_History* dock_history; +studio::Dock_Canvases* dock_canvases; +studio::Dock_Keyframes* dock_keyframes; +studio::Dock_Layers* dock_layers; +studio::Dock_Params* dock_params; +studio::Dock_MetaData* dock_meta_data; +studio::Dock_Children* dock_children; +studio::Dock_Info* dock_info; +studio::Dock_LayerGroups* dock_layer_groups; +studio::Dock_Navigator* dock_navigator; +studio::Dock_Timetrack* dock_timetrack; +studio::Dock_Curves* dock_curves; + +std::list< etl::handle< studio::Module > > module_list_; + +bool studio::App::use_colorspace_gamma=true; + +static int max_recent_files_=25; +int studio::App::get_max_recent_files() { return max_recent_files_; } +void studio::App::set_max_recent_files(int x) { max_recent_files_=x; } + +static synfig::String app_base_path_; + +namespace studio { +}; // END of namespace studio +studio::StateManager* state_manager; + + + + +class GlobalUIInterface : public synfigapp::UIInterface +{ +public: + + virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES) + { + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES); + dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO); + + dialog.set_default_response(dflt); + dialog.show(); + return (Response)dialog.run(); + } + virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES) + { + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES); + dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO); + dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL); + + dialog.set_default_response(dflt); + dialog.show(); + return (Response)dialog.run(); + } + virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK) + { + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK); + dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL); + + dialog.set_default_response(dflt); + dialog.show(); + return (Response)dialog.run(); + } + + virtual bool + task(const std::string &task) + { + std::cerr<pack_start(label); + dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK); + dialog.show(); + dialog.run(); + return true; + } + + virtual bool + warning(const std::string &err) + { + std::cerr<<"warning: "<element.serial=0; + unwound->element.checksum=0; + + for(i=0;i<16;i++) + { + U8 data; + + switch(key[i]) + { + case '0': data=0; break; + case '1': data=1; break; + case '2': data=2; break; + case '3': data=3; break; + case '4': data=4; break; + case '5': data=5; break; + case '6': data=6; break; + case '7': data=7; break; + case '8': data=8; break; + case '9': data=9; break; + case 'a': case 'A': data=10; break; + case 'b': case 'B': data=11; break; + case 'c': case 'C': data=12; break; + case 'd': case 'D': data=13; break; + case 'e': case 'E': data=14; break; + case 'f': case 'F': data=15; break; + default: return 0; break; + } + int bit=i*2; + unwound->element.checksum|=(((U32)data&3)<element.serial|=(((U32)(data>>2)&3)<>24); + } + } + + unwound_key.element.serial^=appid_mask_a; + unwound_key.element.checksum^=appid_mask_b; + + *serial=unwound_key.element.serial; + + return unwound_key.element.checksum==hash_U32(unwound_key.element.serial); +} + + +int check_license(String basedir) +{ +#ifdef LICENSE_KEY_REQUIRED + String key; + String license_file; + +#ifndef _WIN32 + license_file="/usr/local/etc/.synfiglicense"; +#else + license_file=basedir+"\\etc\\.synfiglicense"; +#endif + + try { + key=Glib::file_get_contents(license_file); + } catch (Glib::FileError) { } + U32 serial(0); + if(!v_key_check(key.c_str(),&serial,0xdeadbeef)) + { + while(!v_key_check(key.c_str(),&serial,0xdeadbeef)) + { + key.clear(); + + if(!App::dialog_entry( + _("Synfig Studio Authentication"), + _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."), + key + )) + throw String("No License"); + } + + FILE* file=fopen(license_file.c_str(),"w"); + if(file) + { + fprintf(file,"%s",key.c_str()); + fclose(file); + } + else + synfig::error("Unable to save license key!"); + } + synfig::info("License Authenticated -- Serial #%05d",serial); + return serial; +#else + return 1; +#endif +} + +/* +void +studio::UIManager::insert_action_group (const Glib::RefPtr& action_group, int pos) +{ + action_group_list.push_back(action_group); + Gtk::UIManager::insert_action_group(action_group, pos); +} + +void +studio::UIManager::remove_action_group (const Glib::RefPtr& action_group) +{ + std::list >::iterator iter; + for(iter=action_group_list.begin();iter!=action_group_list.end();++iter) + if(*iter==action_group) + { + action_group_list.erase(iter); + Gtk::UIManager::remove_action_group(action_group); + return; + } + synfig::error("Unable to find action group"); +} + +void +studio::add_action_group_to_top(Glib::RefPtr ui_manager, Glib::RefPtr group) +{ + ui_manager->insert_action_group(group,0); + return; + DEBUGPOINT(); + std::list > prev_groups(ui_manager->get_action_groups()); + std::list >::reverse_iterator iter; + + DEBUGPOINT(); + for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter) + { + DEBUGPOINT(); + if(*iter && (*iter)->get_name()!="menus") + { + synfig::info("Removing action group "+(*iter)->get_name()); + ui_manager->remove_action_group(*iter); + } + } + DEBUGPOINT(); + ui_manager->insert_action_group(group,0); + + DEBUGPOINT(); + for(;!prev_groups.empty();prev_groups.pop_front()) + { + if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus") + ui_manager->insert_action_group(prev_groups.front(),1); + } + DEBUGPOINT(); +} +*/ +class Preferences : public synfigapp::Settings +{ +public: + virtual bool get_value(const synfig::String& key, synfig::String& value)const + { + if(key=="gamma") + { + value=strprintf("%f %f %f %f", + App::gamma.get_gamma_r(), + App::gamma.get_gamma_g(), + App::gamma.get_gamma_b(), + App::gamma.get_black_level() + ); + return true; + } + if(key=="time_format") + { + value=strprintf("%i",App::get_time_format()); + return true; + } + if(key=="file_history.size") + { + value=strprintf("%i",App::get_max_recent_files()); + return true; + } + if(key=="use_colorspace_gamma") + { + value=strprintf("%i",(int)App::use_colorspace_gamma); + return true; + } + if(key=="distance_system") + { + value=strprintf("%s",Distance::system_name(App::distance_system).c_str()); + return true; + } + if(key=="auto_recover_backup_interval") + { + value=strprintf("%i",App::auto_recover->get_timeout()); + return true; + } + + return synfigapp::Settings::get_value(key,value); + } + + virtual bool set_value(const synfig::String& key,const synfig::String& value) + { + if(key=="gamma") + { + float r,g,b,blk; + + strscanf(value,"%f %f %f %f", + &r, + &g, + &b, + &blk + ); + + App::gamma.set_all(r,g,b,blk); + + return true; + } + if(key=="time_format") + { + int i(atoi(value.c_str())); + App::set_time_format(static_cast(i)); + return true; + } + if(key=="auto_recover_backup_interval") + { + int i(atoi(value.c_str())); + App::auto_recover->set_timeout(i); + return true; + } + if(key=="file_history.size") + { + int i(atoi(value.c_str())); + App::set_max_recent_files(i); + return true; + } + if(key=="use_colorspace_gamma") + { + int i(atoi(value.c_str())); + App::use_colorspace_gamma=i; + return true; + } + if(key=="distance_system") + { + App::distance_system=Distance::ident_system(value);; + return true; + } + + return synfigapp::Settings::set_value(key,value); + } + + virtual KeyList get_key_list()const + { + KeyList ret(synfigapp::Settings::get_key_list()); + ret.push_back("gamma"); + ret.push_back("time_format"); + ret.push_back("distance_system"); + ret.push_back("file_history.size"); + ret.push_back("use_colorspace_gamma"); + ret.push_back("auto_recover_backup_interval"); + return ret; + } +}; + +static ::Preferences _preferences; + +void +init_ui_manager() +{ + Glib::RefPtr menus_action_group = Gtk::ActionGroup::create("menus"); + + Glib::RefPtr toolbox_action_group = Gtk::ActionGroup::create("toolbox"); + + Glib::RefPtr actions_action_group = Gtk::ActionGroup::create(); + + menus_action_group->add( Gtk::Action::create("menu-file", "_File") ); + menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") ); + menus_action_group->add( Gtk::Action::create("menu-view", "_View") ); + menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") ); + menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") ); + menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") ); + menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") ); + menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") ); + menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") ); + menus_action_group->add( Gtk::Action::create("menu-group", "Group") ); + menus_action_group->add( Gtk::Action::create("menu-state", "State") ); + menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") ); + + // Add the synfigapp actions... + synfigapp::Action::Book::iterator iter; + for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter) + { + actions_action_group->add(Gtk::Action::create( + "action-"+iter->second.name, + get_action_stock_id(iter->second), + iter->second.local_name,iter->second.local_name + )); + } + +#define DEFINE_ACTION(x,stock) { Glib::RefPtr action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); } +#define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr action( Gtk::Action::create(x, stock,label,label) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); } +#define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ group->add(action,sig); } + + DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties")); + DEFINE_ACTION("about", Gtk::StockID("synfig-about")); + DEFINE_ACTION("open", Gtk::Stock::OPEN); + DEFINE_ACTION("save", Gtk::Stock::SAVE); + DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS); + DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED); + DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add")); + DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update")); + DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit")); + DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert")); + DEFINE_ACTION("import", _("Import")); + DEFINE_ACTION("render", _("Render")); + DEFINE_ACTION("preview", _("Preview")); + DEFINE_ACTION("dialog-flipbook", _("Preview Dialog")); + DEFINE_ACTION("sound", _("Sound File")); + DEFINE_ACTION("options", _("Options")); + DEFINE_ACTION("close", _("Close")); + + + DEFINE_ACTION("undo", Gtk::StockID("gtk-undo")); + DEFINE_ACTION("redo", Gtk::StockID("gtk-redo")); + DEFINE_ACTION("cut", Gtk::StockID("gtk-cut")); + DEFINE_ACTION("copy", Gtk::StockID("gtk-copy")); + DEFINE_ACTION("paste", Gtk::StockID("gtk-paste")); + DEFINE_ACTION("select-all-ducks", _("Select All Ducks")); + DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers")); + DEFINE_ACTION("properties", _("Properties")); + + DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks")); + DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks")); + DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks")); + DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks")); + DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks")); + DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks")); + DEFINE_ACTION("quality-00", _("Use Parametric Renderer")); + DEFINE_ACTION("quality-01", _("Use Quality Level 1")); + DEFINE_ACTION("quality-02", _("Use Quality Level 2")); + DEFINE_ACTION("quality-03", _("Use Quality Level 3")); + DEFINE_ACTION("quality-04", _("Use Quality Level 4")); + DEFINE_ACTION("quality-05", _("Use Quality Level 5")); + DEFINE_ACTION("quality-06", _("Use Quality Level 6")); + DEFINE_ACTION("quality-07", _("Use Quality Level 7")); + DEFINE_ACTION("quality-08", _("Use Quality Level 8")); + DEFINE_ACTION("quality-09", _("Use Quality Level 9")); + DEFINE_ACTION("quality-10", _("Use Quality Level 10")); + DEFINE_ACTION("play", _("Play")); + DEFINE_ACTION("pause", _("Pause")); + DEFINE_ACTION("stop", _("Stop")); + DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show")); + DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap")); + DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show")); + DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res")); + DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin")); + DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in")); + DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out")); + DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit")); + DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100")); + DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in")); + DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out")); + DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe")); + DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe")); + DEFINE_ACTION("seek-next-frame", _("Next Frame")); + DEFINE_ACTION("seek-prev-frame", _("Prev Frame")); + DEFINE_ACTION("seek-next-second", _("Seek Forward")); + DEFINE_ACTION("seek-prev-second", _("Seek Backward")); + DEFINE_ACTION("seek-begin", _("Seek to Begin")); + DEFINE_ACTION("seek-end", _("Seek to End")); + + DEFINE_ACTION("action-group_add", _("Add group")); + + DEFINE_ACTION("canvas-new", _("New Canvas")); + + DEFINE_ACTION("amount-inc", _("Increase Amount")); + DEFINE_ACTION("amount-dec", _("Decrease Amount")); + +#undef DEFINE_ACTION + + +// Set up synfigapp actions + /*{ + synfigapp::Action::Book::iterator iter; + + for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter) + { + Gtk::StockID stock_id; + + if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN)) + { + //Gtk::Image* image(manage(new Gtk::Image())); + if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP; + else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN; + else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP; + else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM; + else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE; + else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES; + else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO; + //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY; + else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE; + else stock_id=Gtk::StockID("synfig-"+iter->second.task); + + actions_action_group->add(Gtk::Action::create( + "action-"+iter->second.name, + stock_id, + iter->second.local_name,iter->second.local_name + )); + } + } + } +*/ + + + Glib::ustring ui_info = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " + " " + " " +" " +" " +" " +" " +" " +" " +" " +//" " +//" " +//" " +//" " +" " +" " +" " +" " +" " +" " + +"" +; +/* "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; +*/ + try + { + actions_action_group->set_sensitive(false); + App::ui_manager()->set_add_tearoffs(true); + App::ui_manager()->insert_action_group(menus_action_group,1); + App::ui_manager()->insert_action_group(actions_action_group,1); + App::ui_manager()->add_ui_from_string(ui_info); + + //App::ui_manager()->get_accel_group()->unlock(); + } + catch(const Glib::Error& ex) + { + synfig::error("building menus and toolbars failed: " + ex.what()); + } + + // Add default keyboard accelerators +#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()); } +#define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); } + ACCEL("//select-all-ducks","a"); + ACCEL("//unselect-all-layers","d"); + ACCEL("//render","F9"); + ACCEL("//preview","F11"); + ACCEL("//properties","F8"); + ACCEL("//options","F12"); + ACCEL("//import","i"); + ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast(0),"//stop")); + ACCEL("//toggle-grid-show","g"); + ACCEL("//toggle-grid-snap","l"); + ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"//toggle-low-res")); + ACCEL("//mask-position-ducks", "1"); + ACCEL("//mask-vertex-ducks", "2"); + ACCEL("//mask-tangent-ducks", "3"); + ACCEL("//mask-radius-ducks", "4"); + ACCEL("//mask-width-ducks", "5"); + ACCEL("//mask-angle-ducks", "6"); + + + ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"//action-layer_raise")); + ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"//action-layer_lower")); + + ACCEL("//quality-01","1"); + ACCEL("//quality-02","2"); + ACCEL("//quality-03","3"); + ACCEL("//quality-04","4"); + ACCEL("//quality-05","5"); + ACCEL("//quality-06","6"); + ACCEL("//quality-07","7"); + ACCEL("//quality-08","8"); + ACCEL("//quality-09","9"); + ACCEL("//quality-10","0"); + ACCEL("//undo","z"); + ACCEL("//redo","r"); + ACCEL("//action-layer_remove","Delete"); + +/* ACCEL2(Gtk::AccelKey(']',static_cast(0),"//jump-next-keyframe")); + ACCEL2(Gtk::AccelKey('[',static_cast(0),"//jump-prev-keyframe")); + ACCEL2(Gtk::AccelKey('=',static_cast(0),"//canvas-zoom-in")); + ACCEL2(Gtk::AccelKey('-',static_cast(0),"//canvas-zoom-out")); + ACCEL("//time-zoom-in","+"); + ACCEL("//time-zoom-out","_"); +*/ + ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"//amount-dec")); + ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"//amount-inc")); + + ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"//jump-next-keyframe")); + ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"//jump-prev-keyframe")); + ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"//canvas-zoom-in")); + ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"//canvas-zoom-out")); + ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"//time-zoom-in")); + ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"//time-zoom-out")); + ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"//seek-next-frame")); + ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"//seek-prev-frame")); + ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"//seek-next-second")); + ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"//seek-prev-second")); + ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"//toggle-onion-skin")); + ACCEL("//seek-begin","Home"); + ACCEL("//seek-end","End"); + ACCEL("//state-normal","a"); + ACCEL("//state-rotate","s"); + ACCEL("//state-scale","d"); + ACCEL("//state-bline","b"); + ACCEL("//state-fill","f"); + ACCEL("//state-eyedrop","e"); + ACCEL("//state-gradient","g"); + ACCEL("//state-zoom","z"); + ACCEL("//canvas-zoom-fit","z"); + +#undef ACCEL +} + +#ifdef _WIN32 +#define mkdir(x,y) mkdir(x) +#endif + +/* === M E T H O D S ======================================================= */ + +App::App(int *argc, char ***argv): + Gtk::Main(argc,argv), + IconControler(etl::dirname((*argv)[0])) +{ + app_base_path_=etl::dirname(etl::dirname((*argv)[0])); + + int serial_; + serial_=check_license(app_base_path_); + + + ui_interface_=new GlobalUIInterface(); + + gdk_rgb_init(); + + Glib::thread_init(); + + distance_system=Distance::SYSTEM_UNITS; + + if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0) + { + if(errno!=EEXIST) + synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str()); + } + else + { + synfig::info("Created directory \"%s\"",get_user_app_directory().c_str()); + } + + + ipc=new IPC(); + + try + { + if(!SYNFIG_CHECK_VERSION()) + { + cerr<<"FATAL: Synfig Version Mismatch"<(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); } + catch(...) + { + get_ui_interface()->error("Failed to initialize synfig!"); + throw; + } + + // add the preferences to the settings + synfigapp::Main::settings().add_domain(&_preferences,"pref"); + + try + { + studio_init_cb.task("Init UI Manager..."); + App::ui_manager_=studio::UIManager::create(); + init_ui_manager(); + + studio_init_cb.task("Init Dock Manager..."); + dock_manager=new studio::DockManager(); + + studio_init_cb.task("Init State Manager..."); + state_manager=new StateManager(); + + studio_init_cb.task("Init Toolbox..."); + toolbox=new studio::Toolbox(); + + studio_init_cb.task("Init Tool Options..."); + dialog_tool_options=new studio::Dialog_ToolOptions(); + dock_manager->register_dockable(*dialog_tool_options); + + studio_init_cb.task("Init History..."); + dock_history=new studio::Dock_History(); + dock_manager->register_dockable(*dock_history); + + studio_init_cb.task("Init Canvases..."); + dock_canvases=new studio::Dock_Canvases(); + dock_manager->register_dockable(*dock_canvases); + + studio_init_cb.task("Init Keyframes..."); + dock_keyframes=new studio::Dock_Keyframes(); + dock_manager->register_dockable(*dock_keyframes); + + studio_init_cb.task("Init Layers..."); + dock_layers=new studio::Dock_Layers(); + dock_manager->register_dockable(*dock_layers); + + studio_init_cb.task("Init Params..."); + dock_params=new studio::Dock_Params(); + dock_manager->register_dockable(*dock_params); + + studio_init_cb.task("Init MetaData..."); + dock_meta_data=new studio::Dock_MetaData(); + dock_manager->register_dockable(*dock_meta_data); + + studio_init_cb.task("Init Children..."); + dock_children=new studio::Dock_Children(); + dock_manager->register_dockable(*dock_children); + + studio_init_cb.task("Init Info..."); + dock_info = new studio::Dock_Info(); + dock_manager->register_dockable(*dock_info); + + studio_init_cb.task("Init Navigator..."); + dock_navigator = new studio::Dock_Navigator(); + dock_manager->register_dockable(*dock_navigator); + + studio_init_cb.task("Init Timetrack..."); + dock_timetrack = new studio::Dock_Timetrack(); + dock_manager->register_dockable(*dock_timetrack); + + studio_init_cb.task("Init Curve Editor..."); + dock_curves = new studio::Dock_Curves(); + dock_manager->register_dockable(*dock_curves); + + studio_init_cb.task("Init Layer Groups..."); + dock_layer_groups = new studio::Dock_LayerGroups(); + dock_manager->register_dockable(*dock_layer_groups); + + + studio_init_cb.task("Init Color Dialog..."); + dialog_color=new studio::Dialog_Color(); + + studio_init_cb.task("Init Gradient Dialog..."); + dialog_gradient=new studio::Dialog_Gradient(); + + studio_init_cb.task("Init DeviceTracker..."); + device_tracker=new studio::DeviceTracker(); + + studio_init_cb.task("Init Tools..."); + state_manager->add_state(&state_normal); + state_manager->add_state(&state_smooth_move); + state_manager->add_state(&state_scale); + state_manager->add_state(&state_rotate); + + state_manager->add_state(&state_bline); + state_manager->add_state(&state_polygon); + state_manager->add_state(&state_circle); + state_manager->add_state(&state_rectangle); + + state_manager->add_state(&state_draw); + state_manager->add_state(&state_sketch); + + state_manager->add_state(&state_eyedrop); + state_manager->add_state(&state_fill); + + state_manager->add_state(&state_width); + state_manager->add_state(&state_gradient); + + state_manager->add_state(&state_zoom); + + studio_init_cb.task("Init ModPalette..."); + module_list_.push_back(new ModPalette()); module_list_.back()->start(); + + studio_init_cb.task("Init ModMirror..."); + module_list_.push_back(new ModMirror()); module_list_.back()->start(); + + + studio_init_cb.task("Init Setup Dialog..."); + dialog_setup=new studio::Dialog_Setup(); + + studio_init_cb.task("Init Input Dialog..."); + dialog_input=new Gtk::InputDialog(); + + studio_init_cb.task("Init auto recovery..."); + auto_recover=new AutoRecover(); + + studio_init_cb.amount_complete(9250,10000); + studio_init_cb.task("Loading Settings..."); + load_settings(); + studio_init_cb.task("Checking auto-recover..."); + + studio_init_cb.amount_complete(9900,10000); + + if(auto_recover->recovery_needed()) + { + about_window.hide(); + if( + get_ui_interface()->yes_no( + "Auto Recovery", + "SYNFIG Studio seems to have crashed\n" + "before you could save all your files.\n" + "Would you like to re-open those files\n" + "and recover your unsaved changes?" + )==synfigapp::UIInterface::RESPONSE_YES + ) + { + if(!auto_recover->recover()) + { + get_ui_interface()->error(_("Unable to fully recover from previous crash")); + } + else + get_ui_interface()->error( + _("SYNFIG Studio has attempted to recover\n" + "from a previous crash. The files that it has\n" + "recovered are NOT YET SAVED. It would be a good\n" + "idea to review them and save them now.") + ); + } + about_window.show(); + } + + // Look for any files given on the command line, + // and load them if found. + for(;*argc>=1;(*argc)--) + if((*argv)[*argc] && (*argv)[*argc][0]!='-') + { + studio_init_cb.task("Loading files..."); + about_window.hide(); + open((*argv)[*argc]); + about_window.show(); + } + + studio_init_cb.task("Done."); + studio_init_cb.amount_complete(10000,10000); + + toolbox->present(); + } + catch(...) + { + get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.")); + } +} + +StateManager* App::get_state_manager() { return state_manager; } + +App::~App() +{ + shutdown_in_progress=true; + + save_settings(); + + synfigapp::Main::settings().remove_domain("pref"); + + selected_instance=0; + + // Unload all of the modules + for(;!module_list_.empty();module_list_.pop_back()); + + delete state_manager; + + delete ipc; + + delete auto_recover; + + toolbox->hide(); + +// studio::App::iteration(false); + + delete toolbox; + +// studio::App::iteration(false); + +// studio::App::iteration(false); + + delete dialog_setup; + + delete dialog_gradient; + + delete dialog_color; + + delete dialog_input; + + delete dock_manager; + + instance_list.clear(); + +// studio::App::iteration(false); +} + +String +App::get_user_app_directory() +{ + return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR); +} + +synfig::String +App::get_config_file(const synfig::String& file) +{ + return Glib::build_filename(get_user_app_directory(),file); +} + +void +App::add_recent_file(const std::string &file_name) +{ + std::string filename(file_name); + + assert(!filename.empty()); + + if(filename.empty()) + return; + + // Toss out any "hidden" files + if(basename(filename)[0]=='.') + return; + + // If we aren't an absolute path, turn outselves into one + if(!is_absolute_path(filename)) + filename=absolute_path(filename); + + list::iterator iter; + // Check to see if the file is already on the list. + // If it is, then remove it from the list + for(iter=recent_files.begin();iter!=recent_files.end();iter++) + if(*iter==filename) + { + recent_files.erase(iter); + break; + } + + + // Push the filename to the front of the list + recent_files.push_front(filename); + + // Clean out the files at the end of the list. + while(recent_files.size()>(unsigned)get_max_recent_files()) + recent_files.pop_back(); + + signal_recent_files_changed_(); + + return; +} + +static Time::Format _App_time_format(Time::FORMAT_NORMAL); + +Time::Format +App::get_time_format() +{ + return _App_time_format; +} + +void +App::set_time_format(synfig::Time::Format x) +{ + _App_time_format=x; +} + + +void +App::save_settings() +{ + try + { + { + std::string filename=get_config_file("accelrc"); + Gtk::AccelMap::save(filename); + } + do{ + std::string filename=get_config_file("recentfiles"); + + std::ofstream file(filename.c_str()); + + if(!file) + { + synfig::warning("Unable to save %s",filename.c_str()); + break; + } + + list::reverse_iterator iter; + + for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++) + file<<*iter<task("Quit Request"); + if(Busy::count) + { + dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again"); + return; + } + + std::list >::iterator iter; + for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin()) + { + if(!(*iter)->safe_close()) + return; + +/* + if((*iter)->synfigapp::Instance::get_action_count()) + { + handle uim; + uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface(); + assert(uim); + string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() ); + switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES)) + { + case synfigapp::UIInterface::RESPONSE_NO: + break; + case synfigapp::UIInterface::RESPONSE_YES: + (*iter)->save(); + break; + case synfigapp::UIInterface::RESPONSE_CANCEL: + return; + default: + assert(0); + return; + } + } + + + if((*iter)->synfigapp::Instance::is_modified()) + { + handle uim; + uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface(); + assert(uim); + 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() ); + switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES)) + { + case synfigapp::UIInterface::RESPONSE_NO: + break; + case synfigapp::UIInterface::RESPONSE_YES: + (*iter)->dialog_cvs_commit(); + break; + case synfigapp::UIInterface::RESPONSE_CANCEL: + return; + default: + assert(0); + return; + } + } +*/ + + // This next line causes things to crash for some reason + //(*iter)->close(); + } + + shutdown_in_progress=true; + + instance_list.clear(); + + while(studio::App::events_pending())studio::App::iteration(false); + + Gtk::Main::quit(); + auto_recover->normal_shutdown(); + + get_ui_interface()->task("Quit Request sent"); +} + +void +App::show_setup() +{ + dialog_setup->refresh(); + dialog_setup->show(); +} + +gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;} +gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;} + +//#ifdef WIN32 +//#define USE_WIN32_FILE_DIALOGS 1 +//#endif + +#ifdef USE_WIN32_FILE_DIALOGS +static OPENFILENAME ofn={}; +#endif + +#ifdef WIN32 +#include +#endif + +bool +App::dialog_open_file(const std::string &title, std::string &filename) +{ +#ifdef USE_WIN32_FILE_DIALOGS + static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ; + + GdkWindow *gdkWinPtr=toolbox->get_window()->gobj(); + HINSTANCE hInstance=static_cast(GetModuleHandle(NULL)); + HWND hWnd=static_cast(GDK_WINDOW_HWND(gdkWinPtr)); + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.hInstance = hInstance; + ofn.lpstrFilter = szFilter; +// ofn.lpstrCustomFilter=NULL; +// ofn.nMaxCustFilter=0; +// ofn.nFilterIndex=0; +// ofn.lpstrFile=NULL; + ofn.nMaxFile=MAX_PATH; +// ofn.lpstrFileTitle=NULL; +// ofn.lpstrInitialDir=NULL; +// ofn.lpstrTitle=NULL; + ofn.Flags=OFN_HIDEREADONLY; +// ofn.nFileOffset=0; +// ofn.nFileExtension=0; + ofn.lpstrDefExt=TEXT("sif"); +// ofn.lCustData = 0l; + ofn.lpfnHook=NULL; +// ofn.lpTemplateName=NULL; + + CHAR szFilename[MAX_PATH]; + CHAR szTitle[500]; + strcpy(szFilename,filename.c_str()); + strcpy(szTitle,title.c_str()); + + ofn.lpstrFile=szFilename; + ofn.lpstrFileTitle=szTitle; + + if(GetOpenFileName(&ofn)) + { + filename=szFilename; + return true; + } + return false; + +#else + synfig::String prev_path; + if(!_preferences.get_value("curr_path",prev_path)) + prev_path="."; + + Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN); + dialog->set_current_folder(prev_path); + dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT); + dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL); + if(!filename.empty()) + dialog->set_filename(filename); + if(dialog->run()==GTK_RESPONSE_ACCEPT) { + filename=dialog->get_filename(); + delete dialog; + return true; + } + delete dialog; + return false; + /* + + GtkWidget *ok; + GtkWidget *cancel; + int val=0; + + GtkWidget *fileselection; + fileselection = gtk_file_selection_new(title.c_str()); + + + if(basename(filename)==filename) + { + gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str()); + } + else + gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str()); + + gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str()); + + ok=GTK_FILE_SELECTION(fileselection)->ok_button; + cancel=GTK_FILE_SELECTION(fileselection)->cancel_button; + + gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val); + gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val); + + gtk_widget_show(fileselection); + + while(!val) + iteration(); + + + if(val==1) + { + filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection)); + _preferences.set_value("curr_path",dirname(filename)); + } + else + { + gtk_widget_destroy(fileselection); + return false; + } + gtk_widget_destroy(fileselection); + return true; + */ +#endif +} + +bool +App::dialog_save_file(const std::string &title, std::string &filename) +{ +#ifdef USE_WIN32_FILE_DIALOGS + static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ; + + GdkWindow *gdkWinPtr=toolbox->get_window()->gobj(); + HINSTANCE hInstance=static_cast(GetModuleHandle(NULL)); + HWND hWnd=static_cast(GDK_WINDOW_HWND(gdkWinPtr)); + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.hInstance = hInstance; + ofn.lpstrFilter = szFilter; +// ofn.lpstrCustomFilter=NULL; +// ofn.nMaxCustFilter=0; +// ofn.nFilterIndex=0; +// ofn.lpstrFile=NULL; + ofn.nMaxFile=MAX_PATH; +// ofn.lpstrFileTitle=NULL; +// ofn.lpstrInitialDir=NULL; +// ofn.lpstrTitle=NULL; + ofn.Flags=OFN_OVERWRITEPROMPT; +// ofn.nFileOffset=0; +// ofn.nFileExtension=0; + ofn.lpstrDefExt=TEXT("sif"); +// ofn.lCustData = 0l; + ofn.lpfnHook=NULL; +// ofn.lpTemplateName=NULL; + + CHAR szFilename[MAX_PATH]; + CHAR szTitle[500]; + strcpy(szFilename,filename.c_str()); + strcpy(szTitle,title.c_str()); + + ofn.lpstrFile=szFilename; + ofn.lpstrFileTitle=szTitle; + + if(GetSaveFileName(&ofn)) + { + filename=szFilename; + return true; + } + return false; +#else + synfig::String prev_path; + if(!_preferences.get_value("curr_path",prev_path)) + prev_path="."; + + Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog->set_current_folder(prev_path); + dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT); + dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL); + if(!filename.empty()) + dialog->set_filename(filename); + if(dialog->run()==GTK_RESPONSE_ACCEPT) { + filename=dialog->get_filename(); + delete dialog; + return true; + } + delete dialog; + return false; +// return dialog_open_file(title, filename); +#endif +} + +bool +App::dialog_saveas_file(const std::string &title, std::string &filename) +{ +#if USE_WIN32_FILE_DIALOGS + static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ; + + GdkWindow *gdkWinPtr=toolbox->get_window()->gobj(); + HINSTANCE hInstance=static_cast(GetModuleHandle(NULL)); + HWND hWnd=static_cast(GDK_WINDOW_HWND(gdkWinPtr)); + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.hInstance = hInstance; + ofn.lpstrFilter = szFilter; +// ofn.lpstrCustomFilter=NULL; +// ofn.nMaxCustFilter=0; +// ofn.nFilterIndex=0; +// ofn.lpstrFile=NULL; + ofn.nMaxFile=MAX_PATH; +// ofn.lpstrFileTitle=NULL; +// ofn.lpstrInitialDir=NULL; +// ofn.lpstrTitle=NULL; + ofn.Flags=OFN_OVERWRITEPROMPT; +// ofn.nFileOffset=0; +// ofn.nFileExtension=0; + ofn.lpstrDefExt=TEXT("sif"); +// ofn.lCustData = 0l; + ofn.lpfnHook=NULL; +// ofn.lpTemplateName=NULL; + + CHAR szFilename[MAX_PATH]; + CHAR szTitle[500]; + strcpy(szFilename,filename.c_str()); + strcpy(szTitle,title.c_str()); + + ofn.lpstrFile=szFilename; + ofn.lpstrFileTitle=szTitle; + + if(GetSaveFileName(&ofn)) + { + filename=szFilename; + return true; + } + return false; +#else + synfig::String prev_path; + if(!_preferences.get_value("curr_path",prev_path)) + prev_path="."; + + Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog->set_current_folder(prev_path); + dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT); + dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL); + if(!filename.empty()) + dialog->set_filename(filename); + if(dialog->run()==GTK_RESPONSE_ACCEPT) { + filename=dialog->get_filename(); + delete dialog; + return true; + } + delete dialog; + return false; +// return dialog_open_file(title, filename); +#endif +} + +void +App::dialog_error_blocking(const std::string &title, const std::string &message) +{ + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-ok"),1); + dialog.show(); + dialog.run(); +} + +void +App::dialog_warning_blocking(const std::string &title, const std::string &message) +{ + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-ok"),1); + dialog.show(); + dialog.run(); +} + +bool +App::dialog_yes_no(const std::string &title, const std::string &message) +{ + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-yes"),1); + dialog.add_button(Gtk::StockID("gtk-no"),0); + dialog.show(); + return dialog.run(); +} + +int +App::dialog_yes_no_cancel(const std::string &title, const std::string &message) +{ + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-yes"),1); + dialog.add_button(Gtk::StockID("gtk-no"),0); + dialog.add_button(Gtk::StockID("gtk-cancel"),2); + dialog.show(); + return dialog.run(); +} + +void +App::dialog_not_implemented() +{ + Gtk::Dialog dialog( + "Feature not available", // Title + true, // Modal + true // use_separator + ); + Gtk::Label label("Sorry, this feature has not yet been implemented."); + label.show(); + + dialog.get_vbox()->pack_start(label); + dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK); + dialog.show(); + dialog.run(); +} + +bool +App::dialog_entry(const std::string &title, const std::string &message,std::string &text) +{ + Gtk::Dialog dialog( + title, // Title + true, // Modal + true // use_separator + ); + Gtk::Label label(message); + label.show(); + dialog.get_vbox()->pack_start(label); + + Gtk::Entry entry; + entry.set_text(text); + entry.show(); + entry.set_activates_default(true); + dialog.get_vbox()->pack_start(entry); + + dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK); + dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL); + dialog.set_default_response(Gtk::RESPONSE_OK); + entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK)); + dialog.show(); + + if(dialog.run()!=Gtk::RESPONSE_OK) + return false; + + text=entry.get_text(); + + return true; +} + + + + +bool +App::open(std::string filename) +{ + return open_as(filename,filename); +} + +bool +App::open_as(std::string filename,std::string as) +{ +#ifdef WIN32 + char long_name[1024]; + if(GetLongPathName(as.c_str(),long_name,sizeof(long_name))); + as=long_name; +#endif + + try + { + OneMoment one_moment; + + etl::handle canvas(open_canvas_as(filename,as)); + if(canvas && get_instance(canvas)) + { + get_instance(canvas)->find_canvas_view(canvas)->present(); + throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str()); + } + if(!canvas) + throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str()); + + add_recent_file(as); + + handle instance(Instance::create(canvas)); + + if(!instance) + throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str()); + + one_moment.hide(); + + 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)"))) + instance->dialog_cvs_update(); + } + catch(String x) + { + dialog_error_blocking(_("Error"), x); + return false; + } + catch(...) + { + dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)")); + return false; + } + + _preferences.set_value("curr_path",dirname(as)); + + return true; +} + + +void +App::new_instance() +{ + handle canvas=synfig::Canvas::create(); + canvas->set_name(strprintf("Untitled%d",Instance::get_count())); + + String file_name(strprintf("untitled%d.sif",Instance::get_count())); + + canvas->rend_desc().set_frame_rate(24.0); + canvas->rend_desc().set_time_start(0.0); + canvas->rend_desc().set_time_end(00.0); + canvas->rend_desc().set_x_res(DPI2DPM(72.0f)); + canvas->rend_desc().set_y_res(DPI2DPM(72.0f)); + canvas->rend_desc().set_tl(Vector(-4,2.25)); + canvas->rend_desc().set_br(Vector(4,-2.25)); + canvas->rend_desc().set_w(480); + canvas->rend_desc().set_h(270); + canvas->rend_desc().set_antialias(1); + canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN); + canvas->set_file_name(file_name); + + Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present(); +} + +void +App::dialog_open() +{ + string filename="*.sif"; + + while(dialog_open_file("Open", filename)) + { + // If the filename still has wildcards, then we should + // continue looking for the file we want + if(find(filename.begin(),filename.end(),'*')!=filename.end()) + continue; + + if(open(filename)) + break; + + get_ui_interface()->error(_("Unable to open file")); + } +} + +void +App::set_selected_instance(etl::loose_handle instance) +{ +/* if(get_selected_instance()==instance) + { + selected_instance=instance; + signal_instance_selected()(instance); + return; + } + else + { +*/ + selected_instance=instance; + if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance) + { + if(instance) + { + instance->focus(instance->get_canvas()); + } + else + set_selected_canvas_view(0); + } + signal_instance_selected()(instance); +} + +void +App::set_selected_canvas_view(etl::loose_handle canvas_view) +{ + selected_canvas_view=canvas_view; + signal_canvas_view_focus()(selected_canvas_view); + if(canvas_view) + { + selected_instance=canvas_view->get_instance(); + signal_instance_selected()(canvas_view->get_instance()); + } +/* + if(get_selected_canvas_view()==canvas_view) + { + signal_canvas_view_focus()(selected_canvas_view); + signal_instance_selected()(canvas_view->get_instance()); + return; + } + selected_canvas_view=canvas_view; + if(canvas_view && canvas_view->get_instance() != get_selected_instance()) + set_selected_instance(canvas_view->get_instance()); + signal_canvas_view_focus()(selected_canvas_view); +*/ +} + +etl::loose_handle +App::get_instance(Canvas::Handle canvas) +{ + if(!canvas) return 0; + canvas=canvas->get_root(); + + std::list >::iterator iter; + for(iter=instance_list.begin();iter!=instance_list.end();++iter) + { + if((*iter)->get_canvas()==canvas) + return *iter; + } + return 0; +} + +void +App::dialog_about() +{ + (new class About())->show(); +} + +void +studio::App::undo() +{ + if(selected_instance) + selected_instance->undo(); +} + +void +studio::App::redo() +{ + if(selected_instance) + selected_instance->redo(); +} + +synfig::String +studio::App::get_base_path() +{ + return app_base_path_; +}