From: Nikita Kitaev Date: Mon, 31 May 2010 04:18:19 +0000 (-0700) Subject: Merge branch 'master' into nikitakit_restructure X-Git-Url: https://git.pterodactylus.net/?p=synfig.git;a=commitdiff_plain;h=db91521de71f46f2debb4b3ef1edfe351aea3b2d Merge branch 'master' into nikitakit_restructure --- db91521de71f46f2debb4b3ef1edfe351aea3b2d diff --cc synfig-studio/src/gui/app.cpp index c1a8ba3,0000000..b50b120 mode 100644,000000..100644 --- a/synfig-studio/src/gui/app.cpp +++ b/synfig-studio/src/gui/app.cpp @@@ -1,2514 -1,0 +1,2585 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file app.cpp +** \brief writeme +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2008 Gerald Young +** Copyright (c) 2008 Carlos López +** Copyright (c) 2009 Nikita Kitaev +** +** 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 + +#ifdef WIN32 +#define WINVER 0x0500 +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_SYS_ERRNO_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include "app.h" +#include "dialogs/about.h" +#include "splash.h" +#include "instance.h" +#include "canvasview.h" +#include "dialogs/dialog_setup.h" +#include "dialogs/dialog_gradient.h" +#include "dialogs/dialog_color.h" +#include "toolbox.h" +#include "onemoment.h" + +#include "docks/dockmanager.h" + +#include "states/state_eyedrop.h" +#include "states/state_normal.h" +#include "states/state_mirror.h" +#include "states/state_draw.h" +#include "states/state_fill.h" +#include "states/state_bline.h" +#include "states/state_polygon.h" +#include "states/state_sketch.h" +#include "states/state_gradient.h" +#include "states/state_circle.h" +#include "states/state_rectangle.h" +#include "states/state_smoothmove.h" +#include "states/state_scale.h" +#include "states/state_star.h" +#include "states/state_text.h" +#include "states/state_width.h" +#include "states/state_rotate.h" +#include "states/state_zoom.h" + +#include "devicetracker.h" +#include "docks/dialog_tooloptions.h" +#include "widgets/widget_enum.h" + +#include "autorecover.h" + +#include +#include "docks/dock_history.h" +#include "docks/dock_canvases.h" +#include "docks/dock_keyframes.h" +#include "docks/dock_layers.h" +#include "docks/dock_params.h" +#include "docks/dock_metadata.h" +#include "docks/dock_children.h" +#include "docks/dock_info.h" +#include "docks/dock_navigator.h" +#include "docks/dock_layergroups.h" +#include "docks/dock_timetrack.h" +#include "docks/dock_curves.h" + +#include "modules/module.h" +#include "modules/mod_palette/mod_palette.h" + +#include + +#include "ipc.h" + +#include "statemanager.h" + +#ifdef WITH_FMOD +#include +#endif + +#include +#include +#include + +#include "general.h" + +#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" +#elif defined(_WIN32) +#define SYNFIG_USER_APP_DIR "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; } + +static std::list recent_files_window_size; + +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::About *studio::App::about=NULL; + +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; +#ifdef SINGLE_THREADED +bool studio::App::single_threaded=false; +#endif +bool studio::App::restrict_radius_ducks=false; +bool studio::App::resize_imported_images=false; +String studio::App::custom_filename_prefix(DEFAULT_FILENAME_PREFIX); +int studio::App::preferred_x_size=480; +int studio::App::preferred_y_size=270; +String studio::App::predefined_size(DEFAULT_PREDEFINED_SIZE); +String studio::App::predefined_fps(DEFAULT_PREDEFINED_FPS); +float studio::App::preferred_fps=24.0; +#ifdef USE_OPEN_FOR_URLS +String studio::App::browser_command("open"); // MacOS only +#else +String studio::App::browser_command("xdg-open"); // Linux XDG standard +#endif + +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 { + +bool +really_delete_widget(Gtk::Widget *widget) +{ + // synfig::info("really delete %p", (void*)widget); + delete widget; + return false; +} + +// nasty workaround - when we've finished with a popup menu, we want to delete it +// attaching to the signal_hide() signal gets us here before the action on the menu has run, +// so schedule the real delete to happen in 50ms, giving the action a chance to run +void +delete_widget(Gtk::Widget *widget) +{ + // synfig::info("delete %p", (void*)widget); + Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50); +} + +}; // END of namespace studio +studio::StateManager* state_manager; + + + + +class GlobalUIInterface : public synfigapp::UIInterface +{ +public: + + virtual Response confirmation(const std::string &title, + const std::string &primaryText, + const std::string &secondaryText, + const std::string &confirmPhrase, + const std::string &cancelPhrase, + Response defaultResponse) + { + Gtk::MessageDialog dialog( + primaryText, // Message + false, // Markup + Gtk::MESSAGE_WARNING, // Type + Gtk::BUTTONS_NONE, // Buttons + true // Modal + ); + + if (! title.empty()) + dialog.set_title(title); + if (! secondaryText.empty()) + dialog.set_secondary_text(secondaryText); + + dialog.add_button(cancelPhrase, RESPONSE_CANCEL); + dialog.add_button(confirmPhrase, RESPONSE_OK); + dialog.set_default_response(defaultResponse); + + dialog.show_all(); + return (Response) dialog.run(); + } + + 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<& 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; + std::list > prev_groups(ui_manager->get_action_groups()); + std::list >::reverse_iterator iter; + + for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter) + { + if(*iter && (*iter)->get_name()!="menus") + { + synfig::info("Removing action group "+(*iter)->get_name()); + ui_manager->remove_action_group(*iter); + } + } + ui_manager->insert_action_group(group,0); + + 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); + } +} +*/ +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; + } +#ifdef SINGLE_THREADED + if(key=="single_threaded") + { + value=strprintf("%i",(int)App::single_threaded); + return true; + } +#endif + if(key=="auto_recover_backup_interval") + { + value=strprintf("%i",App::auto_recover->get_timeout()); + return true; + } + if(key=="restrict_radius_ducks") + { + value=strprintf("%i",(int)App::restrict_radius_ducks); + return true; + } + if(key=="resize_imported_images") + { + value=strprintf("%i",(int)App::resize_imported_images); + return true; + } + if(key=="browser_command") + { + value=App::browser_command; + return true; + } + if(key=="custom_filename_prefix") + { + value=App::custom_filename_prefix; + return true; + } + if(key=="preferred_x_size") + { + value=strprintf("%i",App::preferred_x_size); + return true; + } + if(key=="preferred_y_size") + { + value=strprintf("%i",App::preferred_y_size); + return true; + } + if(key=="predefined_size") + { + value=strprintf("%s",App::predefined_size.c_str()); + return true; + } + if(key=="preferred_fps") + { + value=strprintf("%f",App::preferred_fps); + return true; + } + if(key=="predefined_fps") + { + value=strprintf("%s",App::predefined_fps.c_str()); + 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; + } +#ifdef SINGLE_THREADED + if(key=="single_threaded") + { + int i(atoi(value.c_str())); + App::single_threaded=i; + return true; + } +#endif + if(key=="restrict_radius_ducks") + { + int i(atoi(value.c_str())); + App::restrict_radius_ducks=i; + return true; + } + if(key=="resize_imported_images") + { + int i(atoi(value.c_str())); + App::resize_imported_images=i; + return true; + } + if(key=="browser_command") + { + App::browser_command=value; + return true; + } + if(key=="custom_filename_prefix") + { + App::custom_filename_prefix=value; + return true; + } + if(key=="preferred_x_size") + { + int i(atoi(value.c_str())); + App::preferred_x_size=i; + return true; + } + if(key=="preferred_y_size") + { + int i(atoi(value.c_str())); + App::preferred_y_size=i; + return true; + } + if(key=="predefined_size") + { + App::predefined_size=value; + return true; + } + if(key=="preferred_fps") + { + float i(atof(value.c_str())); + App::preferred_fps=i; + return true; + } + if(key=="predefined_fps") + { + App::predefined_fps=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"); +#ifdef SINGLE_THREADED + ret.push_back("single_threaded"); +#endif + ret.push_back("auto_recover_backup_interval"); + ret.push_back("restrict_radius_ducks"); + ret.push_back("resize_imported_images"); + ret.push_back("browser_command"); + ret.push_back("custom_filename_prefix"); + ret.push_back("preferred_x_size"); + ret.push_back("preferred_y_size"); + ret.push_back("predefined_size"); + ret.push_back("preferred_fps"); + ret.push_back("predefined_fps"); + 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("actions"); + + 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", _("Show/Hide Ducks")) ); + menus_action_group->add( Gtk::Action::create("menu-preview-quality", _("Preview Quality")) ); + menus_action_group->add( Gtk::Action::create("menu-lowres-pixel", _("Low-Res Pixel Size")) ); + 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", _("Tool")) ); + 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) ); actions_action_group->add(action); } +#define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr action( Gtk::Action::create(x, stock,label,label) ); actions_action_group->add(action); } +#define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr action( Gtk::Action::create(x, stock) ); group->add(action,sig); } + + DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties")); + DEFINE_ACTION("about", Gtk::StockID("synfig-about")); + DEFINE_ACTION("new", Gtk::Stock::NEW); + 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 View")); + DEFINE_ACTION("close-document", _("Close Document")); + DEFINE_ACTION("quit", Gtk::Stock::QUIT); + + + 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-ducks", _("Unselect All Ducks")); + DEFINE_ACTION("select-all-layers", _("Select All Layers")); + DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers")); + DEFINE_ACTION("properties", _("Properties")); + + DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks")); + DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks")); + DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks")); + DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks")); + DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks")); + DEFINE_ACTION("mask-angle-ducks", _("Show 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")); + for(list::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++) + DEFINE_ACTION(strprintf("lowres-pixel-%d", *iter), strprintf(_("Set Low-Res pixel size to %d"), *iter)); + 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("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size")); + DEFINE_ACTION("increase-low-res-pixel-size", _("Increase Low-Res Pixel Size")); + 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 +#undef DEFINE_ACTION_2 +#undef DEFINE_ACTION_SIG + + Glib::ustring ui_info = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +; + + for(list::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++) + ui_info += strprintf(" ", *iter); + + 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(accel,path) \ + { \ + 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()); \ + } + + // the toolbox + ACCEL("a", "/action_group_state_manager/state-normal" ); + ACCEL("v", "/action_group_state_manager/state-smooth_move" ); + ACCEL("s", "/action_group_state_manager/state-scale" ); + ACCEL("t", "/action_group_state_manager/state-rotate" ); + ACCEL("m", "/action_group_state_manager/state-mirror" ); + ACCEL("c", "/action_group_state_manager/state-circle" ); + ACCEL("r", "/action_group_state_manager/state-rectangle" ); + ACCEL("q", "/action_group_state_manager/state-star" ); + ACCEL("g", "/action_group_state_manager/state-gradient" ); + ACCEL("p", "/action_group_state_manager/state-polygon" ); + ACCEL("b", "/action_group_state_manager/state-bline" ); + ACCEL("x", "/action_group_state_manager/state-text" ); + ACCEL("f", "/action_group_state_manager/state-fill" ); + ACCEL("e", "/action_group_state_manager/state-eyedrop" ); + ACCEL("z", "/action_group_state_manager/state-zoom" ); + ACCEL("d", "/action_group_state_manager/state-draw" ); + ACCEL("k", "/action_group_state_manager/state-sketch" ); + ACCEL("w", "/action_group_state_manager/state-width" ); + + // everything else + ACCEL("a", "/canvasview/select-all-ducks" ); + ACCEL("d", "/canvasview/unselect-all-ducks" ); + ACCEL("a", "/canvasview/select-all-layers" ); + ACCEL("d", "/canvasview/unselect-all-layers" ); + ACCEL("F9", "/canvasview/render" ); + ACCEL("F11", "/canvasview/preview" ); + ACCEL("F8", "/canvasview/properties" ); + ACCEL("F12", "/canvasview/options" ); + ACCEL("i", "/canvasview/import" ); + ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast(0), "/canvasview/stop" )); + ACCEL("g", "/canvasview/toggle-grid-show" ); + ACCEL("l", "/canvasview/toggle-grid-snap" ); + ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK, "/canvasview/toggle-low-res" )); + ACCEL("1", "/canvasview/mask-position-ducks" ); + ACCEL("2", "/canvasview/mask-vertex-ducks" ); + ACCEL("3", "/canvasview/mask-tangent-ducks" ); + ACCEL("4", "/canvasview/mask-radius-ducks" ); + ACCEL("5", "/canvasview/mask-width-ducks" ); + ACCEL("6", "/canvasview/mask-angle-ducks" ); + ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK, "/action_group_layer_action_manager/action-LayerRaise" )); + ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK, "/action_group_layer_action_manager/action-LayerLower" )); + ACCEL("1", "/canvasview/quality-01" ); + ACCEL("2", "/canvasview/quality-02" ); + ACCEL("3", "/canvasview/quality-03" ); + ACCEL("4", "/canvasview/quality-04" ); + ACCEL("5", "/canvasview/quality-05" ); + ACCEL("6", "/canvasview/quality-06" ); + ACCEL("7", "/canvasview/quality-07" ); + ACCEL("8", "/canvasview/quality-08" ); + ACCEL("9", "/canvasview/quality-09" ); + ACCEL("0", "/canvasview/quality-10" ); + ACCEL("z", "/action_group_dock_history/undo" ); + ACCEL("r", "/action_group_dock_history/redo" ); + ACCEL2(Gtk::AccelKey(GDK_Delete,Gdk::CONTROL_MASK, "/action_group_layer_action_manager/action-LayerRemove" )); + ACCEL2(Gtk::AccelKey('(',Gdk::CONTROL_MASK, "/canvasview/decrease-low-res-pixel-size" )); + ACCEL2(Gtk::AccelKey(')',Gdk::CONTROL_MASK, "/canvasview/increase-low-res-pixel-size" )); + ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK, "/action_group_layer_action_manager/amount-dec" )); + ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK, "/action_group_layer_action_manager/amount-inc" )); + ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK, "/canvasview/jump-next-keyframe" )); + ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK, "/canvasview/jump-prev-keyframe" )); + ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK, "/canvasview/canvas-zoom-in" )); + ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK, "/canvasview/canvas-zoom-out" )); + ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK, "/canvasview/time-zoom-in" )); + ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK, "/canvasview/time-zoom-out" )); + ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK, "/canvasview/seek-next-frame" )); + ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK, "/canvasview/seek-prev-frame" )); + ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK, "/canvasview/seek-next-second" )); + ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK, "/canvasview/seek-prev-second" )); + ACCEL("o", "/canvasview/toggle-onion-skin" ); + ACCEL("z", "/canvasview/canvas-zoom-fit" ); + ACCEL("p", "/canvasview/play" ); + ACCEL("Home", "/canvasview/seek-begin" ); + ACCEL("End", "/canvasview/seek-end" ); + +#undef ACCEL +#undef ACCEL2 +} + +#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), + IconController(etl::dirname((*argv)[0])) +{ + app_base_path_=etl::dirname(etl::dirname((*argv)[0])); + + + ui_interface_=new GlobalUIInterface(); + + gdk_rgb_init(); + + // don't call thread_init() if threads are already initialized + // on some machines bonobo_init() initialized threads before we get here + if (!g_thread_supported()) + 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(); + + if(!SYNFIG_CHECK_VERSION()) + { + cerr<<"FATAL: Synfig Version Mismatch"<(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); } + catch(std::runtime_error x) + { + get_ui_interface()->error(strprintf("%s\n\n%s", _("Failed to initialize synfig!"), x.what())); + throw; + } + 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 About Dialog...")); + about=new studio::About(); + + 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...")); + + /* editing 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_mirror); - if(!getenv("SYNFIG_DISABLE_WIDTH" )) state_manager->add_state(&state_width); // Enabled since 0.61.09 + - /* new objects */ ++ /* geometry */ + state_manager->add_state(&state_circle); + state_manager->add_state(&state_rectangle); + state_manager->add_state(&state_star); + state_manager->add_state(&state_gradient); + if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon); // Enabled - for working without ducks - state_manager->add_state(&state_text); ++ ++ /* bline tools */ + state_manager->add_state(&state_bline); + if(!getenv("SYNFIG_DISABLE_DRAW" )) state_manager->add_state(&state_draw); // Enabled for now. Let's see whether they're good enough yet. - - /* other */ ++ if(!getenv("SYNFIG_DISABLE_WIDTH" )) state_manager->add_state(&state_width); // Enabled since 0.61.09 + state_manager->add_state(&state_fill); + state_manager->add_state(&state_eyedrop); - state_manager->add_state(&state_zoom); ++ ++ /* other */ ++ state_manager->add_state(&state_text); + if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch); ++ 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 Setup Dialog...")); + dialog_setup=new studio::Dialog_Setup(); + + studio_init_cb.task(_("Init Input Dialog...")); + dialog_input=new Gtk::InputDialog(); + dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) ); + dialog_input->get_save_button()->signal_clicked().connect( sigc::mem_fun( *device_tracker, &DeviceTracker::save_preferences) ); + + 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(); + device_tracker->load_preferences(); + + studio_init_cb.task(_("Checking auto-recover...")); + + studio_init_cb.amount_complete(9900,10000); + + bool opened_any = false; + if(auto_recover->recovery_needed()) + { + splash_screen.hide(); + if (get_ui_interface()->confirmation("Crash Recovery", + _("Auto recovery file found"), + _("Synfig Studio seems to have crashed\n" + "before you could save all your files.\n" + "Recover unsaved changes?"), + _("Recover"), _("Ignore")) + == synfigapp::UIInterface::RESPONSE_OK) + { + int number_recovered; + if(!auto_recover->recover(number_recovered)) + if (number_recovered) + get_ui_interface()->error(_("Unable to fully recover from previous crash")); + else + get_ui_interface()->error(_("Unable to 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.")); + + if (number_recovered) + opened_any = true; + } + splash_screen.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...")); + splash_screen.hide(); + open((*argv)[*argc]); + opened_any = true; + splash_screen.show(); + } + + // if no file was specified to be opened, create a new document to help new users get started more easily + if (!opened_any && !getenv("SYNFIG_DISABLE_AUTOMATIC_DOCUMENT_CREATION")) + new_instance(); + + studio_init_cb.task(_("Done.")); + studio_init_cb.amount_complete(10000,10000); + ++ // To avoid problems with some window managers and gtk >= 2.18 ++ // we should show dock dialogs after the settings load. ++ // If dock dialogs are shown before the settings are loaded, ++ // the windows manager can act over it. ++ // See discussions here: ++ // * http://synfig.org/forums/viewtopic.php?f=1&t=1131&st=0&sk=t&sd=a&start=30 ++ // * http://synfig.org/forums/viewtopic.php?f=15&t=1062 ++ dock_manager->show_all_dock_dialogs(); ++ + toolbox->present(); + } + catch(String x) + { + get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable.") + String("\n\n") + x); + } + 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; + + delete about; + + toolbox->hide(); + + delete toolbox; + + delete dialog_setup; + + delete dialog_gradient; + + delete dialog_color; + + delete dialog_input; + + delete dock_manager; + + instance_list.clear(); +} + +String +App::get_user_app_directory() +{ +//! \todo do we need locale_from_utf8() on non-Windows boxes too? (bug #1837445) +#ifdef WIN32 + return Glib::locale_from_utf8(Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR)); +#else + return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR); +#endif +} + +synfig::String +App::get_config_file(const synfig::String& file) +{ + return Glib::build_filename(get_user_app_directory(),file); +} + - #define SCALE_FACTOR (1280) +//! set the \a instance's canvas(es) position and size to be those specified in the first entry of recent_files_window_size +void +App::set_recent_file_window_size(etl::handle instance) +{ - int screen_w(Gdk::screen_width()); - int screen_h(Gdk::screen_height()); + + const std::string &canvas_window_size = *recent_files_window_size.begin(); + + if(canvas_window_size.empty()) + return; + + synfig::String::size_type current=0; + bool seen_root(false), shown_non_root(false); + + while(current != synfig::String::npos) + { + // find end of first field (canvas) or return + synfig::String::size_type separator = canvas_window_size.find_first_of(' ', current); + if(separator == synfig::String::npos) break; + + // find the canvas + synfig::Canvas::Handle canvas; + try { + String warnings; + canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current), warnings); + } + catch(Exception::IDNotFound) { + // can't find the canvas; skip to the next canvas or return + separator = canvas_window_size.find_first_of('\t', current); + if(separator == synfig::String::npos) return; + current = separator+1; + continue; + } + + if (canvas->is_root()) + seen_root = true; + else + shown_non_root = true; + + // check that we have the tab character the ends this canvas' data or return + current = separator+1; + separator = canvas_window_size.find_first_of('\t', current); + if(separator == synfig::String::npos) return; + + int x,y,w,h; + if(!strscanf(String(canvas_window_size, current, separator-current),"%d %d %d %d",&x, &y, &w, &h)) + { + current = separator+1; + continue; + } - - if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0; - if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0; - x=x*screen_w/SCALE_FACTOR; - y=y*screen_h/SCALE_FACTOR; - if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET")) - x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET")); - if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET")) - y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET")); - - if (w > SCALE_FACTOR) w = 150; if (w < 0) w = 0; - if (h > SCALE_FACTOR) h = 150; if (h < 0) h = 0; - + CanvasView::Handle canvasview = instance->find_canvas_view(canvas); + canvasview->move(x,y); - canvasview->resize(w*screen_w/SCALE_FACTOR,h*screen_h/SCALE_FACTOR); ++ canvasview->resize(w,h); + canvasview->present(); + + current = separator+1; + } + + if (shown_non_root && !seen_root) + instance->find_canvas_view(instance->get_canvas())->hide(); +} + +void +App::add_recent_file(const etl::handle instance) +{ - int screen_w(Gdk::screen_width()); - int screen_h(Gdk::screen_height()); + + std::string canvas_window_size; + + const Instance::CanvasViewList& cview_list = instance->canvas_view_list(); + Instance::CanvasViewList::const_iterator iter; + + for(iter=cview_list.begin();iter!=cview_list.end();iter++) + { + if( !((*iter)->is_visible()) ) + continue; + + etl::handle canvas = (*iter)->get_canvas(); + int x_pos, y_pos, x_size, y_size; + (*iter)->get_position(x_pos,y_pos); + (*iter)->get_size(x_size,y_size); + + canvas_window_size += strprintf("%s %d %d %d %d\t", + canvas->get_relative_id(canvas->get_root()).c_str(), - x_pos*SCALE_FACTOR/screen_w, y_pos*SCALE_FACTOR/screen_h, - x_size*SCALE_FACTOR/screen_w, y_size*SCALE_FACTOR/screen_h); ++ x_pos, y_pos, ++ x_size, y_size); + } + + add_recent_file(absolute_path(instance->get_file_name()), canvas_window_size); +} - #undef SCALE_FACTOR + +void +App::add_recent_file(const std::string &file_name, const std::string &window_size) +{ + 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 ourselves into one + if(!is_absolute_path(filename)) + filename=absolute_path(filename); + + std::string old_window_size; + + list::iterator iter; + list::iterator iter_wsize; + // 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_wsize=recent_files_window_size.begin();iter!=recent_files.end();iter++, iter_wsize++) + if(*iter==filename) + { + recent_files.erase(iter); + old_window_size = *iter_wsize; + recent_files_window_size.erase(iter_wsize); + break; + } + + + // Push the filename to the front of the list + recent_files.push_front(filename); + if(window_size.empty()) + recent_files_window_size.push_front(old_window_size); + else + recent_files_window_size.push_front(window_size); + + // Clean out the files at the end of the list. + while(recent_files.size()>(unsigned)get_max_recent_files()) + { + recent_files.pop_back(); + recent_files_window_size.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() +{ + char * old_locale; + try + { + old_locale=strdup(setlocale(LC_NUMERIC, NULL)); + setlocale(LC_NUMERIC, "C"); + { + 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<::reverse_iterator iter; + + for(iter=recent_files_window_size.rbegin();iter!=recent_files_window_size.rend();iter++) + file<<*iter< display(Gdk::Display::get_default()); ++ Glib::RefPtr screen(display->get_default_screen()); ++ Gdk::Rectangle rect; ++ // A proper way to obtain the primary monitor is to use the ++ // Gdk::Screen::get_primary_monitor () const member. But as it ++ // was introduced in gtkmm 2.20 I assume that the monitor 0 is the ++ // primary one. ++ screen->get_monitor_geometry(0,rect); ++#define hpanel_width 79.0f ++#define hpanel_height 25.0f ++#define vpanel_width 20.0f ++#define vpanel_height 100.0f ++#define vdock 20.0f ++#define hdock 20.0f ++ ++/* percentages referred to width or height of the screen ++ *---------------------------------------------------------------------* ++ * t | | ++ * o | | ++ * o | |vdock% ++ * l | | ++ * b | |------------ ++ * o | | ++ * x | |vdock% ++ * -------- | ++ * | ++ * |------------ ++ * | ++ * |vdock% ++ * | ++ * | ++ *-----hdock%----------------------------------------------|------------ ++ * | | ++ * | |vdock% ++ * | | ++ * | | ++ * --------------------------------------------------------------------* ++*/ ++// Vertical Panel ++ int v_xpos=rect.get_x() + rect.get_width()*(1.0-vpanel_width/100.0); ++ int v_xsize=rect.get_width()*vpanel_width/100.0; ++ int v_ypos=rect.get_y(); ++ int v_ysize=rect.get_height()*vpanel_height/100.0; ++ std::string v_pos(strprintf("%d %d", v_xpos, v_ypos)); ++ std::string v_size(strprintf("%d %d", v_xsize, v_ysize)); ++// Horizontal Panel ++ int h_xpos=rect.get_x(); ++ int h_xsize=rect.get_width()*hpanel_width/100.0; ++ int h_ypos=rect.get_y()+ rect.get_height()*(1.0-hpanel_height/100.0);; ++ int h_ysize=rect.get_height()*hpanel_height/100.0; ++ std::string h_pos(strprintf("%d %d", h_xpos, h_ypos)); ++ std::string h_size(strprintf("%d %d", h_xsize, h_ysize)); ++ int v_dock1 = rect.get_height()*vdock*0.8/100.0; ++ int v_dock2 = rect.get_height()*vdock*0.6/100.0; ++ int v_dock3 = rect.get_height()*vdock*1.1/100.0; ++ int h_dock = rect.get_width()*hdock/100.0; ++//Contents size ++ std::string v_contents(strprintf("%d %d %d", v_dock1, v_dock2, v_dock3)); ++ std::string h_contents(strprintf("%d", h_dock)); ++// Tool Box position ++ std::string tbox_pos(strprintf("%d %d", rect.get_x(), rect.get_y())); ++/* ++ synfig::info("tool box pos: %s", tbox_pos.c_str()); ++ synfig::info("v_contents sizes: %s", v_contents.c_str()); ++ synfig::info("v_pos: %s", v_pos.c_str()); ++ synfig::info("v_sizes: %s", v_size.c_str()); ++ synfig::info("h_contents sizes: %s", h_contents.c_str()); ++ synfig::info("h_pos: %s", h_pos.c_str()); ++ synfig::info("h_sizes: %s", h_size.c_str()); ++*/ + synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1"); + synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups"); - synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207"); - synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32"); - synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174"); ++ synfigapp::Main::settings().set_value("dock.dialog.1.contents_size",v_contents); ++ synfigapp::Main::settings().set_value("dock.dialog.1.size",v_size); ++ synfigapp::Main::settings().set_value("dock.dialog.1.pos",v_pos); + synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0"); + synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data"); - synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263"); - synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973"); - synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235"); ++ synfigapp::Main::settings().set_value("dock.dialog.2.contents_size",h_contents); ++ synfigapp::Main::settings().set_value("dock.dialog.2.size",h_size); ++ synfigapp::Main::settings().set_value("dock.dialog.2.pos",h_pos); ++ synfigapp::Main::settings().set_value("window.toolbox.pos",tbox_pos); ++ ++ dock_manager->show_all_dock_dialogs(); ++} ++ ++void ++App::reset_initial_preferences() ++{ + synfigapp::Main::settings().set_value("pref.distance_system","pt"); + synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1"); +#ifdef SINGLE_THREADED + synfigapp::Main::settings().set_value("pref.single_threaded","1"); +#endif + synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0"); + synfigapp::Main::settings().set_value("pref.resize_imported_images","0"); + synfigapp::Main::settings().set_value("pref.custom_filename_prefix",DEFAULT_FILENAME_PREFIX); + synfigapp::Main::settings().set_value("pref.preferred_x_size","480"); + synfigapp::Main::settings().set_value("pref.preferred_y_size","270"); + synfigapp::Main::settings().set_value("pref.predefined_size",DEFAULT_PREDEFINED_SIZE); + synfigapp::Main::settings().set_value("pref.preferred_fps","24.0"); + synfigapp::Main::settings().set_value("pref.predefined_fps",DEFAULT_PREDEFINED_FPS); - synfigapp::Main::settings().set_value("window.toolbox.pos","4 4"); ++ +} + +bool +App::shutdown_request(GdkEventAny*) +{ + quit(); + return true; + //return !shutdown_in_progress; +} + +void +App::quit() +{ + if(shutdown_in_progress)return; + + + get_ui_interface()->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, std::string preference) +{ + // info("App::dialog_open_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str()); + +#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 // not USE_WIN32_FILE_DIALOGS + synfig::String prev_path; + + if(!_preferences.get_value(preference, prev_path)) + prev_path = "."; + + prev_path = absolute_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::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT); + + if (filename.empty()) + dialog->set_filename(prev_path); + else if (is_absolute_path(filename)) + dialog->set_filename(filename); + else + dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename); + + if(dialog->run() == GTK_RESPONSE_ACCEPT) { + filename = dialog->get_filename(); + // info("Saving preference %s = '%s' in App::dialog_open_file()", preference.c_str(), dirname(filename).c_str()); + _preferences.set_value(preference, dirname(filename)); + delete dialog; + return true; + } + + delete dialog; + return false; +#endif // not USE_WIN32_FILE_DIALOGS +} + +bool +App::dialog_save_file(const std::string &title, std::string &filename, std::string preference) +{ + // info("App::dialog_save_file('%s', '%s', '%s')", title.c_str(), filename.c_str(), preference.c_str()); + +#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; + _preferences.set_value(preference,dirname(filename)); + return true; + } + return false; +#else + synfig::String prev_path; + + if(!_preferences.get_value(preference, prev_path)) + prev_path="."; + + prev_path = absolute_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::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); + + Widget_Enum *file_type_enum = 0; + if (preference == ANIMATION_DIR_PREFERENCE) + { + file_type_enum = manage(new Widget_Enum()); + file_type_enum->set_param_desc(ParamDesc().set_hint("enum") - .add_enum_value(synfig::RELEASE_VERSION_0_62_00, "0.62.00", strprintf("0.62.00 (%s)", _("current"))) ++ .add_enum_value(synfig::RELEASE_VERSION_0_62_01, "0.62.01", strprintf("0.62.01 (%s)", _("current"))) ++ .add_enum_value(synfig::RELEASE_VERSION_0_62_00, "0.62.00", "0.61.00") + .add_enum_value(synfig::RELEASE_VERSION_0_61_09, "0.61.09", "0.61.09") + .add_enum_value(synfig::RELEASE_VERSION_0_61_08, "0.61.08", "0.61.08") + .add_enum_value(synfig::RELEASE_VERSION_0_61_07, "0.61.07", "0.61.07") + .add_enum_value(synfig::RELEASE_VERSION_0_61_06, "0.61.06", strprintf("0.61.06 %s", _("and older")))); + file_type_enum->set_value(RELEASE_VERSION_END-1); // default to the most recent version + + Gtk::HBox *hbox = manage(new Gtk::HBox); + hbox->pack_start(*manage(new Gtk::Label(_("File Format Version: "))),Gtk::PACK_SHRINK,0); + hbox->pack_start(*file_type_enum,Gtk::PACK_EXPAND_WIDGET,0); + hbox->show_all(); + + dialog->set_extra_widget(*hbox); + } + + if (filename.empty()) + dialog->set_filename(prev_path); + else + { + std::string full_path; + if (is_absolute_path(filename)) + full_path = filename; + else + full_path = prev_path + ETL_DIRECTORY_SEPARATOR + filename; + + // select the file if it exists + dialog->set_filename(full_path); + + // if the file doesn't exist, put its name into the filename box + struct stat s; + if(stat(full_path.c_str(),&s) == -1 && errno == ENOENT) + dialog->set_current_name(basename(filename)); + } + + if(dialog->run() == GTK_RESPONSE_ACCEPT) { + if (preference == ANIMATION_DIR_PREFERENCE) + set_file_version(synfig::ReleaseVersion(file_type_enum->get_value())); + filename = dialog->get_filename(); + // info("Saving preference %s = '%s' in App::dialog_save_file()", preference.c_str(), dirname(filename).c_str()); + _preferences.set_value(preference, dirname(filename)); + delete dialog; + return true; + } + + delete dialog; + return false; +#endif +} + +void +App::dialog_error_blocking(const std::string &title, const std::string &message) +{ + Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true); + dialog.set_title(title); + dialog.show(); + dialog.run(); +} + +void +App::dialog_warning_blocking(const std::string &title, const std::string &message) +{ + Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true); + dialog.set_title(title); + 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::MessageDialog dialog(_("Feature not available"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true); + dialog.set_secondary_text(_("Sorry, this feature has not yet been implemented.")); + dialog.run(); +} + +static bool +try_open_url(const std::string &url) +{ +#ifdef WIN32 + return ShellExecute(GetDesktopWindow(), "open", url.c_str(), NULL, NULL, SW_SHOW); +#else // !WIN32 + std::vector command_line; + std::vector browsers; + browsers.reserve(23); + + // Browser wrapper scripts +#ifdef USE_OPEN_FOR_URLS + browsers.push_back("open"); // Apple MacOS X wrapper, on Linux it opens a virtual console +#endif + browsers.push_back("xdg-open"); // XDG wrapper + browsers.push_back("sensible-browser"); // Debian wrapper + browsers.push_back("gnome-open"); // GNOME wrapper + browsers.push_back("kfmclient"); // KDE wrapper + browsers.push_back("exo-open"); // XFCE wrapper + + // Alternatives system + browsers.push_back("gnome-www-browser"); // Debian GNOME alternative + browsers.push_back("x-www-browser"); // Debian GUI alternative + + // Individual browsers + browsers.push_back("firefox"); + browsers.push_back("epiphany-browser"); + browsers.push_back("epiphany"); + browsers.push_back("konqueror"); + browsers.push_back("iceweasel"); + browsers.push_back("mozilla"); + browsers.push_back("netscape"); + browsers.push_back("icecat"); + browsers.push_back("galeon"); + browsers.push_back("midori"); + browsers.push_back("safari"); + browsers.push_back("opera"); + browsers.push_back("amaya"); + browsers.push_back("netsurf"); + browsers.push_back("dillo"); + + // Try the user-specified browser first + command_line.push_back(App::browser_command); + if( command_line[0] == "kfmclient" ) command_line.push_back("openURL"); + command_line.push_back(url); + + try { Glib::spawn_async(".", command_line, Glib::SPAWN_SEARCH_PATH); return true; } + catch( Glib::SpawnError& exception ){ + + while ( !browsers.empty() ) + { + // Skip the browser if we already tried it + if( browsers[0] == App::browser_command ) + continue; + + // Construct the command line + command_line.clear(); + command_line.push_back(browsers[0]); + if( command_line[0] == "kfmclient" ) command_line.push_back("openURL"); + command_line.push_back(url); + + // Remove the browser from the list + browsers.erase(browsers.begin()); + + // Try to spawn the browser + try { Glib::spawn_async(".", command_line, Glib::SPAWN_SEARCH_PATH); } + // Failed, move on to the next one + catch(Glib::SpawnError& exception){ continue; } + return true; // No exception means we succeeded! + } + } + + return false; +#endif // !WIN32 +} + +void +App::dialog_help() +{ + if (!try_open_url("http://synfig.org/wiki/Category:Manual")) + { + Gtk::MessageDialog dialog(_("Documentation"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_CLOSE, true); + dialog.set_secondary_text(_("Documentation for Synfig Studio is available on the website:\n\nhttp://synfig.org/wiki/Category:Manual")); + dialog.set_title(_("Help")); + dialog.run(); + } +} + +void +App::open_url(const std::string &url) +{ + if(!try_open_url(url)) + { + Gtk::MessageDialog dialog(_("No browser was found. Please load this website manually:"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true); + dialog.set_secondary_text(url); + dialog.set_title(_("No browser found")); + 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::dialog_paragraph(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); + + Glib::RefPtr text_buffer(Gtk::TextBuffer::create()); + text_buffer->set_text(text); + Gtk::TextView text_view(text_buffer); + text_view.show(); + + dialog.get_vbox()->pack_start(text_view); + + 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); + + //text_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=text_buffer->get_text(); + + return true; +} + +bool +App::open(std::string filename) +{ + return open_as(filename,filename); +} + +// this is called from autorecover.cpp: +// App::open_as(get_shadow_file_name(filename),filename) +// other than that, 'filename' and 'as' are the same +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))); + // when called from autorecover.cpp, filename doesn't exist, and so long_name is empty + // don't use it if that's the case + if (long_name[0] != '\0') + as=long_name; +#endif + + try + { + OneMoment one_moment; + String errors, warnings; + + etl::handle canvas(open_canvas_as(filename,as,errors,warnings)); + if(canvas && get_instance(canvas)) + { + get_instance(canvas)->find_canvas_view(canvas)->present(); + info("%s is already open", filename.c_str()); + // throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str()); + } + else + { + if(!canvas) + throw (String)strprintf(_("Unable to load \"%s\":\n\n"),filename.c_str()) + errors; + + if (warnings != "") + dialog_warning_blocking(_("Warnings"), strprintf("%s:\n\n%s", _("Warnings"), warnings.c_str())); + + if (as.find(custom_filename_prefix.c_str()) != 0) + add_recent_file(as); + + handle instance(Instance::create(canvas)); + + if(!instance) + throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str()); + + set_recent_file_window_size(instance); + + 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(runtime_error x) + { + dialog_error_blocking(_("Error"), x.what()); + return false; + } + catch(...) + { + dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)")); + return false; + } + + return true; +} + + +void +App::new_instance() +{ + handle canvas=synfig::Canvas::create(); + + String file_name(strprintf("%s%d", App::custom_filename_prefix.c_str(), Instance::get_count()+1)); + canvas->set_name(file_name); + file_name += ".sifz"; + + canvas->rend_desc().set_frame_rate(preferred_fps); + canvas->rend_desc().set_time_start(0.0); + canvas->rend_desc().set_time_end(5.0); + canvas->rend_desc().set_x_res(DPI2DPM(72.0f)); + canvas->rend_desc().set_y_res(DPI2DPM(72.0f)); + // The top left and botton right positions are expressed in units + // Original convention is that 1 unit = 60 pixels + canvas->rend_desc().set_tl(Vector(-(preferred_x_size/60.0)/2.0,(preferred_y_size/60.0)/2.0)); + canvas->rend_desc().set_br(Vector((preferred_x_size/60.0)/2.0,-(preferred_y_size/60.0)/2.0)); + canvas->rend_desc().set_w(preferred_x_size); + canvas->rend_desc().set_h(preferred_y_size); + canvas->rend_desc().set_antialias(1); + canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN); + canvas->set_file_name(file_name); + + handle instance = Instance::create(canvas); + + if (getenv("SYNFIG_ENABLE_NEW_CANVAS_EDIT_PROPERTIES")) + instance->find_canvas_view(canvas)->canvas_properties.present(); +} + +void +App::dialog_open(string filename) +{ + if (filename.empty()) + filename="*.sif"; + + while(dialog_open_file("Open", filename, ANIMATION_DIR_PREFERENCE)) + { + // 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(etl::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() +{ + if(about) + 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_; +} diff --cc synfig-studio/src/gui/app.h index f9960d3,0000000..06b60d3 mode 100644,000000..100644 --- a/synfig-studio/src/gui/app.h +++ b/synfig-studio/src/gui/app.h @@@ -1,363 -1,0 +1,364 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file app.h +** \brief writeme +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2008 Carlos López +** +** 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 +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_APP_H +#define __SYNFIG_STUDIO_APP_H + +/* === H E A D E R S ======================================================= */ + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include "iconcontroller.h" + +/* === M A C R O S ========================================================= */ + +#define MISC_DIR_PREFERENCE "misc_dir" +#define ANIMATION_DIR_PREFERENCE "animation_dir" +#define IMAGE_DIR_PREFERENCE "image_dir" +#define SKETCH_DIR_PREFERENCE "sketch_dir" +#define RENDER_DIR_PREFERENCE "render_dir" + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace Gtk +{ + class InputDialog; + class UIManager; + class ActionGroup; +}; + +namespace synfigapp +{ + class UIInterface; + class Main; +}; + +class Preferences; + +namespace studio { + +typedef Gtk::UIManager UIManager; + +class About; +class Toolbox; +class Instance; +class CanvasView; +class Dialog_Setup; +class Dialog_Gradient; +class Dialog_Color; +class Dialog_ToolOptions; +class DeviceTracker; +class AutoRecover; + +class DockManager; + +class Dock_History; +class Dock_Canvases; + +class Dock_Keyframes; +class Dock_Params; +class Dock_Layers; +class Dock_MetaData; +class Dock_Children; +class Dock_Info; +class Dock_Navigator; +class Dock_LayerGroups; +class IPC; + +class Module; + +class StateManager; +class IconController; + +class App : public Gtk::Main, private IconController +{ + friend class Preferences; + friend class Dialog_Setup; + + /* + -- ** -- P U B L I C T Y P E S --------------------------------------------- + */ + +public: + + struct Busy + { + static int count; + Busy(){count++;} + ~Busy(){count--;} + }; + + + /* + -- ** -- P R I V A T E D A T A --------------------------------------------- + */ + +private: + //static etl::handle ui_interface_; + //static int max_recent_files; + +/* //declated as globals in app.cpp + static Dock_Keyframes *dock_keyframes; + static Dock_Layers *dock_layers; + static Dock_Params *dock_params; + static Dock_MetaData *dock_meta_data; + static Dock_Children *dock_children; + static Dock_Info *dock_info; + static Dock_Navigator *dock_navigator; + static Dock_History *dock_history; + static Dock_Canvases *dock_canvases; + static Dock_LayerGroups *dock_layer_groups; + + static IPC *ipc; +*/ + + etl::smart_ptr synfigapp_main; + + + static etl::handle selected_instance; + static etl::handle selected_canvas_view; + + static Glib::RefPtr ui_manager_; + +// static std::list< etl::handle< Module > > module_list_; + + /* + -- ** -- P U B L I C D A T A ----------------------------------------------- + */ + +public: + static Gtk::InputDialog* dialog_input; + + static DeviceTracker* device_tracker; + static AutoRecover* auto_recover; + static DockManager* dock_manager; + + static DockManager* get_dock_manager() { return dock_manager; } + + static Dialog_Setup* dialog_setup; + static Dialog_Gradient* dialog_gradient; + static Dialog_Color* dialog_color; +// static Dialog_Palette* dialog_palette; + static Dialog_ToolOptions *dialog_tool_options; + + static synfig::Distance::System distance_system; + + static synfig::Gamma gamma; + + static About *about; + static Toolbox *toolbox; + + static std::list > instance_list; + + static bool shutdown_in_progress; + + static bool use_colorspace_gamma; + +#ifdef SINGLE_THREADED + static bool single_threaded; +#endif + + static bool restrict_radius_ducks; + static bool resize_imported_images; + + static synfig::String browser_command; + static synfig::String custom_filename_prefix; + static int preferred_x_size; + static int preferred_y_size; + static synfig::String predefined_size; + static synfig::String predefined_fps; + static float preferred_fps; + /* + -- ** -- S I G N A L S ------------------------------------------------------- + */ +/* //declated as globals in app.cpp + static sigc::signal< + void, + etl::loose_handle + > signal_canvas_view_focus_; + static sigc::signal< + void, + etl::handle + > signal_instance_selected_; + static sigc::signal< + void, + etl::handle + > signal_instance_created_; + static sigc::signal< + void, + etl::handle + > signal_instance_deleted_; + static sigc::signal signal_recent_files_changed_; + static sigc::signal signal_present_all_; +*/ +public: + + static sigc::signal &signal_present_all(); + + static sigc::signal &signal_recent_files_changed(); + + static sigc::signal< + void, + etl::loose_handle + >& signal_canvas_view_focus(); + + static sigc::signal< + void, + etl::handle + > &signal_instance_selected(); + + static sigc::signal< + void, + etl::handle + > &signal_instance_created(); + + static sigc::signal< + void, + etl::handle + > &signal_instance_deleted(); + + /* + -- ** -- P R I V A T E M E T H O D S --------------------------------------- + */ + +private: + static void add_recent_file(const std::string &filename, const std::string &window_size = std::string()); + + /* + -- ** -- P U B L I C M E T H O D S ----------------------------------------- + */ + +public: + + App(int *argc, char ***argv); + virtual ~App(); + + /* + -- ** -- S T A T I C P U B L I C M E T H O D S --------------------------- + */ + +public: + + static StateManager* get_state_manager(); + + static Glib::RefPtr& ui_manager() { return ui_manager_; } + + static void set_recent_file_window_size(etl::handle instance); + static void add_recent_file(const etl::handle instance); + + static synfig::String get_base_path(); + static void save_settings(); + static void load_settings(); + static void reset_initial_window_configuration(); ++ static void reset_initial_preferences(); + + static const std::list& get_recent_files(); + + static const etl::handle& get_ui_interface(); + + + static void set_selected_instance(etl::loose_handle instance); + static void set_selected_canvas_view(etl::loose_handle); + + static etl::loose_handle get_instance(etl::handle canvas); + + static etl::loose_handle get_selected_instance() { return selected_instance; } + static etl::loose_handle get_selected_canvas_view() { return selected_canvas_view; } + + static bool open(std::string filename); + + static bool open_as(std::string filename,std::string as); + + static void new_instance(); + + static void dialog_open(std::string filename = ""); + + static void dialog_about(); + + static void quit(); + + static void show_setup(); + + static void undo(); + static void redo(); + + static int get_max_recent_files(); + static void set_max_recent_files(int x); + + + static synfig::Time::Format get_time_format(); + static void set_time_format(synfig::Time::Format x); + + static bool shutdown_request(GdkEventAny*bleh=NULL); + +// static bool dialog_file(const std::string &title, std::string &filename); + + static bool dialog_open_file(const std::string &title, std::string &filename, std::string preference); + static bool dialog_save_file(const std::string &title, std::string &filename, std::string preference); + + static void dialog_error_blocking(const std::string &title, const std::string &message); + + static void dialog_warning_blocking(const std::string &title, const std::string &message); + + static bool dialog_entry(const std::string &title, const std::string &message,std::string &text); + static bool dialog_paragraph(const std::string &title, const std::string &message,std::string &text); + + static bool dialog_yes_no(const std::string &title, const std::string &message); + + static int dialog_yes_no_cancel(const std::string &title, const std::string &message); + + static void dialog_not_implemented(); + + static void dialog_help(); + + static void open_url(const std::string &url); + + static synfig::String get_user_app_directory(); + static synfig::String get_config_file(const synfig::String& file); +}; // END of class App + + void delete_widget(Gtk::Widget *widget); + +}; // END namespace studio + +/* === E N D =============================================================== */ + +#endif diff --cc synfig-studio/src/gui/asyncrenderer.cpp index 72a286c,0000000..4ec1537 mode 100644,000000..100644 --- a/synfig-studio/src/gui/asyncrenderer.cpp +++ b/synfig-studio/src/gui/asyncrenderer.cpp @@@ -1,541 -1,0 +1,541 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file asyncrenderer.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 Chris Moore +** +** 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 "asyncrenderer.h" +#include "app.h" +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef HAVE_SIGNAL_H +#include +#endif + +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +#define BOREDOM_TIMEOUT 50 + +#define REJOIN_ON_STOP 1 + +// The Glib::Dispatcher class is broken as of Glibmm 2.4.5. +// Defining this macro enables the workaround. +#define GLIB_DISPATCHER_BROKEN 1 + +/* === C L A S S E S ======================================================= */ + +class AsyncTarget_Tile : public synfig::Target_Tile +{ +public: + etl::handle warm_target; + + struct tile_t + { + Surface surface; + int x,y; + tile_t(const Surface& surface,int x, int y): + surface(surface), + x(x),y(y) + { + } + }; + std::list tile_queue; + Glib::Mutex mutex; + +#ifndef GLIB_DISPATCHER_BROKEN + Glib::Dispatcher tile_ready_signal; +#endif + Glib::Cond cond_tile_queue_empty; + bool alive_flag; + + sigc::connection ready_connection; + +public: + AsyncTarget_Tile(etl::handle warm_target): + warm_target(warm_target) + { + set_avoid_time_sync(warm_target->get_avoid_time_sync()); + set_tile_w(warm_target->get_tile_w()); + set_tile_h(warm_target->get_tile_h()); + set_canvas(warm_target->get_canvas()); + set_quality(warm_target->get_quality()); + set_remove_alpha(warm_target->get_remove_alpha()); + set_threads(warm_target->get_threads()); + set_clipping(warm_target->get_clipping()); + set_rend_desc(&warm_target->rend_desc()); + alive_flag=true; +#ifndef GLIB_DISPATCHER_BROKEN + ready_connection=tile_ready_signal.connect(sigc::mem_fun(*this,&AsyncTarget_Tile::tile_ready)); +#endif + } + + ~AsyncTarget_Tile() + { + ready_connection.disconnect(); + } + void set_dead() + { + Glib::Mutex::Lock lock(mutex); + alive_flag=false; + } + + virtual int total_tiles()const + { + return warm_target->total_tiles(); + } + + virtual int next_tile(int& x, int& y) + { + if(!alive_flag) + return 0; + + return warm_target->next_tile(x,y); + } + + virtual int next_frame(Time& time) + { + if(!alive_flag) + return 0; + return warm_target->next_frame(time); + } + + virtual bool start_frame(synfig::ProgressCallback *cb=0) + { + if(!alive_flag) + return false; + return warm_target->start_frame(cb); + } + + virtual bool add_tile(const synfig::Surface &surface, int gx, int gy) + { + assert(surface); + if(!alive_flag) + return false; + Glib::Mutex::Lock lock(mutex); + tile_queue.push_back(tile_t(surface,gx,gy)); + if(tile_queue.size()==1) + { +#ifdef GLIB_DISPATCHER_BROKEN + ready_connection=Glib::signal_timeout().connect( + sigc::bind_return( + sigc::mem_fun(*this,&AsyncTarget_Tile::tile_ready), + false + ) + ,0 + ); +#else + tile_ready_signal(); +#endif + } + + return alive_flag; + } + + void tile_ready() + { + Glib::Mutex::Lock lock(mutex); + if(!alive_flag) + { + tile_queue.clear(); + cond_tile_queue_empty.signal(); + return; + } + while(!tile_queue.empty() && alive_flag) + { + tile_t& tile(tile_queue.front()); + + if (getenv("SYNFIG_SHOW_TILE_OUTLINES")) + { + Color red(1,0,0); + tile.surface.fill(red, 0, 0, 1, tile.surface.get_h()); + tile.surface.fill(red, 0, 0, tile.surface.get_w(), 1); + } + + alive_flag=warm_target->add_tile(tile.surface,tile.x,tile.y); + + tile_queue.pop_front(); + } + cond_tile_queue_empty.signal(); + } + + virtual void end_frame() + { +#ifdef SINGLE_THREADED + if (!single_threaded()) + { +#endif + while(alive_flag) + { + Glib::Mutex::Lock lock(mutex); + if(!tile_queue.empty() && alive_flag) + { + if(cond_tile_queue_empty.timed_wait(mutex,Glib::TimeVal(0,BOREDOM_TIMEOUT))) + break; + } + else + break; + } +#ifdef SINGLE_THREADED + } +#endif + Glib::Mutex::Lock lock(mutex); + if(!alive_flag) + return; + return warm_target->end_frame(); + } +}; + + + +class AsyncTarget_Scanline : public synfig::Target_Scanline +{ +public: + etl::handle warm_target; + + int scanline_; + Surface surface; + + Glib::Mutex mutex; + +#ifndef GLIB_DISPATCHER_BROKEN + Glib::Dispatcher frame_ready_signal; +#endif + Glib::Cond cond_frame_queue_empty; + bool alive_flag; + bool ready_next; + sigc::connection ready_connection; + + +public: + AsyncTarget_Scanline(etl::handle warm_target): + warm_target(warm_target) + { + set_avoid_time_sync(warm_target->get_avoid_time_sync()); + set_canvas(warm_target->get_canvas()); + set_quality(warm_target->get_quality()); + set_remove_alpha(warm_target->get_remove_alpha()); + set_threads(warm_target->get_threads()); + set_rend_desc(&warm_target->rend_desc()); + alive_flag=true; +#ifndef GLIB_DISPATCHER_BROKEN + ready_connection=frame_ready_signal.connect(sigc::mem_fun(*this,&AsyncTarget_Scanline::frame_ready)); +#endif + surface.set_wh(warm_target->rend_desc().get_w(),warm_target->rend_desc().get_h()); + } + + ~AsyncTarget_Scanline() + { + ready_connection.disconnect(); + } + + virtual int next_frame(Time& time) + { + if(!alive_flag) + return 0; + return warm_target->next_frame(time); + + } + + void set_dead() + { + Glib::Mutex::Lock lock(mutex); + alive_flag=false; + } + + virtual bool start_frame(synfig::ProgressCallback */*cb*/=0) + { + return alive_flag; + } + + virtual void end_frame() + { + { + Glib::Mutex::Lock lock(mutex); + + if(!alive_flag) + return; + ready_next=false; + +#ifdef GLIB_DISPATCHER_BROKEN + ready_connection=Glib::signal_timeout().connect( + sigc::bind_return( + sigc::mem_fun(*this,&AsyncTarget_Scanline::frame_ready), + false + ) + ,0 + ); +#else + frame_ready_signal(); +#endif + } + +#ifdef SINGLE_THREADED + if (single_threaded()) + signal_progress()(); + else +#endif + while(alive_flag && !ready_next) + { + Glib::Mutex::Lock lock(mutex); + if(cond_frame_queue_empty.timed_wait(mutex,Glib::TimeVal(0,BOREDOM_TIMEOUT))) + break; + } + } + + + virtual Color * start_scanline(int scanline) + { + Glib::Mutex::Lock lock(mutex); + + return surface[scanline]; + } + + virtual bool end_scanline() + { + return alive_flag; + } + + void frame_ready() + { + Glib::Mutex::Lock lock(mutex); + if(alive_flag) + alive_flag=warm_target->add_frame(&surface); +#ifdef SINGLE_THREADED + if (!single_threaded()) +#endif + cond_frame_queue_empty.signal(); + ready_next=true; + } +}; + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +AsyncRenderer::AsyncRenderer(etl::handle target_,synfig::ProgressCallback *cb): + error(false), + success(false), + cb(cb) +#ifdef SINGLE_THREADED + , updating(false) +#endif +{ + render_thread=0; + if(etl::handle::cast_dynamic(target_)) + { + etl::handle wrap_target( + new AsyncTarget_Tile(etl::handle::cast_dynamic(target_)) + ); + + signal_stop_.connect(sigc::mem_fun(*wrap_target,&AsyncTarget_Tile::set_dead)); + + target=wrap_target; + } + else if(etl::handle::cast_dynamic(target_)) + { + etl::handle wrap_target( + new AsyncTarget_Scanline( + etl::handle::cast_dynamic(target_) + ) + ); + + signal_stop_.connect(sigc::mem_fun(*wrap_target,&AsyncTarget_Scanline::set_dead)); + + target=wrap_target; + } +} + +AsyncRenderer::~AsyncRenderer() +{ + stop(); +} + +void +AsyncRenderer::stop() +{ + if(target) + { + Glib::Mutex::Lock lock(mutex); + done_connection.disconnect(); + + if(render_thread) + { + signal_stop_(); + +#if REJOIN_ON_STOP +#ifdef SINGLE_THREADED + if (!single_threaded()) +#endif + render_thread->join(); +#endif + + // Make sure all the dispatch crap is cleared out + //Glib::MainContext::get_default()->iteration(false); + + if(success) + signal_success_(); + + signal_finished_(); + + target=0; + render_thread=0; + } + } +} + +void +AsyncRenderer::pause() +{ +} + +void +AsyncRenderer::resume() +{ +} + +void +AsyncRenderer::start() +{ + done_connection=Glib::signal_timeout().connect( + sigc::bind_return( + mem_fun(*this,&AsyncRenderer::start_), + false + ) + ,50 + ); +} + +#ifdef SINGLE_THREADED +void +AsyncRenderer::rendering_progress() +{ + updating = true; + while(studio::App::events_pending()) studio::App::iteration(false); + updating = false; +} +#endif + +void +AsyncRenderer::start_() +{ + error=false;success=false; + if(target) + { +#ifndef GLIB_DISPATCHER_BROKEN + done_connection=signal_done_.connect(mem_fun(*this,&AsyncRenderer::stop)); +#endif + +#ifdef SINGLE_THREADED + if (single_threaded()) + { - synfig::info("%s:%d rendering in the same thread", __FILE__, __LINE__); ++ //synfig::info("%s:%d rendering in the same thread", __FILE__, __LINE__); + target->signal_progress().connect(sigc::mem_fun(this,&AsyncRenderer::rendering_progress)); + render_thread = (Glib::Thread*)1; + render_target(); + } + else +#endif + { + render_thread=Glib::Thread::create( + sigc::mem_fun(*this,&AsyncRenderer::render_target), +#if REJOIN_ON_STOP + true +#else + false +#endif + ); + assert(render_thread); + } + } + else + { + stop(); + } +} + +void +AsyncRenderer::render_target() +{ + etl::handle target(AsyncRenderer::target); + + if(target && target->render()) + { + success=true; + } + else + { + error=true; +#ifndef REJOIN_ON_STOP + return; +#endif + } + + if(mutex.trylock()) + { +#ifdef GLIB_DISPATCHER_BROKEN + done_connection=Glib::signal_timeout().connect( + sigc::bind_return( + mem_fun(*this,&AsyncRenderer::stop), + false + ) + ,0 + ); +#else + signal_done_.emit(); +#endif + mutex.unlock(); + } +} diff --cc synfig-studio/src/gui/dialogs/about.cpp index dc005ff,0000000..ef8404d mode 100644,000000..100644 --- a/synfig-studio/src/gui/dialogs/about.cpp +++ b/synfig-studio/src/gui/dialogs/about.cpp @@@ -1,248 -1,0 +1,254 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file about.cpp +** \brief About dialog implementation +** +** $Id$ +** +** \legal +** Copyright (c) 2008 Paul Wise +** +** 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 + +#include + +#include + +#include + +// This is generated at make time from .svn or .git/svn or autorevision.conf +#include + +#include "about.h" +#include "app.h" + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +#ifndef VERSION +#define VERSION "unknown" +#define PACKAGE "synfigstudio" +#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 "png" +#endif + +#define stringify_(x) #x +#define stringify(x) stringify_(x) + +/* === G L O B A L S ======================================================= */ + +extern const guint gtk_major_version; +extern const guint gtk_minor_version; +extern const guint gtk_micro_version; +extern const guint gtk_binary_age; +extern const guint gtk_interface_age; + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +About::About() +{ + +#ifdef HAVE_GTK_ABOUTDIALOG_SET_PROGRAM_NAME + set_program_name(PACKAGE_NAME); +#else + set_name(PACKAGE_NAME); +#endif + set_version(VERSION); + set_comments(_("2D vector animation studio")); + + set_url_hook(sigc::mem_fun(*this, &About::on_link_clicked)); + set_website("http://synfig.org/"); + set_website_label(_("Visit the Synfig website")); + - set_copyright(_("Copyright 2001-2008\nRobert B. Quattlebaum Jr.,\nAdrian Bentley and Synfig contributors")); ++ set_copyright(_("Copyright 2001-2010\nRobert B. Quattlebaum Jr.,\nAdrian Bentley and Synfig contributors")); + Glib::ustring license = + "This program 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.\n\n" + + "This program 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.\n\n" + + "You should have received a copy of the GNU General Public License along " + "with this program; if not, write to the Free Software Foundation, Inc., " + "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or visit: http://www.gnu.org/"; + set_license(license); +#ifdef HAVE_GTK_ABOUTDIALOG_SET_WRAP_LICENSE + set_wrap_license(true); +#endif + + std::vector authors; + authors.push_back(_("Original developers:")); + authors.push_back(""); + authors.push_back("Robert B. Quattlebaum Jr (darco)"); + authors.push_back("Adrian Bentley"); + authors.push_back(""); + authors.push_back(_("Contributors:")); + authors.push_back(""); + authors.push_back("Adrian Winchell (SnapSilverlight)"); + authors.push_back("Andreas Jochens"); ++ authors.push_back("Brendon Higgins"); + authors.push_back("Carlos López González (genete)"); + authors.push_back("Carlos A. Sosa Navarro"); + authors.push_back("Chris Moore (dooglus)"); + authors.push_back("Chris Norman (pixelgeek)"); + authors.push_back("Cyril Brulebois (KiBi)"); + authors.push_back("Daniel Fort"); + authors.push_back("Daniel Hornung (rubikcube)"); + authors.push_back("David Roden (Bombe)"); + authors.push_back("Dmitriy Pomerantsev (Atrus)"); + authors.push_back("Douglas Lau"); + authors.push_back("Gerald Young (Yoyobuae)"); + authors.push_back("Gerco Ballintijn"); + authors.push_back("IL'dar AKHmetgaleev (AkhIL)"); + authors.push_back("Konstantin Dmitriev (zelgadis)"); + authors.push_back("Luka Pravica"); ++ authors.push_back("Nikita Kitaev (nikitakit)"); + authors.push_back("Martin Michlmayr (tbm)"); + authors.push_back("Miguel Gea Milvaques (xerakko)"); + authors.push_back("Paul Wise (pabs)"); + authors.push_back("Ralf Corsepius"); + authors.push_back("Ray Frederikson"); + authors.push_back("Timo Paulssen (timonator)"); + authors.push_back("Yue Shi Lai"); + set_authors(authors); + + std::vector artists; + artists.push_back("Aurore D (rore)"); ++ artists.push_back("Bertrand Grégoire (berteh)"); + artists.push_back("Carlos López González (genete)"); + artists.push_back("Chris Norman (pixelgeek)"); + artists.push_back("Daniel Hornung (rubikcube)"); + artists.push_back("David Rylander (rylleman)"); + artists.push_back("Franco Iacomella (Yaco)"); + artists.push_back("Gerald Young (Yoyobuae)"); + artists.push_back("Henrique Lopes Barone"); ++ artists.push_back("Konstantin Dmitriev (zelgadis)"); ++ artists.push_back("Madeleine Crubellier (mad0)"); + artists.push_back("Robert B. Quattlebaum Jr. (darco)"); ++ artists.push_back("Thimotee Guiet (satrip)"); + + set_artists(artists); + + // TRANSLATORS: change this to your name, separate multiple names with \n + set_translator_credits(_("translator-credits")); + + std::string imagepath; +#ifdef WIN32 + imagepath=App::get_base_path()+ETL_DIRECTORY_SEPARATOR+IMAGE_DIR; +#else + imagepath=IMAGE_DIR; +#endif + char* synfig_root=getenv("SYNFIG_ROOT"); + if(synfig_root) { + imagepath=synfig_root; + imagepath+=ETL_DIRECTORY_SEPARATOR; + imagepath+="share"; + imagepath+=ETL_DIRECTORY_SEPARATOR; + imagepath+="pixmaps"; + } + imagepath+=ETL_DIRECTORY_SEPARATOR; + + Gtk::Image *Logo = manage(new class Gtk::Image()); + Logo->set(imagepath+"synfig_icon."IMAGE_EXT); + set_logo(Logo->get_pixbuf()); + +#ifdef SHOW_EXTRA_INFO + + string extra_info = get_comments() + "\n"; + + #ifdef DEVEL_VERSION + extra_info += strprintf(_("\nDevelopment version:\n%s\n"),DEVEL_VERSION); + #endif + + extra_info += "\n"; + + extra_info += strprintf(_("Built on %s" /* at %s */ "\n"), __DATE__ /* , __TIME__ */ ); + + extra_info += "\n"; + + extra_info += strprintf(_("Built with:\n"), ETL_VERSION); + extra_info += strprintf(_("ETL %s\n"), ETL_VERSION); + extra_info += strprintf(_("Synfig API %s\n"), stringify(SYNFIG_VERSION)); + extra_info += strprintf(_("Synfig library %d\n"), SYNFIG_LIBRARY_VERSION); + extra_info += strprintf(_("GTK+ %d.%d.%d\n"), GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); + #ifdef __GNUC__ + extra_info += strprintf(_("GNU G++ %d.%d.%d\n"),__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__); + #endif + + extra_info += "\n"; + + extra_info += strprintf(_("Using:\n"), synfig::get_version()); + extra_info += strprintf(_("Synfig %s\n"), synfig::get_version()); + extra_info += strprintf(_("GTK+ %d.%d.%d"),gtk_major_version,gtk_minor_version,gtk_micro_version); + + #ifdef _DEBUG + extra_info += "\n\nDEBUG BUILD"; + #endif + + set_comments(extra_info); + +#endif + + // Hide the dialog when you click close + signal_response().connect(sigc::mem_fun(*this, &About::close)); +} + +void About::close(int){ + hide(); +} + +void About::on_link_clicked(Gtk::AboutDialog&, const Glib::ustring &url) +{ + App::open_url(url); +} diff --cc synfig-studio/src/gui/dialogs/dialog_targetparam.cpp index 03bb696,0000000..7c8250e mode 100644,000000..100644 --- a/synfig-studio/src/gui/dialogs/dialog_targetparam.cpp +++ b/synfig-studio/src/gui/dialogs/dialog_targetparam.cpp @@@ -1,150 -1,0 +1,182 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file dialog_targetparam.cpp +** \brief Implementation for the TargetParam Dialog +** +** $Id$ +** +** \legal +** Copyright (c) 2010 Carlos López González +** +** 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 "dialogs/dialog_targetparam.h" + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace studio; + +/* === M A C R O S ========================================================= */ + ++#define CUSTOM_VCODEC_DESCRIPTION _("Custom Video Codec") ++#define CUSTOM_VCODEC _("write your video codec here") ++ +/* === G L O B A L S ======================================================= */ +//! Allowed video codecs +/*! \warning This variable is linked to allowed_video_codecs_description, + * if you change this you must change the other acordingly. + * \warning These codecs are linked to the filename extensions for + * mod_ffmpeg. If you change this you must change the others acordingly. + */ +const char* allowed_video_codecs[] = +{ - "flv", "h263p", "huffyuv", "libtheora", "libx264", "libxvid", ++ "flv", "h263p", "huffyuv", "libtheora", "libx264", + "mjpeg", "mpeg1video", "mpeg2video", "mpeg4", "msmpeg4", - "msmpeg4v1", "msmpeg4v2", "wmv1", "wmv2", NULL ++ "msmpeg4v1", "msmpeg4v2", "wmv1", "wmv2", CUSTOM_VCODEC, NULL +}; + +//! Allowed video codecs description. +/*! \warning This variable is linked to allowed_video_codecs, + * if you change this you must change the other acordingly. + */ +const char* allowed_video_codecs_description[] = +{ + _("Flash Video (FLV) / Sorenson Spark / Sorenson H.263."), + _("H.263+ / H.263-1998 / H.263 version 2."), + _("Huffyuv / HuffYUV."), + _("libtheora Theora."), + _("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10."), - _("libxvidcore MPEG-4 part 2."), + _("MJPEG (Motion JPEG)."), + _("raw MPEG-1 video."), + _("raw MPEG-2 video."), - _("MPEG-4 part 2."), ++ _("MPEG-4 part 2. (XviD/DivX)"), + _("MPEG-4 part 2 Microsoft variant version 3."), + _("MPEG-4 part 2 Microsoft variant version 1."), + _("MPEG-4 part 2 Microsoft variant version 2."), + _("Windows Media Video 7."), + _("Windows Media Video 8."), ++ CUSTOM_VCODEC_DESCRIPTION, + NULL +}; +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +/* === E N T R Y P O I N T ================================================= */ + - Dialog_TargetParam::Dialog_TargetParam(synfig::TargetParam &tparam) ++Dialog_TargetParam::Dialog_TargetParam(Gtk::Window &parent, synfig::TargetParam &tparam): ++ Gtk::Dialog(_("Target Parameters"), parent, false, true) +{ - set_title(_("TargetParam Dialog")); + set_tparam(tparam); ++ // Custom Video Codec Entry ++ Gtk::Label* custom_label(manage(new Gtk::Label(std::string(CUSTOM_VCODEC_DESCRIPTION)+":"))); ++ custom_label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); ++ customvcodec=Gtk::manage(new Gtk::Entry()); + // Available Video Codecs Combo Box Text. - vcodec = Gtk::manage(new Gtk::ComboBoxText()); + Gtk::Label* label(manage(new Gtk::Label(_("Available Video Codecs:")))); + label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); - get_vbox()->pack_start(*label, true, true, 0); ++ vcodec = Gtk::manage(new Gtk::ComboBoxText()); ++ // Appends the codec descriptions to the Combo Box + for (int i = 0; allowed_video_codecs[i] != NULL && + allowed_video_codecs_description[i] != NULL; i++) + vcodec->append_text(allowed_video_codecs_description[i]); ++ //Adds the Combo Box and the Custom Video Codec entry to the vertical box ++ get_vbox()->pack_start(*label, true, true, 0); ++ get_vbox()->pack_start(*vcodec, true, true, 0); ++ get_vbox()->pack_start(*custom_label, true, true, 0); ++ get_vbox()->pack_start(*customvcodec, true, true, 0); ++ ++ // Connect the signal change to the handler ++ vcodec->signal_changed().connect(sigc::mem_fun(*this, &Dialog_TargetParam::on_vcodec_change)); ++ // By defaut, set the active text to the Custom Video Codec ++ vcodec->set_active_text(CUSTOM_VCODEC_DESCRIPTION); ++ customvcodec->set_text(CUSTOM_VCODEC); ++ //Compare the passed vcodec to the available and set it active if found + for (int i = 0; allowed_video_codecs[i] != NULL && + allowed_video_codecs_description[i] != NULL; i++) + if(!get_tparam().video_codec.compare(allowed_video_codecs[i])) ++ { + vcodec->set_active_text(allowed_video_codecs_description[i]); - - get_vbox()->pack_start(*vcodec, true, true, 0); ++ customvcodec->set_text(allowed_video_codecs[i]); ++ } + + //Bitrate Spin Button + Gtk::Adjustment* bradj(manage(new class Gtk::Adjustment(double(tparam.bitrate), 10.0,1000.0))); + bitrate = Gtk::manage(new class Gtk::SpinButton(*bradj)); + Gtk::Label* label2(manage(new Gtk::Label(_("Video Bit Rate:")))); + label2->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); + get_vbox()->pack_start(*label2, true, true, 0); + get_vbox()->pack_start(*bitrate,true, true, 0); + + get_vbox()->show_all(); + + ok_button = manage(new class Gtk::Button(Gtk::StockID("gtk-ok"))); + ok_button->show(); + add_action_widget(*ok_button,Gtk::RESPONSE_OK); + ok_button->signal_clicked().connect(sigc::mem_fun(*this,&Dialog_TargetParam::on_ok)); + + cancel_button = manage(new class Gtk::Button(Gtk::StockID("gtk-cancel"))); + cancel_button->show(); + add_action_widget(*cancel_button,Gtk::RESPONSE_CANCEL); + cancel_button->signal_clicked().connect(sigc::mem_fun(*this,&Dialog_TargetParam::on_cancel)); + +} + +void +Dialog_TargetParam::on_ok() +{ - std::string codecnamed = vcodec->get_active_text(); - for (int i = 0; allowed_video_codecs[i] != NULL && - allowed_video_codecs_description[i] != NULL; i++) - if(!codecnamed.compare(allowed_video_codecs_description[i])) - tparam_.video_codec=allowed_video_codecs[i]; ++ tparam_.video_codec=customvcodec->get_text().c_str(); + tparam_.bitrate=bitrate->get_value(); + hide(); +} + +void +Dialog_TargetParam::on_cancel() +{ + hide(); +} + ++void ++Dialog_TargetParam::on_vcodec_change() ++{ ++ std::string codecnamed = vcodec->get_active_text(); ++ customvcodec->set_sensitive(false); ++ for (int i = 0; allowed_video_codecs[i] != NULL && ++ allowed_video_codecs_description[i] != NULL; i++) ++ if(!codecnamed.compare(allowed_video_codecs_description[i])) ++ { ++ if(!codecnamed.compare(CUSTOM_VCODEC_DESCRIPTION)) ++ customvcodec->set_sensitive(true); ++ else ++ customvcodec->set_text(allowed_video_codecs[i]); ++ } ++} ++ +Dialog_TargetParam::~Dialog_TargetParam() +{ +} + diff --cc synfig-studio/src/gui/dialogs/dialog_targetparam.h index 5575c20,0000000..8eb0c52 mode 100644,000000..100644 --- a/synfig-studio/src/gui/dialogs/dialog_targetparam.h +++ b/synfig-studio/src/gui/dialogs/dialog_targetparam.h @@@ -1,71 -1,0 +1,73 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file dialogs/dialog_targetparam.h +** \brief Targetparam Dialog Header +** +** $Id$ +** +** \legal +** Copyright (c) 2010 Carlos López González +** +** 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 +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_DIALOG_TARGETPARAM_H +#define __SYNFIG_STUDIO_DIALOG_TARGETPARAM_H + +/* === H E A D E R S ======================================================= */ +#include +#include +#include +#include + +#include + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class Dialog_TargetParam : public Gtk::Dialog +{ + synfig::TargetParam tparam_; + Gtk::Button *ok_button; + Gtk::Button *cancel_button; + Gtk::SpinButton *bitrate; + Gtk::ComboBoxText *vcodec; ++ Gtk::Entry *customvcodec; + + void on_ok(); + void on_cancel(); ++ void on_vcodec_change(); + +public: - Dialog_TargetParam(synfig::TargetParam &tparam); ++ Dialog_TargetParam(Gtk::Window &parent, synfig::TargetParam &tparam); + ~Dialog_TargetParam(); + + synfig::TargetParam get_tparam() const { return tparam_; } + void set_tparam(const synfig::TargetParam &tp) {tparam_=tp; } + +}; + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif + + + diff --cc synfig-studio/src/gui/docks/dockmanager.cpp index a6c2ad6,0000000..b3fe3ea mode 100644,000000..100644 --- a/synfig-studio/src/gui/docks/dockmanager.cpp +++ b/synfig-studio/src/gui/docks/dockmanager.cpp @@@ -1,328 -1,0 +1,313 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file dockmanager.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** 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 "docks/dockmanager.h" +#include +#include "docks/dockable.h" +#include "docks/dockdialog.h" +#include +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +class studio::DockSettings : public synfigapp::Settings +{ + DockManager* dock_manager; + +public: + DockSettings(DockManager* dock_manager):dock_manager(dock_manager) + { + synfigapp::Main::settings().add_domain(this,"dock"); + } + + virtual ~DockSettings() + { + synfigapp::Main::settings().remove_domain("dock"); + } - #define SCALE_FACTOR (1280) + virtual bool get_value(const synfig::String& key_, synfig::String& value)const + { - int screen_w(Gdk::screen_width()); - int screen_h(Gdk::screen_height()); + + if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")try + { + synfig::String key(key_.begin()+7,key_.end()); + synfig::String::size_type separator=key.find_first_of('.'); + int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str())); + key=synfig::String(key.begin()+separator+1,key.end()); + + DockDialog& dock_dialog(dock_manager->find_dock_dialog(id)); + + if(key=="contents_size") + { + dock_dialog.rebuild_sizes(); + vector::const_iterator iter(dock_dialog.get_dock_book_sizes().begin()); + vector::const_iterator end(dock_dialog.get_dock_book_sizes().end()); + value.clear(); + for(;iter!=end;++iter) - value+=strprintf("%d ",(*iter)*SCALE_FACTOR/screen_h); ++ value+=strprintf("%d ",*iter); + return true; + } + if(key=="pos") + { + int x,y; dock_dialog.get_position(x,y); - value=strprintf("%d %d",x*SCALE_FACTOR/screen_w,y*SCALE_FACTOR/screen_h); ++ value=strprintf("%d %d",x,y); + return true; + } + if(key=="size") + { + int x,y; dock_dialog.get_size(x,y); - value=strprintf("%d %d",x*SCALE_FACTOR/screen_w,y*SCALE_FACTOR/screen_h); ++ value=strprintf("%d %d",x,y); + return true; + } + if(key=="contents") + { + value=dock_dialog.get_contents(); + return true; + } + if(key=="comp_selector") + { + value=dock_dialog.get_composition_selector()?"1":"0"; + return true; + } + }catch (...) { return false; } + return synfigapp::Settings::get_value(key_,value); + } + + virtual bool set_value(const synfig::String& key_,const synfig::String& value) + { - int screen_w(Gdk::screen_width()); - int screen_h(Gdk::screen_height()); + + if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog") + { + synfig::String key(key_.begin()+7,key_.end()); + synfig::String::size_type separator=key.find_first_of('.'); + int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str())); + key=synfig::String(key.begin()+separator+1,key.end()); + + DockDialog& dock_dialog(dock_manager->find_dock_dialog(id)); + + if(key=="contents_size") + { + try { + int width, height; + Gtk::IconSize::lookup(Gtk::IconSize(4),width,height); + vector data; + String::size_type n=0; + String value_(value); + while(value_.size() && value_.size()>n){ + value_=String(value_.begin()+n,value_.end()); + int size; + if(!strscanf(value_,"%d",&size)) + break; - if (size > SCALE_FACTOR) size = SCALE_FACTOR - 150; - if (size < 0) size = 0; - size=size*screen_h/SCALE_FACTOR; - - // prevent errors like this, by allowing space for at least the dockable's icon: - // ** CRITICAL **: clearlooks_style_draw_box_gap: assertion `height >= -1' failed - if (size < height + 9) size = height + 9; + + data.push_back(size); + + n=value_.find(" "); + if(n==String::npos) + break; + n++; + } + dock_dialog.set_dock_book_sizes(data); + } + catch(...) + { + synfig::error("Exception caught!!!"); + return false; + } + return true; + } + if(key=="pos") + { + int x,y; + if(!strscanf(value,"%d %d",&x, &y)) + return false; - if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0; - if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0; - x=x*screen_w/SCALE_FACTOR; - y=y*screen_h/SCALE_FACTOR; - if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET")) - x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET")); - if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET")) - y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET")); ++ //synfig::info("dock_manager. move to: %d, %d", x,y); + dock_dialog.move(x,y); + return true; + } + if(key=="size") + { + int x,y; + if(!strscanf(value,"%d %d",&x, &y)) + return false; - if (x > SCALE_FACTOR) x = 150; if (x < 0) x = 0; - if (y > SCALE_FACTOR) y = 150; if (y < 0) y = 0; - x=x*screen_w/SCALE_FACTOR; - y=y*screen_h/SCALE_FACTOR; ++ //synfig::info("dock_manager. size to: %d, %d", x,y); + dock_dialog.set_default_size(x,y); + dock_dialog.resize(x,y); + return true; + } + if(key=="contents") + { + dock_dialog.set_contents(value); + return true; + } + if(key=="comp_selector") + { + if(value.empty() || value[0]=='0') + dock_dialog.set_composition_selector(false); + else + dock_dialog.set_composition_selector(true); + return true; + } + } + return synfigapp::Settings::set_value(key_,value); + } + + virtual KeyList get_key_list()const + { + synfigapp::Settings::KeyList ret(synfigapp::Settings::get_key_list()); + + std::list::const_iterator iter; + for(iter=dock_manager->dock_dialog_list_.begin();iter!=dock_manager->dock_dialog_list_.end();++iter) + { + ret.push_back(strprintf("dialog.%d.contents",(*iter)->get_id())); + ret.push_back(strprintf("dialog.%d.comp_selector",(*iter)->get_id())); + ret.push_back(strprintf("dialog.%d.pos",(*iter)->get_id())); + ret.push_back(strprintf("dialog.%d.size",(*iter)->get_id())); + ret.push_back(strprintf("dialog.%d.contents_size",(*iter)->get_id())); + } + return ret; + } +}; + +/* === M E T H O D S ======================================================= */ + +DockManager::DockManager(): + dock_settings(new DockSettings(this)) +{ +} + +DockManager::~DockManager() +{ + while(!dock_dialog_list_.empty()) + { + dock_dialog_list_.back()->close(); + } + while(!dockable_list_.empty()) + { + Dockable* dockable(dockable_list_.back()); + // synfig::info("DockManager::~DockManager(): Deleting dockable \"%s\"",dockable->get_name().c_str()); + dockable_list_.pop_back(); + delete dockable; + } +} + +void +DockManager::register_dockable(Dockable& x) +{ + dockable_list_.push_back(&x); + // synfig::info("DockManager::register_dockable(): Registered dockable \"%s\"",dockable_list_.back()->get_name().c_str()); + signal_dockable_registered()(&x); +} + +bool +DockManager::unregister_dockable(Dockable& x) +{ + std::list::iterator iter; + for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter) + { + if(&x==*iter) + { + x.detach(); + dockable_list_.erase(iter); + synfig::info("DockManager::unregister_dockable(): \"%s\" has been Unregistered",x.get_name().c_str()); + return true; + } + } + return false; +} + +Dockable& +DockManager::find_dockable(const synfig::String& x) +{ + std::list::iterator iter; + for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter) + if((*iter)->get_name()==x) + return **iter; + + throw std::runtime_error("DockManager::find_dockable(): not found"); +} + +void +DockManager::present(synfig::String x) +{ + try + { + find_dockable(x).present(); + } + catch(...) + { + } +} + +DockDialog& +DockManager::find_dock_dialog(int id) +{ + std::list::iterator iter; + for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter) + if((*iter)->get_id()==id) + return **iter; + + DockDialog* dock_dialog(new DockDialog()); + dock_dialog->set_id(id); - dock_dialog->show(); + return *dock_dialog; +} + +const DockDialog& +DockManager::find_dock_dialog(int id)const +{ + std::list::const_iterator iter; + for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter) + if((*iter)->get_id()==id) + return **iter; + + throw std::runtime_error("DockManager::find_dock_dialog(int id)const: not found"); +} ++ ++void ++DockManager::show_all_dock_dialogs() ++{ ++ std::list::iterator iter; ++ for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter) ++ (*iter)->present(); ++} diff --cc synfig-studio/src/gui/docks/dockmanager.h index 0949bcc,0000000..e92e06c mode 100644,000000..100644 --- a/synfig-studio/src/gui/docks/dockmanager.h +++ b/synfig-studio/src/gui/docks/dockmanager.h @@@ -1,82 -1,0 +1,83 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file docks/dockmanager.h +** \brief Template Header +** +** $Id$ +** +** \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 +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_DOCKMANAGER_H +#define __SYNFIG_DOCKMANAGER_H + +/* === H E A D E R S ======================================================= */ + +#include +#include +#include +#include +#include +#include + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio { + +class Dockable; +class DockDialog; +class DockSettings; + +class DockManager : public sigc::trackable +{ + friend class Dockable; + friend class DockDialog; + friend class DockSettings; + + std::list dockable_list_; + std::list dock_dialog_list_; + + sigc::signal signal_dockable_registered_; + + etl::smart_ptr dock_settings; + +public: + DockManager(); + ~DockManager(); + + DockDialog& find_dock_dialog(int id); + const DockDialog& find_dock_dialog(int id)const; + + sigc::signal& signal_dockable_registered() { return signal_dockable_registered_; } + + void register_dockable(Dockable& x); + bool unregister_dockable(Dockable& x); + Dockable& find_dockable(const synfig::String& x); + void present(synfig::String x); ++ void show_all_dock_dialogs(); + +}; // END of class DockManager + +}; // END of namespace studio + +/* === E N D =============================================================== */ + +#endif diff --cc synfig-studio/src/gui/duck.cpp index 14ea8d0,0000000..da571f6 mode 100644,000000..100644 --- a/synfig-studio/src/gui/duck.cpp +++ b/synfig-studio/src/gui/duck.cpp @@@ -1,300 -1,0 +1,300 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file duck.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2009 Nikita Kitaev +** +** 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 "duck.h" +#include + +#include +#include +#include +#include +#include + +#include "general.h" +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +int studio::Duck::duck_count(0); + +struct _DuckCounter +{ + static int counter; + ~_DuckCounter() + { + if(counter) + synfig::error("%d ducks not yet deleted!",counter); + } +} _duck_counter; + +int _DuckCounter::counter(0); + + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +Duck::Duck(): + rotations(synfig::Angle::deg(0)), + origin(0,0), + scalar(1), + editable(false), + radius_(false), + tangent_(false), + hover_(false), + ignore_(false) +{ duck_count++; _DuckCounter::counter++; } + +Duck::Duck(const synfig::Point &point): + type_(TYPE_NONE), + point(point), + rotations(synfig::Angle::deg(0)), + origin(0,0), + scalar(1), + guid_(0), + editable(false), + radius_(false), + tangent_(false), + hover_(false), + ignore_(false) +{ duck_count++; _DuckCounter::counter++;} + +Duck::Duck(const synfig::Point &point,const synfig::Point &origin): + point(point), + rotations(synfig::Angle::deg(0)), + origin(origin), + scalar(1), + guid_(0), + editable(false), + radius_(true), + tangent_(false), + hover_(false), + ignore_(false) +{ duck_count++; _DuckCounter::counter++;} + +Duck::~Duck() { duck_count--; _DuckCounter::counter--;} + +synfig::GUID +Duck::get_data_guid()const +{ + if(value_desc_.is_value_node()) + return value_desc_.get_value_node()->get_guid(); + return synfig::GUID::hasher(get_name()); +} + +void +Duck::set_name(const synfig::String &x) +{ + name=x; + if(guid_==synfig::GUID::zero()) + { + guid_=synfig::GUID::hasher(name); + } +} + + +bool +Duck::operator==(const Duck &rhs)const +{ + if(this==&rhs) + return true; + return + name==rhs.name && + scalar==rhs.scalar && + type_==rhs.type_ && + transform_stack_.size()==rhs.transform_stack_.size(); + //true; + //(origin_duck?*origin_duck==*rhs.origin_duck:origin==rhs.origin) && + //(shared_point?*shared_point==*rhs.shared_point:point==rhs.point) ; +} + +synfig::Point +Duck::get_trans_point()const +{ + return transform_stack_.perform(get_sub_trans_point()); +} + +void +Duck::set_trans_point(const synfig::Point &x) +{ + set_sub_trans_point(transform_stack_.unperform(x)); +} + +void +Duck::set_trans_point(const synfig::Point &x, const synfig::Time &time) +{ + set_sub_trans_point(transform_stack_.unperform(x), time); +} + +//! Sets the origin point. +void +Duck::set_origin(const synfig::Point &x) +{ + origin=x; origin_duck=0; +} + +//! Sets the origin point as another duck +void +Duck::set_origin(const etl::handle &x) +{ + origin_duck=x; +} + +//! Retrieves the origin location +synfig::Point +Duck::get_origin()const +{ + return origin_duck?origin_duck->get_point():origin; +} + +//! Retrieves the origin duck +const etl::handle & +Duck::get_origin_duck() const +{ + return origin_duck; +} + +//! Retrieves the origin location +synfig::Point +Duck::get_trans_origin()const +{ + return transform_stack_.perform(get_sub_trans_origin()); +} + +synfig::Point +Duck::get_sub_trans_point()const +{ + return get_point()*get_scalar()+get_sub_trans_origin(); +} + +void +Duck::set_sub_trans_point(const synfig::Point &x, const synfig::Time &time) +{ + if (get_type() == Duck::TYPE_TANGENT || + get_type() == Duck::TYPE_ANGLE) + { + Angle old_angle = get_point().angle(); + set_point((x-get_sub_trans_origin())/get_scalar()); + Angle change = get_point().angle() - old_angle; + while (change < Angle::deg(-180)) change += Angle::deg(360); + while (change > Angle::deg(180)) change -= Angle::deg(360); - int old_halves = round_to_int(Angle::deg(rotations).get()/180); ++ //int old_halves = round_to_int(Angle::deg(rotations).get()/180); + rotations += change; - int new_halves = round_to_int(Angle::deg(rotations).get()/180); - if (old_halves != new_halves && ++ //int new_halves = round_to_int(Angle::deg(rotations).get()/180); ++ /*if (old_halves != new_halves && + (new_halves > 1 || new_halves < -1 || + old_halves > 1 || old_halves < -1)) - synfig::info("rotation: %.2f turns", new_halves/2.0); ++ synfig::info("rotation: %.2f turns", new_halves/2.0)*/; + } else if(get_type() == Duck::TYPE_VERTEX || get_type() == Duck::TYPE_POSITION) + { + set_point((x-get_sub_trans_origin())/get_scalar()); + + ValueNode_BLineCalcVertex::Handle bline_vertex; + ValueNode_Composite::Handle composite; + + if ((bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(get_value_desc().get_value_node())) || + ((composite = ValueNode_Composite::Handle::cast_dynamic(get_value_desc().get_value_node())) && + composite->get_type() == ValueBase::TYPE_BLINEPOINT && + (bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(composite->get_link("point"))))) + { + synfig::Point closest_point = get_point(); + synfig::Real radius = 0.0; + ValueNode_BLine::Handle bline = ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline"))); + synfig::find_closest_point( + (*bline)(time), + get_point(), + radius, + bline->get_loop(), + &closest_point); + set_point(closest_point); + } + } + else set_point((x-get_sub_trans_origin())/get_scalar()); +} + +void +Duck::set_sub_trans_point(const synfig::Point &x) +{ + if (get_type() == Duck::TYPE_TANGENT || + get_type() == Duck::TYPE_ANGLE) + { + Angle old_angle = get_point().angle(); + set_point((x-get_sub_trans_origin())/get_scalar()); + Angle change = get_point().angle() - old_angle; + while (change < Angle::deg(-180)) change += Angle::deg(360); + while (change > Angle::deg(180)) change -= Angle::deg(360); - int old_halves = round_to_int(Angle::deg(rotations).get()/180); ++ //int old_halves = round_to_int(Angle::deg(rotations).get()/180); + rotations += change; - int new_halves = round_to_int(Angle::deg(rotations).get()/180); - if (old_halves != new_halves && ++ //int new_halves = round_to_int(Angle::deg(rotations).get()/180); ++ /*if (old_halves != new_halves && + (new_halves > 1 || new_halves < -1 || + old_halves > 1 || old_halves < -1)) - synfig::info("rotation: %.2f turns", new_halves/2.0); ++ synfig::info("rotation: %.2f turns", new_halves/2.0);*/ + } + else set_point((x-get_sub_trans_origin())/get_scalar()); +} + +synfig::Point +Duck::get_sub_trans_origin()const +{ + return origin_duck?origin_duck->get_sub_trans_point():origin; +} + +#ifdef _DEBUG +synfig::String +Duck::type_name(Type id) +{ + String ret; + + if (id & TYPE_POSITION) { if (!ret.empty()) ret += ", "; ret += "position"; } + if (id & TYPE_TANGENT ) { if (!ret.empty()) ret += ", "; ret += "tangent" ; } + if (id & TYPE_RADIUS ) { if (!ret.empty()) ret += ", "; ret += "radius" ; } + if (id & TYPE_WIDTH ) { if (!ret.empty()) ret += ", "; ret += "width" ; } + if (id & TYPE_ANGLE ) { if (!ret.empty()) ret += ", "; ret += "angle" ; } + if (id & TYPE_VERTEX ) { if (!ret.empty()) ret += ", "; ret += "vertex" ; } + + if (ret.empty()) + ret = "none"; + + return ret; +} +#endif // _DEBUG diff --cc synfig-studio/src/gui/iconcontroller.cpp index 87e7edb,0000000..5b5a8d1 mode 100644,000000..100644 --- a/synfig-studio/src/gui/iconcontroller.cpp +++ b/synfig-studio/src/gui/iconcontroller.cpp @@@ -1,548 -1,0 +1,548 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file iconcontroller.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2008 Paul Wise +** Copyright (c) 2009 Gerco Ballintijn +** Copyright (c) 2009 Carlos López +** Copyright (c) 2009 Nikita Kitaev +** +** 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 "iconcontroller.h" +#include +#include +#include +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace etl; +using namespace std; +using namespace studio; +using namespace synfig; + +/* === M A C R O S ========================================================= */ + +#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 "png" +#endif + +/* === M E T H O D S ======================================================= */ + +static Glib::RefPtr _tree_pixbuf_table_value_type[(int)synfig::ValueBase::TYPE_END]; + +#ifdef WIN32 +IconController::IconController(const synfig::String& basepath) +#else +IconController::IconController(const synfig::String& /*basepath*/) +#endif +{ + Gtk::IconSource icon_source; + icon_source.set_direction_wildcarded(); + icon_source.set_state_wildcarded(); + icon_source.set_size_wildcarded(); + icon_factory=Gtk::IconFactory::create(); + + std::string path_to_icons; +#ifdef WIN32 + path_to_icons=basepath+ETL_DIRECTORY_SEPARATOR+".."+ETL_DIRECTORY_SEPARATOR+IMAGE_DIR; +#else + path_to_icons=IMAGE_DIR; +#endif + + char* synfig_root=getenv("SYNFIG_ROOT"); + if(synfig_root) { + path_to_icons=synfig_root; + path_to_icons+=ETL_DIRECTORY_SEPARATOR; + path_to_icons+="share"; + path_to_icons+=ETL_DIRECTORY_SEPARATOR; + path_to_icons+="pixmaps"; + path_to_icons+=ETL_DIRECTORY_SEPARATOR; + path_to_icons+="synfigstudio"; + } + path_to_icons+=ETL_DIRECTORY_SEPARATOR; + + try{ + Gtk::Window::set_default_icon_from_file(path_to_icons+"synfig_icon."+IMAGE_EXT); + } catch(...) + { + synfig::warning("Unable to open "+path_to_icons+"synfig_icon."+IMAGE_EXT); + } + +#define INIT_STOCK_ICON(name,iconfile,desc){ \ + Gtk::StockItem stockitem(Gtk::StockID("synfig-" #name),desc); \ + Gtk::Stock::add(stockitem); \ + Gtk::IconSet icon_set; \ + icon_source.set_filename(path_to_icons+iconfile); \ + icon_set.add_source(icon_source); \ + icon_factory->add(stockitem.get_stock_id(),icon_set); \ + } + +#define INIT_STOCK_ICON_CLONE(name,stockid,desc){ \ + Gtk::StockItem stockitem(Gtk::StockID("synfig-" #name),desc); \ + Gtk::Stock::add(stockitem); \ + Gtk::IconSet icon_set; \ + if(Gtk::Stock::lookup(stockitem.get_stock_id(),icon_set)) \ + icon_factory->add(stockitem.get_stock_id(),icon_set); \ + } + +#define INIT_STOCK_ITEM(name,desc) \ + stock_##name=Gtk::StockItem(Gtk::StockID("synfig-" #name),desc); \ + Gtk::Stock::add(stock_##name); + + INIT_STOCK_ICON(bool,"bool_icon."IMAGE_EXT,_("Bool")); + INIT_STOCK_ICON(integer,"integer_icon."IMAGE_EXT,_("Integer")); + INIT_STOCK_ICON(angle,"angle_icon."IMAGE_EXT,_("Angle")); + INIT_STOCK_ICON(time,"time_icon."IMAGE_EXT,_("Time")); + INIT_STOCK_ICON(real,"real_icon."IMAGE_EXT,_("Real")); + INIT_STOCK_ICON(vector,"vector_icon."IMAGE_EXT,_("Vector")); + INIT_STOCK_ICON(color,"color_icon."IMAGE_EXT,_("Color")); + INIT_STOCK_ICON(segment,"segment_icon."IMAGE_EXT,_("Segment")); + INIT_STOCK_ICON(blinepoint,"blinepoint_icon."IMAGE_EXT,_("BLine Point")); + INIT_STOCK_ICON(list,"list_icon."IMAGE_EXT,_("Rename")); + INIT_STOCK_ICON(canvas,"canvas_icon."IMAGE_EXT,_("Canvas")); + INIT_STOCK_ICON(string,"string_icon."IMAGE_EXT,_("Rename")); + + INIT_STOCK_ICON(reset_colors,"reset_colors_icon."IMAGE_EXT,_("Reset Colors")); + INIT_STOCK_ICON(swap_colors,"swap_colors_icon."IMAGE_EXT,_("Swap Colors")); + INIT_STOCK_ICON(value_node,"valuenode_icon."IMAGE_EXT,_("ValueNode")); + INIT_STOCK_ICON(about,"about_icon."IMAGE_EXT,_("About")); + INIT_STOCK_ICON(rename,"rename_icon."IMAGE_EXT,_("Rename")); + INIT_STOCK_ICON(canvas_pointer,"canvas_pointer_icon."IMAGE_EXT,_("Rename")); + INIT_STOCK_ICON(canvas_new,"canvas_icon."IMAGE_EXT,_("New Canvas")); + INIT_STOCK_ICON(saveall,"saveall_icon."IMAGE_EXT,_("Save All")); + + INIT_STOCK_ICON(layer,"layer_icon."IMAGE_EXT,_("Layer")); + INIT_STOCK_ICON(layer_pastecanvas,"pastecanvas_icon."IMAGE_EXT,_("Paste Canvas")); + INIT_STOCK_ICON(layer_duplicate,"layer_duplicate_icon."IMAGE_EXT,_("Duplicate Layer")); + INIT_STOCK_ICON(layer_gradient_lineal,"gradient_icon."IMAGE_EXT,_("Lineal Gradient Layer")); + INIT_STOCK_ICON(layer_gradient_radial,"layer_gradient_radial_icon."IMAGE_EXT,_("Radial Gradient Layer")); + INIT_STOCK_ICON(layer_gradient_spiral,"layer_gradient_spiral_icon."IMAGE_EXT,_("Spiral Gradient Layer")); + INIT_STOCK_ICON(layer_gradient_curve,"layer_gradient_curve_icon."IMAGE_EXT,_("Curve Gradient Layer")); + INIT_STOCK_ICON(layer_gradient_conical,"layer_gradient_conical_icon."IMAGE_EXT,_("Conical Gradient Layer")); + INIT_STOCK_ICON(layer_gradient_noise,"layer_gradient_noise_icon."IMAGE_EXT,_("Noise Gradient Layer")); + INIT_STOCK_ICON(layer_checkerboard,"layer_checkerboard_icon."IMAGE_EXT,_("Checker Board Layer")); + INIT_STOCK_ICON(layer_blur,"layer_blur_icon."IMAGE_EXT,_("Blur Layer")); + INIT_STOCK_ICON(layer_blur_motion,"layer_blur_motion_icon."IMAGE_EXT,_("Motion Blur Layer")); + INIT_STOCK_ICON(layer_blur_radial,"layer_blur_radial_icon."IMAGE_EXT,_("Radial Blur Layer")); + INIT_STOCK_ICON(layer_distortion_curvewarp,"layer_distortion_curvewarp_icon."IMAGE_EXT,_("Curve Warp Layer")); + INIT_STOCK_ICON(layer_distortion_insideout,"layer_distortion_insideout_icon."IMAGE_EXT,_("Inside Out Layer")); + INIT_STOCK_ICON(layer_distortion_noise,"layer_distortion_noise_icon."IMAGE_EXT,_("Noise Distort Layer")); + INIT_STOCK_ICON(layer_distortion_spherize,"layer_distortion_spherize_icon."IMAGE_EXT,_("Spherize Layer")); + INIT_STOCK_ICON(layer_distortion_stretch,"layer_distortion_stretch_icon."IMAGE_EXT,_("Stretch Layer")); + INIT_STOCK_ICON(layer_distortion_twirl,"layer_distortion_twirl_icon."IMAGE_EXT,_("Twirl Layer")); + INIT_STOCK_ICON(layer_distortion_warp,"layer_distortion_warp_icon."IMAGE_EXT,_("Warp Layer")); + INIT_STOCK_ICON(layer_filter_clamp,"layer_filter_clamp_icon."IMAGE_EXT,_("Clamp Layer")); + INIT_STOCK_ICON(layer_filter_colorcorrect,"layer_filter_colorcorrect_icon."IMAGE_EXT,_("Color Correct Layer")); + INIT_STOCK_ICON(layer_filter_halftone2,"layer_filter_halftone2_icon."IMAGE_EXT,_("Half Tone 2 Layer")); + INIT_STOCK_ICON(layer_filter_halftone3,"layer_filter_halftone3_icon."IMAGE_EXT,_("Half Tone 3 Layer")); + INIT_STOCK_ICON(layer_filter_luma,"layer_filter_luma_icon."IMAGE_EXT,_("Luma Layer")); + INIT_STOCK_ICON(layer_fractal_mandelbrot,"layer_fractal_mandelbrot_icon."IMAGE_EXT,_("Mandelbrot Set Layer")); + INIT_STOCK_ICON(layer_fractal_julia,"layer_fractal_julia_icon."IMAGE_EXT,_("Julia Set Layer")); + INIT_STOCK_ICON(layer_stylize_bevel,"layer_stylize_bevel_icon."IMAGE_EXT,_("Bevel Layer")); + INIT_STOCK_ICON(layer_stylize_shade,"layer_stylize_shade_icon."IMAGE_EXT,_("Shade Layer")); + INIT_STOCK_ICON(layer_example_metaballs,"layer_example_metaballs_icon."IMAGE_EXT,_("Metaballs Layer")); + INIT_STOCK_ICON(layer_other_XOR,"layer_other_XOR_icon."IMAGE_EXT,_("XOR Pattern Layer")); + INIT_STOCK_ICON(layer_other_supersample,"layer_other_supersample_icon."IMAGE_EXT,_("Super Sample Layer")); + INIT_STOCK_ICON(layer_other_timeloop,"layer_other_timeloop_icon."IMAGE_EXT,_("Time Loop Layer")); + INIT_STOCK_ICON(layer_transform_translate,"layer_transform_translate_icon."IMAGE_EXT,_("Translate Layer")); + + INIT_STOCK_ICON(plant,"plant_icon."IMAGE_EXT,""); + + INIT_STOCK_ICON(group,"group_icon."IMAGE_EXT,_("Group")); + INIT_STOCK_ICON(grid_enable,"grid_enable_icon."IMAGE_EXT,_("Show Grid")); + INIT_STOCK_ICON(grid_disable,"grid_disable_icon."IMAGE_EXT,_("Hide Grid")); + INIT_STOCK_ICON(grid_snap_enable,"grid_snap_enable_icon."IMAGE_EXT,_("Enable Grid Snap")); + INIT_STOCK_ICON(grid_snap_disable,"grid_snap_disable_icon."IMAGE_EXT,_("Disable Grid Snap")); + INIT_STOCK_ICON(duplicate,"duplicate_icon."IMAGE_EXT,_("Duplicate")); + INIT_STOCK_ICON(encapsulate,"encapsulate_icon."IMAGE_EXT,_("Encapsulate")); + INIT_STOCK_ICON(select_all_child_layers,"select_all_child_layers_icon."IMAGE_EXT,_("Select All Child Layers")); + + INIT_STOCK_ICON(clear_undo,"clear_undo_icon."IMAGE_EXT,_("Clear Undo Stack")); + INIT_STOCK_ICON(clear_redo,"clear_redo_icon."IMAGE_EXT,_("Clear Redo Stack")); + + INIT_STOCK_ICON(children,"children_icon."IMAGE_EXT,_("Children")); + INIT_STOCK_ICON(curves,"curves_icon."IMAGE_EXT,_("Curves")); + INIT_STOCK_ICON(keyframes,"keyframe_icon."IMAGE_EXT,_("Keyframes")); + INIT_STOCK_ICON(meta_data,"meta_data_icon."IMAGE_EXT,_("MetaData")); + INIT_STOCK_ICON(navigator,"navigator_icon."IMAGE_EXT,_("Navigator")); + INIT_STOCK_ICON(timetrack,"time_track_icon."IMAGE_EXT,_("Time Track")); + + INIT_STOCK_ICON(keyframe_lock_all,"keyframe_lock_all."IMAGE_EXT,_("All Keyframes Locked")); + INIT_STOCK_ICON(keyframe_lock_past,"keyframe_lock_past."IMAGE_EXT,_("Past Keyframes Locked")); + INIT_STOCK_ICON(keyframe_lock_future,"keyframe_lock_future."IMAGE_EXT,_("Future Keyframes Locked")); + INIT_STOCK_ICON(keyframe_lock_none,"keyframe_lock_none."IMAGE_EXT,_("No Keyframes Locked")); + + INIT_STOCK_ICON(set_outline_color,"set_outline_color."IMAGE_EXT,_("Set as Outline")); + INIT_STOCK_ICON(set_fill_color,"set_fill_color."IMAGE_EXT,_("Set as Fill")); + + INIT_STOCK_ICON(seek_begin,"seek_begin."IMAGE_EXT,_("Seek to Begin")); + INIT_STOCK_ICON(seek_prev_frame,"seek_prev_frame."IMAGE_EXT,_("Previous Frame")); + INIT_STOCK_ICON(seek_next_frame,"seek_next_frame."IMAGE_EXT,_("Next Frame")); + INIT_STOCK_ICON(seek_end,"seek_end."IMAGE_EXT,_("Seek to End")); + INIT_STOCK_ICON(add_to_group,"action_add_to_group_icon."IMAGE_EXT,_("Add Layer to Group")); + INIT_STOCK_ICON(remove_from_group,"action_remove_from_group_icon."IMAGE_EXT,_("Remove Layer from Group")); + INIT_STOCK_ICON(set_desc,"action_set_layer_description_icon."IMAGE_EXT,_("Set Layer Description")); + INIT_STOCK_ICON(export,"action_export_icon."IMAGE_EXT,_("Export Value Node")); + INIT_STOCK_ICON(unexport,"action_unexport_icon."IMAGE_EXT,_("Unexport Value Node")); + + INIT_STOCK_ICON(toggle_duck_position,"duck_position_icon."IMAGE_EXT,_("Toggle position ducks")); + INIT_STOCK_ICON(toggle_duck_vertex,"duck_vertex_icon."IMAGE_EXT,_("Toggle vertex ducks")); + INIT_STOCK_ICON(toggle_duck_tangent,"duck_tangent_icon."IMAGE_EXT,_("Toggle tangent ducks")); + INIT_STOCK_ICON(toggle_duck_radius,"duck_radius_icon."IMAGE_EXT,_("Toggle radius ducks")); + INIT_STOCK_ICON(toggle_duck_width,"duck_width_icon."IMAGE_EXT,_("Toggle width ducks")); + INIT_STOCK_ICON(toggle_duck_angle,"duck_angle_icon."IMAGE_EXT,_("Toggle angle ducks")); + + INIT_STOCK_ICON(toggle_show_grid,"show_grid_icon."IMAGE_EXT,_("Toggle show grid")); + INIT_STOCK_ICON(toggle_snap_grid,"snap_grid_icon."IMAGE_EXT,_("Toggle snap grid")); + + INIT_STOCK_ICON(toggle_onion_skin,"onion_skin_icon."IMAGE_EXT,_("Toggle onion skin")); + + INIT_STOCK_ICON(increase_resolution,"incr_resolution_icon."IMAGE_EXT,_("Increase resolution")); + INIT_STOCK_ICON(decrease_resolution,"decr_resolution_icon."IMAGE_EXT,_("Decrease resolution")); + + INIT_STOCK_ICON(preview_options,"preview_options_icon."IMAGE_EXT,_("Preview Options Dialog")); + INIT_STOCK_ICON(render_options,"render_options_icon."IMAGE_EXT,_("Render Options Dialog")); + + INIT_STOCK_ICON_CLONE(cvs_add,"gtk-add",_("CVS Add")); + INIT_STOCK_ICON_CLONE(cvs_update,"gtk-open",_("CVS Update")); + INIT_STOCK_ICON_CLONE(cvs_commit,"gtk-save",_("CVS Commit")); + INIT_STOCK_ICON_CLONE(cvs_revert,"gtk-revert",_("CVS Revert")); + + // Tools - INIT_STOCK_ICON(normal,"normal_icon."IMAGE_EXT,_("Normal Tool")); ++ INIT_STOCK_ICON(normal,"normal_icon."IMAGE_EXT,_("Transform Tool")); + INIT_STOCK_ICON(transform,"transform_icon."IMAGE_EXT,_("Transform Tool")); + INIT_STOCK_ICON(polygon,"polyline_icon."IMAGE_EXT,_("Polygon Tool")); + INIT_STOCK_ICON(bline,"bline_icon."IMAGE_EXT,_("BLine Tool")); + INIT_STOCK_ICON(eyedrop,"eyedrop_icon."IMAGE_EXT,_("Eyedrop Tool")); + INIT_STOCK_ICON(fill,"fill_icon."IMAGE_EXT,_("Fill Tool")); + INIT_STOCK_ICON(draw,"draw_icon."IMAGE_EXT,_("Draw Tool")); + INIT_STOCK_ICON(sketch,"sketch_icon."IMAGE_EXT,_("Sketch Tool")); + INIT_STOCK_ICON(circle,"circle_icon."IMAGE_EXT,_("Circle Tool")); + INIT_STOCK_ICON(rectangle,"rectangle_icon."IMAGE_EXT,_("Rectangle Tool")); + INIT_STOCK_ICON(smooth_move,"smooth_move_icon."IMAGE_EXT,_("SmoothMove Tool")); + INIT_STOCK_ICON(rotate,"rotate_icon."IMAGE_EXT,"Rotate Tool"); + INIT_STOCK_ICON(width,"width_icon."IMAGE_EXT,_("Width Tool")); + INIT_STOCK_ICON(scale,"scale_icon."IMAGE_EXT,"Scale Tool"); + INIT_STOCK_ICON(zoom,"zoom_icon."IMAGE_EXT,_("Zoom Tool")); + INIT_STOCK_ICON(info,"info_icon."IMAGE_EXT,_("Info Tool")); + INIT_STOCK_ICON(mirror,"mirror_icon."IMAGE_EXT,_("Mirror Tool")); + INIT_STOCK_ICON(text,"text_icon."IMAGE_EXT,"Text Tool"); + INIT_STOCK_ICON(gradient,"gradient_icon."IMAGE_EXT,_("Gradient Tool")); + INIT_STOCK_ICON(star,"star_icon."IMAGE_EXT,_("Star Tool")); + +#undef INIT_STOCK_ICON +#undef INIT_STOCK_ICON + + icon_factory->add_default(); + + Gtk::IconSize::register_new("synfig-small_icon",12,12); + Gtk::IconSize::register_new("synfig-small_icon_16x16",16,16); + + for(int i(0);i<(int)ValueBase::TYPE_END;i++) + _tree_pixbuf_table_value_type[i]=Gtk::Button().render_icon(value_icon(ValueBase::Type(i)),Gtk::ICON_SIZE_SMALL_TOOLBAR); + +} + +IconController::~IconController() +{ + for(int i(0);i<(int)ValueBase::TYPE_END;i++) + _tree_pixbuf_table_value_type[i]=Glib::RefPtr(); + + icon_factory->remove_default(); +} + +Gdk::Cursor +IconController::get_normal_cursor() +{ + return Gdk::Cursor(Gdk::TOP_LEFT_ARROW); +} + +Gdk::Cursor +IconController::get_tool_cursor(const Glib::ustring& name,const Glib::RefPtr& window) +{ + //this function is never called + //it is commented out in WorkArea::refresh_cursor() + assert(0); + // \todo Do we still need it? + + Glib::RefPtr pixmap; + pixmap=Gdk::Pixmap::create(window, 64, 64, 8); + pixmap->set_colormap(window->get_colormap()); + //pixmap->set_colormap(Gdk::Colormap::create(pixmap->get_visual(),false)); + Glib::RefPtr pixbuf; + pixbuf=Gtk::Button().render_icon(Gtk::StockID("synfig-"+name),Gtk::ICON_SIZE_SMALL_TOOLBAR); + + pixbuf->render_to_drawable_alpha( + pixmap, + 0,0, // SOURCE X,Y + 0,0, // DEST X Y + -1,-1, // WIDTH HEIGHT + Gdk::PIXBUF_ALPHA_FULL, // (ignored) + 64, //int alpha_threshold, + Gdk::RGB_DITHER_MAX, //RgbDither dither, + 2,2 //int x_dither, int y_dither + ); +/* + pixmap->draw_pixbuf( + Glib::RefPtr(0), // GC + pixbuf, + 0, 0, // Source X,Y + 0, 0, // Dest X,Y + -1, -1, // Width, Height + Gdk::RGB_DITHER_MAX, // Dither + 0,0 // Dither X,Y + ); +*/ + + Gdk::Color FG("#000000"); + Gdk::Color BG("#FF00FF"); + + return Gdk::Cursor(pixmap, pixmap, FG, BG, 0, 0); +} + +Gtk::StockID +studio::value_icon(synfig::ValueBase::Type type) +{ + switch(type) + { + case ValueBase::TYPE_BOOL: + return Gtk::StockID("synfig-bool"); + break; + case ValueBase::TYPE_INTEGER: + return Gtk::StockID("synfig-integer"); + break; + case ValueBase::TYPE_ANGLE: + return Gtk::StockID("synfig-angle"); + break; + case ValueBase::TYPE_TIME: + return Gtk::StockID("synfig-time"); + break; + case ValueBase::TYPE_REAL: + return Gtk::StockID("synfig-real"); + break; + case ValueBase::TYPE_VECTOR: + return Gtk::StockID("synfig-vector"); + break; + case ValueBase::TYPE_COLOR: + return Gtk::StockID("synfig-color"); + break; + case ValueBase::TYPE_SEGMENT: + return Gtk::StockID("synfig-segment"); + break; + case ValueBase::TYPE_BLINEPOINT: + return Gtk::StockID("synfig-blinepoint"); + break; + case ValueBase::TYPE_LIST: + return Gtk::StockID("synfig-list"); + break; + case ValueBase::TYPE_CANVAS: + return Gtk::StockID("synfig-canvas_pointer"); + break; + case ValueBase::TYPE_STRING: + return Gtk::StockID("synfig-string"); + break; + case ValueBase::TYPE_GRADIENT: + return Gtk::StockID("synfig-gradient"); + break; + case ValueBase::TYPE_NIL: + default: + return Gtk::StockID("synfig-unknown"); + break; + } +} + +Gtk::StockID +studio::valuenode_icon(etl::handle value_node) +{ + if(handle::cast_dynamic(value_node)) + { + return value_icon(value_node->get_type()); + } + else + { + return Gtk::StockID("synfig-value_node"); + } +} + +Glib::RefPtr +studio::get_tree_pixbuf(synfig::ValueBase::Type type) +{ + //return Gtk::Button().render_icon(value_icon(type),Gtk::ICON_SIZE_SMALL_TOOLBAR); + return _tree_pixbuf_table_value_type[int(type)]; +} + +#ifdef WIN32 +#define TEMPORARY_DELETE_MACRO DELETE +#undef DELETE +#endif + +Gtk::StockID +studio::get_action_stock_id(const synfigapp::Action::BookEntry& action) +{ + Gtk::StockID stock_id; + if(action.task=="add") stock_id=Gtk::Stock::ADD; + else if(action.task=="connect") stock_id=Gtk::Stock::CONNECT; + else if(action.task=="disconnect") stock_id=Gtk::Stock::DISCONNECT; + else if(action.task=="insert") stock_id=Gtk::Stock::ADD; + else if(action.task=="lower") stock_id=Gtk::Stock::GO_DOWN; + else if(action.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM; + else if(action.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP; + else if(action.task=="raise") stock_id=Gtk::Stock::GO_UP; + else if(action.task=="remove") stock_id=Gtk::Stock::DELETE; + else if(action.task=="set_off") stock_id=Gtk::Stock::NO; + else if(action.task=="set_on") stock_id=Gtk::Stock::YES; + else stock_id=Gtk::StockID("synfig-"+ + action.task); + return stock_id; +} + +#ifdef WIN32 +#define DELETE TEMPORARY_DELETE_MACRO +#undef TEMPORARY_DELETE_MACRO +#endif + +Gtk::StockID +studio::layer_icon(const synfig::String &layer) +{ + if(layer=="PasteCanvas" || layer=="pastecanvas" || layer=="paste_canvas") + return Gtk::StockID("synfig-layer_pastecanvas"); + else if(layer=="rotate") + return Gtk::StockID("synfig-rotate"); + else if(layer=="zoom") + return Gtk::StockID("synfig-zoom"); + else if(layer=="region") + return Gtk::StockID("synfig-bline"); + else if(layer=="polygon") + return Gtk::StockID("synfig-polygon"); + else if(layer=="outline") + return Gtk::StockID("synfig-width"); + else if(layer=="circle") + return Gtk::StockID("synfig-circle"); + else if(layer=="rectangle") + return Gtk::StockID("synfig-rectangle"); + else if(layer=="star") + return Gtk::StockID("synfig-star"); + else if(layer=="plant") + return Gtk::StockID("synfig-plant"); + else if(layer=="text") + return Gtk::StockID("synfig-text"); + else if(layer=="checker_board") + return Gtk::StockID("synfig-layer_checkerboard"); + else if(layer=="duplicate") + return Gtk::StockID("synfig-layer_duplicate"); + else if(layer=="linear_gradient") + return Gtk::StockID("synfig-layer_gradient_lineal"); + else if(layer=="radial_gradient") + return Gtk::StockID("synfig-layer_gradient_radial"); + else if(layer=="spiral_gradient") + return Gtk::StockID("synfig-layer_gradient_spiral"); + else if(layer=="curve_gradient") + return Gtk::StockID("synfig-layer_gradient_curve"); + else if(layer=="conical_gradient") + return Gtk::StockID("synfig-layer_gradient_conical"); + else if(layer=="noise") + return Gtk::StockID("synfig-layer_gradient_noise"); + else if(layer=="blur") + return Gtk::StockID("synfig-layer_blur"); + else if(layer=="radial_blur") + return Gtk::StockID("synfig-layer_blur_radial"); + else if(layer=="MotionBlur") // in the future should be "motion_blur" + return Gtk::StockID("synfig-layer_blur_motion"); + else if(layer=="curve_warp") + return Gtk::StockID("synfig-layer_distortion_curvewarp"); + else if(layer=="inside_out") + return Gtk::StockID("synfig-layer_distortion_insideout"); + else if(layer=="noise_distort") + return Gtk::StockID("synfig-layer_distortion_noise"); + else if(layer=="spherize") + return Gtk::StockID("synfig-layer_distortion_spherize"); + else if(layer=="stretch") + return Gtk::StockID("synfig-layer_distortion_stretch"); + else if(layer=="twirl") + return Gtk::StockID("synfig-layer_distortion_twirl"); + else if(layer=="warp") + return Gtk::StockID("synfig-layer_distortion_warp"); + else if(layer=="clamp") + return Gtk::StockID("synfig-layer_filter_clamp"); + else if(layer=="colorcorrect") + return Gtk::StockID("synfig-layer_filter_colorcorrect"); + else if(layer=="halftone2") + return Gtk::StockID("synfig-layer_filter_halftone2"); + else if(layer=="halftone3") + return Gtk::StockID("synfig-layer_filter_halftone3"); + else if(layer=="lumakey") + return Gtk::StockID("synfig-layer_filter_luma"); + else if(layer=="mandelbrot") + return Gtk::StockID("synfig-layer_fractal_mandelbrot"); + else if(layer=="julia") + return Gtk::StockID("synfig-layer_fractal_julia"); + else if(layer=="bevel") + return Gtk::StockID("synfig-layer_stylize_bevel"); + else if(layer=="shade") + return Gtk::StockID("synfig-layer_stylize_shade"); + else if(layer=="metaballs") + return Gtk::StockID("synfig-layer_example_metaballs"); + else if(layer=="simple_circle") + return Gtk::StockID("synfig-circle"); + else if(layer=="filled_rectangle") + return Gtk::StockID("synfig-rectangle"); + else if(layer=="xor_pattern") + return Gtk::StockID("synfig-layer_other_XOR"); + else if(layer=="super_sample") + return Gtk::StockID("synfig-layer_other_supersample"); + else if(layer=="timeloop") + return Gtk::StockID("synfig-layer_other_timeloop"); + else if(layer=="translate") + return Gtk::StockID("synfig-layer_transform_translate"); + else + return Gtk::StockID("synfig-layer"); +} + +Glib::RefPtr +studio::get_tree_pixbuf_layer(const synfig::String &layer) +{ + return Gtk::Button().render_icon(layer_icon(layer),Gtk::ICON_SIZE_SMALL_TOOLBAR); +} diff --cc synfig-studio/src/gui/render.cpp index 870a356,0000000..a94a94c mode 100644,000000..100644 --- a/synfig-studio/src/gui/render.cpp +++ b/synfig-studio/src/gui/render.cpp @@@ -1,380 -1,0 +1,382 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file gtkmm/render.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** 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 "render.h" +#include "app.h" +#include +#include +#include +#include +#include "asyncrenderer.h" +#include "dialogs/dialog_targetparam.h" + +#include "general.h" + +#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 ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +RenderSettings::RenderSettings(Gtk::Window& parent, etl::handle canvas_interface): + Gtk::Dialog(_("Render Settings"),parent,false,true), + canvas_interface_(canvas_interface), + adjustment_quality(3,0,9), + entry_quality(adjustment_quality,1,0), + adjustment_antialias(1,1,31), + entry_antialias(adjustment_antialias,1,0), + toggle_single_frame(_("Use _current frame"), true), - tparam("libxvid",200) ++ tparam("mpeg4",200) +{ + widget_rend_desc.show(); + widget_rend_desc.signal_changed().connect(sigc::mem_fun(*this,&studio::RenderSettings::on_rend_desc_changed)); + widget_rend_desc.set_rend_desc(canvas_interface_->get_canvas()->rend_desc()); + + canvas_interface->signal_rend_desc_changed().connect(sigc::mem_fun(*this,&RenderSettings::on_rend_desc_changed)); + + menu_target=manage(new class Gtk::Menu()); + + menu_target->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Auto"), + sigc::bind(sigc::mem_fun(*this,&RenderSettings::set_target),String()) + )); + + synfig::Target::Book::iterator iter; + synfig::Target::Book book(synfig::Target::book()); + + for(iter=book.begin();iter!=book.end();iter++) + { + menu_target->items().push_back(Gtk::Menu_Helpers::MenuElem(iter->first, + sigc::bind(sigc::mem_fun(*this,&RenderSettings::set_target),iter->first) + )); + } + optionmenu_target.set_menu(*menu_target); + + optionmenu_target.set_history(0); + + Gtk::Alignment *dialogPadding = manage(new Gtk::Alignment(0, 0, 1, 1)); + dialogPadding->set_padding(12, 12, 12, 12); + get_vbox()->pack_start(*dialogPadding, false, false, 0); + + Gtk::VBox *dialogBox = manage(new Gtk::VBox(false, 12)); + dialogPadding->add(*dialogBox); + + Gtk::Button *choose_button(manage(new class Gtk::Button(Gtk::StockID(_("Choose..."))))); + choose_button->show(); + choose_button->signal_clicked().connect(sigc::mem_fun(*this, &studio::RenderSettings::on_choose_pressed)); + - Gtk::Button *tparam_button(manage(new class Gtk::Button(Gtk::StockID(_("Parameters..."))))); ++ tparam_button=manage(new class Gtk::Button(Gtk::StockID(_("Parameters...")))); + tparam_button->show(); ++ tparam_button->set_sensitive(false); + tparam_button->signal_clicked().connect(sigc::mem_fun(*this, &studio::RenderSettings::on_targetparam_pressed)); + + Gtk::Frame *target_frame=manage(new Gtk::Frame(_("Target"))); + target_frame->set_shadow_type(Gtk::SHADOW_NONE); + ((Gtk::Label *) target_frame->get_label_widget())->set_markup(_("Target")); + dialogBox->pack_start(*target_frame); + Gtk::Alignment *targetPadding = manage(new Gtk::Alignment(0, 0, 1, 1)); + targetPadding->set_padding(6, 0, 24, 0); + target_frame->add(*targetPadding); + + Gtk::Table *target_table = manage(new Gtk::Table(2, 3, false)); + target_table->set_row_spacings(6); + target_table->set_col_spacings(12); + targetPadding->add(*target_table); + + Gtk::Label *filenameLabel = manage(new Gtk::Label(_("_Filename"), true)); + filenameLabel->set_alignment(0, 0.5); + filenameLabel->set_mnemonic_widget(entry_filename); + target_table->attach(*filenameLabel, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + target_table->attach(entry_filename, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + target_table->attach(*choose_button, 2, 3, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + + Gtk::Label *targetLabel = manage(new Gtk::Label(_("_Target"), true)); + targetLabel->set_alignment(0, 0.5); + targetLabel->set_mnemonic_widget(optionmenu_target); + target_table->attach(*targetLabel, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + target_table->attach(optionmenu_target, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + target_table->attach(*tparam_button, 2, 3, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + + toggle_single_frame.signal_toggled().connect(sigc::mem_fun(*this, &studio::RenderSettings::on_single_frame_toggle)); + + Gtk::Frame *settings_frame=manage(new Gtk::Frame(_("Settings"))); + settings_frame->set_shadow_type(Gtk::SHADOW_NONE); + ((Gtk::Label *) settings_frame->get_label_widget())->set_markup(_("Settings")); + dialogBox->pack_start(*settings_frame); + + Gtk::Alignment *settingsPadding = manage(new Gtk::Alignment(0, 0, 1, 1)); + settingsPadding->set_padding(6, 0, 24, 0); + settings_frame->add(*settingsPadding); + + Gtk::Table *settings_table=manage(new Gtk::Table(2,2,false)); + settings_table->set_row_spacings(6); + settings_table->set_col_spacings(12); + settingsPadding->add(*settings_table); + + Gtk::Label *qualityLabel = manage(new Gtk::Label(_("_Quality"), true)); + qualityLabel->set_alignment(0, 0.5); + qualityLabel->set_mnemonic_widget(entry_quality); + settings_table->attach(*qualityLabel, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + settings_table->attach(entry_quality, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + + Gtk::Label *antiAliasLabel = manage(new Gtk::Label(_("_Anti-Aliasing"), true)); + antiAliasLabel->set_alignment(0, 0.5); + antiAliasLabel->set_mnemonic_widget(entry_antialias); + settings_table->attach(*antiAliasLabel, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + settings_table->attach(entry_antialias, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + + toggle_single_frame.set_alignment(0, 0.5); + settings_table->attach(toggle_single_frame, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + + dialogBox->pack_start(widget_rend_desc); + + + Gtk::Button *render_button(manage(new class Gtk::Button(Gtk::StockID(_("Render"))))); + render_button->show(); + add_action_widget(*render_button,1); + render_button->signal_clicked().connect(sigc::mem_fun(*this, &studio::RenderSettings::on_render_pressed)); + + Gtk::Button *cancel_button(manage(new class Gtk::Button(Gtk::StockID("gtk-cancel")))); + cancel_button->show(); + add_action_widget(*cancel_button,0); + cancel_button->signal_clicked().connect(sigc::mem_fun(*this, &studio::RenderSettings::on_cancel_pressed)); + + //set_default_response(1); + + set_title(_("Render Settings")+String(" - ")+canvas_interface_->get_canvas()->get_name()); + + toggle_single_frame.set_active(false); + widget_rend_desc.enable_time_section(); + + set_entry_filename(); + + get_vbox()->show_all(); +} + +RenderSettings::~RenderSettings() +{ +} + +void +RenderSettings::set_entry_filename() +{ + String filename(filename_sans_extension(canvas_interface_->get_canvas()->get_file_name())); + + // if this isn't the root canvas, append () to the filename + etl::handle canvas = canvas_interface_->get_canvas(); + if (!canvas->is_root()) + { + if(canvas->get_name().empty()) + filename+=" ("+canvas->get_id()+')'; + else + filename+=" ("+canvas->get_name()+')'; + } + + filename += ".png"; + + try + { + entry_filename.set_text((filename)); + } + catch(...) + { + synfig::warning("Averted crash!"); + entry_filename.set_text("output.png"); + } +} + +void +RenderSettings::on_rend_desc_changed() +{ + widget_rend_desc.set_rend_desc(canvas_interface_->get_canvas()->rend_desc()); +} + +void +RenderSettings::set_target(synfig::String name) +{ + target_name=name; ++ tparam_button->set_sensitive(target_name.compare("ffmpeg")?false:true); +} + +void +RenderSettings::on_choose_pressed() +{ + String filename=entry_filename.get_text(); + if(App::dialog_save_file("Save Render As", filename, RENDER_DIR_PREFERENCE)) + entry_filename.set_text(filename); +} + +void +RenderSettings::on_targetparam_pressed() +{ - Dialog_TargetParam *dialogtp = new Dialog_TargetParam(tparam); ++ Dialog_TargetParam *dialogtp = new Dialog_TargetParam(*this, tparam); + if(dialogtp->run()==Gtk::RESPONSE_OK) + tparam=dialogtp->get_tparam(); + + delete dialogtp; +} + +void +RenderSettings::on_render_pressed() +{ + String filename=entry_filename.get_text(); + synfig::String calculated_target_name(target_name); + + if(filename.empty()) + { + canvas_interface_->get_ui_interface()->error(_("You must supply a filename!")); + return; + } + + // If the target type is not yet defined, + // try to figure it out from the outfile. + if(calculated_target_name.empty()) + { + try + { + String ext(filename_extension(filename)); + if (ext.size()) ext=ext.substr(1); // skip initial '.' + synfig::info("render target filename: '%s'; extension: '%s'", filename.c_str(), ext.c_str()); + if(Target::ext_book().count(ext)) + { + calculated_target_name=Target::ext_book()[ext]; + synfig::info("'%s' is a known extension - using target '%s'", ext.c_str(), calculated_target_name.c_str()); + } + else + { + calculated_target_name=ext; + synfig::info("unknown extension"); + } + } + catch(std::runtime_error x) + { + canvas_interface_->get_ui_interface()->error(_("Unable to determine proper target from filename.")); + return; + } + } + + if(filename.empty() && calculated_target_name!="null") + { + canvas_interface_->get_ui_interface()->error(_("A filename is required for this target")); + return; + } + + Target::Handle target=Target::create(calculated_target_name,filename, tparam); + if(!target) + { + canvas_interface_->get_ui_interface()->error(_("Unable to create target for ")+filename); + return; + } + // This is the only way I've found to avoid send a non writable + // filename path to the renderer. + fstream filetest (filename.c_str(), fstream::out); + if (filetest.fail()) + { + canvas_interface_->get_ui_interface()->error(_("Unable to create file for ")+filename); + return; + } + + hide(); + + target->set_canvas(canvas_interface_->get_canvas()); + RendDesc rend_desc(widget_rend_desc.get_rend_desc()); + rend_desc.set_antialias((int)adjustment_antialias.get_value()); + + // If we are to only render the current frame + if(toggle_single_frame.get_active()) + rend_desc.set_time(canvas_interface_->get_time()); + + target->set_rend_desc(&rend_desc); + target->set_quality((int)adjustment_quality.get_value()); + if( !target->init() ){ + canvas_interface_->get_ui_interface()->error(_("Target initialization failure")); + return; + } + + canvas_interface_->get_ui_interface()->task(_("Rendering ")+filename); + + if(async_renderer) + { + async_renderer->stop(); + async_renderer.detach(); + } + async_renderer=new AsyncRenderer(target); + async_renderer->signal_finished().connect( sigc::mem_fun(*this,&RenderSettings::on_finished)); + async_renderer->start(); + /* + if(!target->render(canvas_interface_->get_ui_interface().get())) + { + canvas_interface_->get_ui_interface()->error(_("Render Failure")); + canvas_interface_->get_ui_interface()->amount_complete(0,10000); + return; + } + + // Success! + canvas_interface_->get_ui_interface()->task(filename+_(" rendered successfully")); + canvas_interface_->get_ui_interface()->amount_complete(0,10000); + */ + return; +} + +void +RenderSettings::on_finished() +{ + canvas_interface_->get_ui_interface()->task(_("File rendered successfully")); + canvas_interface_->get_ui_interface()->amount_complete(0,10000); +} + +void +RenderSettings::on_cancel_pressed() +{ + hide(); +} + +void +RenderSettings::on_single_frame_toggle() +{ + if(toggle_single_frame.get_active()) + widget_rend_desc.disable_time_section(); + else + widget_rend_desc.enable_time_section(); +} diff --cc synfig-studio/src/gui/render.h index 729251b,0000000..ac26cbc mode 100644,000000..100644 --- a/synfig-studio/src/gui/render.h +++ b/synfig-studio/src/gui/render.h @@@ -1,108 -1,0 +1,109 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file gtkmm/render.h +** \brief Template Header +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 Chris Moore +** +** 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 +*/ +/* ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __SYNFIG_STUDIO_GTKMM_RENDER_H +#define __SYNFIG_STUDIO_GTKMM_RENDER_H + +/* === H E A D E R S ======================================================= */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "renddesc.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +namespace studio +{ +class AsyncRenderer; + +class RenderSettings : public Gtk::Dialog +{ + Gtk::Tooltips tooltips; + + etl::handle canvas_interface_; + Widget_RendDesc widget_rend_desc; + + Gtk::Entry entry_filename; + + Gtk::Adjustment adjustment_quality; + Gtk::SpinButton entry_quality; + + Gtk::Adjustment adjustment_antialias; + Gtk::SpinButton entry_antialias; + + Gtk::CheckButton toggle_single_frame; + + Gtk::OptionMenu optionmenu_target; + Gtk::Menu *menu_target; ++ Gtk::Button *tparam_button; + + synfig::String target_name; + + void set_target(synfig::String name); + + etl::handle async_renderer; + + synfig::TargetParam tparam; + +public: + RenderSettings(Gtk::Window& parent,etl::handle canvas_interface); + ~RenderSettings(); + void set_entry_filename(); + +private: + + void on_rend_desc_changed(); + void on_single_frame_toggle(); + void on_choose_pressed(); + void on_render_pressed(); + void on_cancel_pressed(); + void on_targetparam_pressed(); + + void on_finished(); +}; // END of class RenderSettings + +}; // END of namespace studio + + +/* === E N D =============================================================== */ + +#endif diff --cc synfig-studio/src/gui/splash.cpp index fe87f01,0000000..d952fd1 mode 100644,000000..100644 --- a/synfig-studio/src/gui/splash.cpp +++ b/synfig-studio/src/gui/splash.cpp @@@ -1,252 -1,0 +1,258 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file splash.cpp +** \brief writeme +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 Chris Moore +** Copyright (c) 2008 Paul Wise +** +** 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 +** +** === N O T E S =========================================================== +** +** ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "splash.h" +#include "app.h" + +#include "general.h" + +#endif + +using namespace std; +using namespace etl; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +#ifndef VERSION +#define VERSION "unknown" +#define PACKAGE "synfigstudio" +#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 "png" +#endif + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +class studio::SplashProgress : public synfig::ProgressCallback +{ + Splash &splash; + +public: + + SplashProgress(Splash &splash):splash(splash) { } + + virtual bool task(const std::string &task) + { + if(splash.tasklabel) + { + splash.tasklabel->set_label(task); + splash.tasklabel->show(); + } + else + { + cerr<set_label(_("ERROR:")+task); + splash.tasklabel->show(); + } + else + { + cerr<set_label(_("WARNING:")+task); + splash.tasklabel->show(); + } + else + { + cerr<set_fraction((float)current/(float)total); + splash.progressbar->show(); + } + else + cerr<set(imagepath+"splash_screen."IMAGE_EXT); ++ srand(time(NULL)); ++ const float ran = rand()/float(RAND_MAX); ++ int number = 1; ++ if(ran >0.499999) ++ number = 2; ++ //synfig::info("%s", strprintf("%d",number).c_str()); ++ splash_image->set(imagepath+"splash_screen"+strprintf("%d",number)+"."IMAGE_EXT); + splash_image->set_alignment(0.5,0.5); + splash_image->set_padding(0,0); + + // Get the image size + int image_w = 350; int image_h = 0; + Glib::RefPtr pixbuf = splash_image->get_pixbuf(); + if( pixbuf ){ + image_w = pixbuf->get_width(); + image_h = pixbuf->get_height(); + } + + // Create the progress bar + progressbar = manage(new class Gtk::ProgressBar()); + progressbar->set_size_request(image_w,24); + + // Create the current task label + tasklabel = manage(new class Gtk::Label()); + tasklabel->set_size_request(image_w,24); + tasklabel->set_use_underline(false); + + // Create the Gtk::Fixed container and put all of the widgets into it + Gtk::Fixed* fixed = manage(new class Gtk::Fixed()); + if( pixbuf ) fixed->put(*splash_image, 0, 0); + fixed->put(*progressbar, 0, image_h+24); + fixed->put(*tasklabel, 0, image_h); + + // Create shadow around the outside of the window + Gtk::Frame* frame = manage(new class Gtk::Frame()); + frame->set_shadow_type(Gtk::SHADOW_OUT); + frame->add(*fixed); + + // Set up the parameters for this pop-up window + set_title("Synfig Studio "VERSION); + set_modal(false); + property_window_position().set_value(Gtk::WIN_POS_CENTER); + set_resizable(false); + set_type_hint(Gdk::WINDOW_TYPE_HINT_SPLASHSCREEN); + set_auto_startup_notification(false); + try { + set_icon_from_file(imagepath+"synfig_icon."+IMAGE_EXT); + } catch(...) { + synfig::warning("Unable to open "+imagepath+"synfig_icon."+IMAGE_EXT); + } + add(*frame); + + // show everything off + if( pixbuf ) splash_image->show(); + fixed->show(); + frame->show(); + + // Once the splash is shown, we want startup stuff to continue as normal + signal_map().connect(sigc::mem_fun(*this, &Splash::enable_startup_notification)); + + cb=new SplashProgress(*this); +} + +Splash::~Splash() +{ + delete cb; +} + +synfig::ProgressCallback * +Splash::get_callback() +{ + return cb; +} + +void +Splash::enable_startup_notification(){ + set_auto_startup_notification(true); +} diff --cc synfig-studio/src/gui/states/state_mirror.cpp index 2b1eb0a,0000000..3f7786b mode 100644,000000..100644 --- a/synfig-studio/src/gui/states/state_mirror.cpp +++ b/synfig-studio/src/gui/states/state_mirror.cpp @@@ -1,336 -1,0 +1,354 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file state_mirror.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2009 Nikita Kitaev +** +** 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 + +#include +#include + +#include "state_mirror.h" +#include "state_normal.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" + +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include "docks/dialog_tooloptions.h" +#include +#include "duck.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +enum Axis { + AXIS_X, + AXIS_Y +} ; + +/* === G L O B A L S ======================================================= */ + +StateMirror studio::state_mirror; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_Mirror : public DuckDrag_Base +{ + synfig::Vector center; + + std::vector positions; + +public: + Axis axis; + + DuckDrag_Mirror(); + void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin); + bool end_duck_drag(Duckmatic* duckmatic); + void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector); +}; + +class studio::StateMirror_Context : public sigc::trackable +{ + etl::handle canvas_view_; + CanvasView::IsWorking is_working; + - synfigapp::Settings& settings; - - sigc::connection keypress_connect; - sigc::connection keyrelease_connect; - + etl::handle duck_dragger_; + + Gtk::Table options_table; + ++ ++ sigc::connection keypress_connect; ++ sigc::connection keyrelease_connect; ++ bool shift_is_pressed; + Gtk::RadioButton::Group radiobutton_group; + Gtk::RadioButton radiobutton_axis_x; + Gtk::RadioButton radiobutton_axis_y; + +public: + + Axis get_axis()const { return radiobutton_axis_x.get_active()?AXIS_X:AXIS_Y; } + void set_axis(Axis a) + { + if(a==AXIS_X) + radiobutton_axis_x.set_active(true); + else + radiobutton_axis_y.set_active(true); + + duck_dragger_->axis=get_axis(); + } + + void update_axes() + { + duck_dragger_->axis=get_axis(); + get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW); + } + ++ ++ ++ + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); ++ Smach::event_result event_mouse_motion_handler(const Smach::event& x); + + void refresh_tool_options(); + + StateMirror_Context(CanvasView* canvas_view); + + ~StateMirror_Context(); + + const etl::handle& get_canvas_view()const{return canvas_view_;} + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} + synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} + WorkArea * get_work_area()const{return canvas_view_->get_work_area();} + - void load_settings(); - void save_settings(); ++ bool key_press_event(GdkEventKey *event); ++ bool key_release_event(GdkEventKey *event); ++ + - bool key_event(GdkEventKey *event); +}; // END of class StateMirror_Context + +/* === M E T H O D S ======================================================= */ + +StateMirror::StateMirror(): + Smach::state("mirror") +{ + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateMirror_Context::event_refresh_tool_options)); + insert(event_def(EVENT_STOP,&StateMirror_Context::event_stop_handler)); ++ insert(event_def(EVENT_WORKAREA_MOUSE_MOTION, &StateMirror_Context::event_mouse_motion_handler)); ++ insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG, &StateMirror_Context::event_mouse_motion_handler)); +} + +StateMirror::~StateMirror() +{ +} + - void - StateMirror_Context::load_settings() - { - String value; - - settings.get_value("mirror.axis",value); - set_axis((Axis)atoi(value.c_str())); - } - - void - StateMirror_Context::save_settings() - { - settings.set_value("mirror.lock_aspect",strprintf("%d",(int)get_axis())); - } - +StateMirror_Context::StateMirror_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), + is_working(*canvas_view), - settings(synfigapp::Main::get_selected_input_device()->settings()), + duck_dragger_(new DuckDrag_Mirror()), + radiobutton_axis_x(radiobutton_group,_("Horizontal")), + radiobutton_axis_y(radiobutton_group,_("Vertical")) +{ + // Set up the tool options dialog + options_table.attach(*manage(new Gtk::Label(_("Mirror Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(radiobutton_axis_x, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(radiobutton_axis_y, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + options_table.attach(*manage(new Gtk::Label(_("(Shift key toggles axis)"))), 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + radiobutton_axis_x.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes)); + radiobutton_axis_y.signal_toggled().connect(sigc::mem_fun(*this,&StateMirror_Context::update_axes)); ++ shift_is_pressed=false; ++ keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_press_event),false); ++ keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_release_event),false); + + options_table.show_all(); + refresh_tool_options(); + App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + - keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false); - keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateMirror_Context::key_event),false); - + get_work_area()->set_cursor(Gdk::SB_H_DOUBLE_ARROW); +// get_work_area()->reset_cursor(); + + App::toolbox->refresh(); + - set_axis(AXIS_X); - load_settings(); ++ set_axis(AXIS_Y); +} + +bool - StateMirror_Context::key_event(GdkEventKey *event) ++StateMirror_Context::key_press_event(GdkEventKey *event) +{ + if (event->keyval==GDK_Shift_L || event->keyval==GDK_Shift_R ) + { ++ if (shift_is_pressed) return false; ++ shift_is_pressed=true; + set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X); - get_work_area()->set_cursor(get_axis() == AXIS_X?Gdk::SB_H_DOUBLE_ARROW:Gdk::SB_V_DOUBLE_ARROW); ++ update_axes(); ++ } ++ ++ return false; //Pass on the event to other handlers, just in case ++} ++ ++bool ++StateMirror_Context::key_release_event(GdkEventKey *event) ++{ ++ if (event->keyval==GDK_Shift_L || event->keyval==GDK_Shift_R ) ++ { ++ if (!shift_is_pressed) return false; ++ shift_is_pressed = false; ++ set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X); ++ update_axes(); + } + + return false; //Pass on the event to other handlers, just in case +} + +void +StateMirror_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); + App::dialog_tool_options->set_local_name(_("Mirror Tool")); + App::dialog_tool_options->set_name("mirror"); +} + +Smach::event_result +StateMirror_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateMirror_Context::event_stop_handler(const Smach::event& /*x*/) +{ + throw &state_normal; + return Smach::RESULT_OK; +} + - StateMirror_Context::~StateMirror_Context() ++Smach::event_result ++StateMirror_Context::event_mouse_motion_handler(const Smach::event& x) +{ - save_settings(); ++ // synfig::info("STATE NORMAL: Received mouse button down Event"); ++ ++ const EventMouse& event(*reinterpret_cast(&x)); ++ bool shift_state = event.modifier&GDK_SHIFT_MASK; ++ if (shift_state != shift_is_pressed) ++ { ++ shift_is_pressed = !shift_is_pressed; ++ set_axis(get_axis()==AXIS_X ? AXIS_Y:AXIS_X); ++ } + ++ return Smach::RESULT_OK; ++} ++ ++StateMirror_Context::~StateMirror_Context() ++{ + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + + keypress_connect.disconnect(); + keyrelease_connect.disconnect(); + + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + +DuckDrag_Mirror::DuckDrag_Mirror(): + axis(AXIS_X) +{ +} + +#ifndef EPSILON +#define EPSILON 0.0000001 +#endif + +void +DuckDrag_Mirror::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& /*offset*/) +{ + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + positions.clear(); + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + Point p((*iter)->get_trans_point()); + positions.push_back(p); + } + +} + +void +DuckDrag_Mirror::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + center=vector; + int i; + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + Time time(duckmatic->get_time()); + + // do the Vertex and Position ducks first + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + if ((*iter)->get_type() == Duck::TYPE_VERTEX || + (*iter)->get_type() == Duck::TYPE_POSITION) + { + Vector p(positions[i]); + + if (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0]; + else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1]; + + (*iter)->set_trans_point(p); + } + + // then do the other ducks + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + if ((*iter)->get_type() != Duck::TYPE_VERTEX && + (*iter)->get_type() != Duck::TYPE_POSITION) + { + // we don't need to mirror radius ducks - they're one-dimensional + if ((*iter)->is_radius()) + continue; + + Vector p(positions[i]); + + if (axis==AXIS_X) p[0] = -(p[0]-center[0]) + center[0]; + else if (axis==AXIS_Y) p[1] = -(p[1]-center[1]) + center[1]; + + (*iter)->set_trans_point(p); + } +} + +bool +DuckDrag_Mirror::end_duck_drag(Duckmatic* duckmatic) +{ + duckmatic->signal_edited_selected_ducks(); + return true; +} diff --cc synfig-studio/src/gui/states/state_normal.cpp index 723ca90,0000000..f71af5b mode 100644,000000..100644 --- a/synfig-studio/src/gui/states/state_normal.cpp +++ b/synfig-studio/src/gui/states/state_normal.cpp @@@ -1,824 -1,0 +1,767 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file state_normal.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2009 Nikita Kitaev +** +** 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 + +#include +#include +#include +#include +#include +#include + +#include "state_normal.h" +#include "canvasview.h" +#include "workarea.h" +#include "app.h" + +#include +#include "event_mouse.h" +#include "event_layerclick.h" +#include "toolbox.h" +#include "docks/dialog_tooloptions.h" +#include +#include "duck.h" +#include +#include + +#include "general.h" +#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 EPSILON +#define EPSILON 0.0000001 +#endif + +/* === G L O B A L S ======================================================= */ + +StateNormal studio::state_normal; + +/* === C L A S S E S & S T R U C T S ======================================= */ + +class DuckDrag_Combo : public DuckDrag_Base +{ + synfig::Vector last_move; + synfig::Vector drag_offset; + synfig::Vector center; + synfig::Vector snap; + + synfig::Angle original_angle; + synfig::Real original_mag; + + std::vector last_; + std::vector positions; + + + bool bad_drag; + bool move_only; + +public: + CanvasView* canvas_view_; + bool scale; + bool rotate; + bool constrain; + DuckDrag_Combo(); + void begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& begin); + bool end_duck_drag(Duckmatic* duckmatic); + void duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector); + + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} +}; + + +class studio::StateNormal_Context : public sigc::trackable +{ + CanvasView* canvas_view_; + - synfigapp::Settings& settings; - - sigc::connection keypress_connect; - sigc::connection keyrelease_connect; - + etl::handle duck_dragger_; + + Gtk::Table options_table; + - Gtk::CheckButton checkbutton_rotate; - Gtk::CheckButton checkbutton_scale; - Gtk::CheckButton checkbutton_constrain; - +public: + - bool get_rotate_flag()const { return checkbutton_rotate.get_active(); } - void set_rotate_flag(bool x) { checkbutton_rotate.set_active(x); refresh_rotate_flag(); } - void refresh_rotate_flag() { if(duck_dragger_)duck_dragger_->rotate=get_rotate_flag(); } ++ void refresh_cursor(); ++ ++ bool get_rotate_flag()const { if(duck_dragger_) return duck_dragger_->rotate; else return false; } ++ void set_rotate_flag(bool x) { if(duck_dragger_ && x!=duck_dragger_->rotate) ++ {duck_dragger_->rotate=x; refresh_cursor();} } + - bool get_scale_flag()const { return checkbutton_scale.get_active(); } - void set_scale_flag(bool x) { checkbutton_scale.set_active(x); refresh_scale_flag(); } - void refresh_scale_flag() { if(duck_dragger_)duck_dragger_->scale=get_scale_flag(); } ++ bool get_scale_flag()const { if(duck_dragger_) return duck_dragger_->scale; else return false; } ++ void set_scale_flag(bool x) { if(duck_dragger_ && x!=duck_dragger_->scale) ++ {duck_dragger_->scale=x; refresh_cursor();} } + - bool get_constrain_flag()const { return checkbutton_constrain.get_active(); } - void set_constrain_flag(bool x) { checkbutton_constrain.set_active(x); refresh_constrain_flag(); } - void refresh_constrain_flag() { if(duck_dragger_)duck_dragger_->constrain=get_constrain_flag(); } ++ bool get_constrain_flag()const { if(duck_dragger_) return duck_dragger_->constrain; else return false; } ++ void set_constrain_flag(bool x) { if(duck_dragger_ && x!=duck_dragger_->constrain) ++ {duck_dragger_->constrain=x; refresh_cursor();} } + + StateNormal_Context(CanvasView* canvas_view); + + ~StateNormal_Context(); + + CanvasView* get_canvas_view()const{return canvas_view_;} + etl::handle get_canvas_interface()const{return canvas_view_->canvas_interface();} + synfig::Canvas::Handle get_canvas()const{return canvas_view_->get_canvas();} + WorkArea * get_work_area()const{return canvas_view_->get_work_area();} + - void load_settings(); - void save_settings(); - - bool key_pressed(GdkEventKey *event); - bool key_released(GdkEventKey *event); - + Smach::event_result event_stop_handler(const Smach::event& x); + Smach::event_result event_refresh_handler(const Smach::event& x); + Smach::event_result event_refresh_ducks_handler(const Smach::event& x); + Smach::event_result event_undo_handler(const Smach::event& x); + Smach::event_result event_redo_handler(const Smach::event& x); + Smach::event_result event_mouse_button_down_handler(const Smach::event& x); + Smach::event_result event_multiple_ducks_clicked_handler(const Smach::event& x); ++ Smach::event_result event_mouse_motion_handler(const Smach::event& x); + Smach::event_result event_refresh_tool_options(const Smach::event& x); + void refresh_tool_options(); + Smach::event_result event_layer_click(const Smach::event& x); + + +}; // END of class StateNormal_Context + +/* === M E T H O D S ======================================================= */ + +StateNormal::StateNormal(): + Smach::state("normal") +{ + insert(event_def(EVENT_STOP,&StateNormal_Context::event_stop_handler)); + insert(event_def(EVENT_REFRESH,&StateNormal_Context::event_refresh_handler)); + insert(event_def(EVENT_REFRESH_DUCKS,&StateNormal_Context::event_refresh_ducks_handler)); + insert(event_def(EVENT_UNDO,&StateNormal_Context::event_undo_handler)); + insert(event_def(EVENT_REDO,&StateNormal_Context::event_redo_handler)); + insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DOWN,&StateNormal_Context::event_mouse_button_down_handler)); + insert(event_def(EVENT_WORKAREA_MULTIPLE_DUCKS_CLICKED,&StateNormal_Context::event_multiple_ducks_clicked_handler)); + insert(event_def(EVENT_REFRESH_TOOL_OPTIONS,&StateNormal_Context::event_refresh_tool_options)); ++ insert(event_def(EVENT_WORKAREA_MOUSE_MOTION, &StateNormal_Context::event_mouse_motion_handler)); ++ insert(event_def(EVENT_WORKAREA_MOUSE_BUTTON_DRAG, &StateNormal_Context::event_mouse_motion_handler)); + insert(event_def(EVENT_WORKAREA_LAYER_CLICKED,&StateNormal_Context::event_layer_click)); + +} + +StateNormal::~StateNormal() +{ +} + - void - StateNormal_Context::load_settings() ++void StateNormal_Context::refresh_cursor() +{ - String value; - - if(settings.get_value("normal.rotate",value) && value=="1") - set_rotate_flag(true); - else - set_rotate_flag(false); - - if(settings.get_value("normal.scale",value) && value=="1") - set_scale_flag(true); - else - set_scale_flag(false); - - if(settings.get_value("normal.constrain",value) && value=="1") - set_constrain_flag(true); - else - set_constrain_flag(false); ++ // Check the current state and return when applicable ++ synfig::String sname; ++ sname=get_canvas_view()->get_smach().get_state_name(); ++ if (sname!="normal") ++ return; ++ ++ // Change the cursor based on key flags ++ if(get_rotate_flag() && !get_scale_flag()) ++ { ++ get_work_area()->set_cursor(Gdk::EXCHANGE); ++ return; ++ } ++ if(!get_rotate_flag() && get_scale_flag()) ++ { ++ get_work_area()->set_cursor(Gdk::SIZING); ++ return; ++ } ++ if(get_rotate_flag() && get_scale_flag()) ++ { ++ get_work_area()->set_cursor(Gdk::CROSSHAIR); ++ return; ++ } + - } ++ // Default cursor for Transform tool ++ get_work_area()->set_cursor(Gdk::ARROW); + - void - StateNormal_Context::save_settings() - { - settings.set_value("normal.rotate",get_rotate_flag()?"1":"0"); - settings.set_value("normal.scale",get_scale_flag()?"1":"0"); - settings.set_value("normal.constrain",get_constrain_flag()?"1":"0"); +} + +StateNormal_Context::StateNormal_Context(CanvasView* canvas_view): + canvas_view_(canvas_view), - settings(synfigapp::Main::get_selected_input_device()->settings()), - duck_dragger_(new DuckDrag_Combo()), - checkbutton_rotate(_("Rotate (Ctrl)")), - checkbutton_scale(_("Scale (Alt)")), - checkbutton_constrain(_("Constrain (Shift)")) ++ duck_dragger_(new DuckDrag_Combo()) +{ + duck_dragger_->canvas_view_=get_canvas_view(); + + // Set up the tool options dialog - options_table.attach(*manage(new Gtk::Label(_("Normal Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_rotate, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_scale, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - options_table.attach(checkbutton_constrain, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - - checkbutton_rotate.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_rotate_flag)); - checkbutton_scale.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_scale_flag)); - checkbutton_constrain.signal_toggled().connect(sigc::mem_fun(*this,&StateNormal_Context::refresh_constrain_flag)); - ++ options_table.attach(*manage(new Gtk::Label(_("Transform Tool"))), 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); ++ options_table.attach(*manage(new Gtk::Label(_("Ctrl to rotate"), Gtk::ALIGN_LEFT)), 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); ++ options_table.attach(*manage(new Gtk::Label(_("Alt to scale"), Gtk::ALIGN_LEFT)), 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); ++ options_table.attach(*manage(new Gtk::Label(_("Shift to constrain"), Gtk::ALIGN_LEFT)), 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + + options_table.show_all(); + refresh_tool_options(); + //App::dialog_tool_options->set_widget(options_table); + //App::dialog_tool_options->present(); + + get_work_area()->set_allow_layer_clicks(true); + get_work_area()->set_duck_dragger(duck_dragger_); + - keypress_connect=get_work_area()->signal_key_press_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_pressed),false); - keyrelease_connect=get_work_area()->signal_key_release_event().connect(sigc::mem_fun(*this,&StateNormal_Context::key_released),false); - + //these will segfault +// get_work_area()->set_cursor(Gdk::CROSSHAIR); +// get_work_area()->reset_cursor(); + + App::toolbox->refresh(); - - load_settings(); - refresh_scale_flag(); - } - - bool - StateNormal_Context::key_pressed(GdkEventKey *event) - { - switch(event->keyval) - { - case GDK_Control_L: - case GDK_Control_R: - set_rotate_flag(true); - break; - case GDK_Alt_L: - case GDK_Alt_R: - set_scale_flag(true); - break; - case GDK_Shift_L: - case GDK_Shift_R: - set_constrain_flag(true); - break; - default: - break; - } - return false; //Pass on the event to other handlers, just in case - } - - bool - StateNormal_Context::key_released(GdkEventKey *event) - { - switch(event->keyval) - { - case GDK_Control_L: - case GDK_Control_R: - set_rotate_flag(false); - break; - case GDK_Alt_L: - case GDK_Alt_R: - set_scale_flag(false); - break; - case GDK_Shift_L: - case GDK_Shift_R: - set_constrain_flag(false); - break; - default: - break; - } - return false; //Pass on the event to other handlers +} + +void +StateNormal_Context::refresh_tool_options() +{ + App::dialog_tool_options->clear(); + App::dialog_tool_options->set_widget(options_table); - App::dialog_tool_options->set_local_name(_("Normal Tool")); ++ App::dialog_tool_options->set_local_name(_("Transform Tool")); + App::dialog_tool_options->set_name("normal"); +} + + + +StateNormal_Context::~StateNormal_Context() +{ - save_settings(); - + get_work_area()->clear_duck_dragger(); + get_work_area()->reset_cursor(); + - keypress_connect.disconnect(); - keyrelease_connect.disconnect(); - + App::dialog_tool_options->clear(); + + App::toolbox->refresh(); +} + +DuckDrag_Combo::DuckDrag_Combo(): + scale(false), + rotate(false), - constrain(false) // Lock aspect for scale; smooth move for translate ++ constrain(false) // Lock aspect for scale +{ +} + +void +DuckDrag_Combo::begin_duck_drag(Duckmatic* duckmatic, const synfig::Vector& offset) +{ + last_move=Vector(1,1); + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + bad_drag=false; + + drag_offset=duckmatic->find_duck(offset)->get_trans_point(); + + //snap=drag_offset-duckmatic->snap_point_to_grid(drag_offset); + //snap=offset-drag_offset_; + snap=Vector(0,0); + + // Calculate center + Point vmin(100000000,100000000); + Point vmax(-100000000,-100000000); + //std::set >::iterator iter; + positions.clear(); + int i; + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + Point p((*iter)->get_trans_point()); + vmin[0]=min(vmin[0],p[0]); + vmin[1]=min(vmin[1],p[1]); + vmax[0]=max(vmax[0],p[0]); + vmax[1]=max(vmax[1],p[1]); + positions.push_back(p); + } + center=(vmin+vmax)*0.5; + if((vmin-vmax).mag()<=EPSILON) + move_only=true; + else + move_only=false; + + + synfig::Vector vect(offset-center); + original_angle=Angle::tan(vect[1],vect[0]); + original_mag=vect.mag(); +} + + +void +DuckDrag_Combo::duck_drag(Duckmatic* duckmatic, const synfig::Vector& vector) +{ + if (!duckmatic) return; + + if(bad_drag) + return; + + //Override axis lock set in workarea when holding down the shift key + if (!move_only && (scale || rotate)) + duckmatic->set_axis_lock(false); + + synfig::Vector vect; + if (move_only || (!scale && !rotate)) + vect= duckmatic->snap_point_to_grid(vector)-drag_offset+snap; + else + vect= duckmatic->snap_point_to_grid(vector)-center+snap; + + last_move=vect; + + const DuckList selected_ducks(duckmatic->get_selected_ducks()); + DuckList::const_iterator iter; + + Time time(duckmatic->get_time()); + + int i; + if( move_only || (!scale && !rotate) ) + { + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if((*iter)->get_type()==Duck::TYPE_VERTEX || (*iter)->get_type()==Duck::TYPE_POSITION) + (*iter)->set_trans_point(positions[i]+vect, time); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION) + (*iter)->set_trans_point(positions[i]+vect, time); + } + } + + if (rotate) + { + Angle::deg angle(Angle::tan(vect[1],vect[0])); + angle=original_angle-angle; + if (constrain) + { + float degrees = angle.get()/15; + angle= Angle::deg (degrees>0?std::floor(degrees)*15:std::ceil(degrees)*15); + } + Real mag(vect.mag()/original_mag); + Real sine(Angle::sin(angle).get()); + Real cosine(Angle::cos(angle).get()); + + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION)continue; + + Vector x(positions[i]-center),p; + + p[0]=cosine*x[0]+sine*x[1]; + p[1]=-sine*x[0]+cosine*x[1]; + if(scale)p*=mag; + p+=center; + (*iter)->set_trans_point(p, time); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector x(positions[i]-center),p; + + p[0]=cosine*x[0]+sine*x[1]; + p[1]=-sine*x[0]+cosine*x[1]; + if(scale)p*=mag; + p+=center; + (*iter)->set_trans_point(p, time); + } + } else if (scale) + { + if(!constrain) + { + if(abs(drag_offset[0]-center[0])>EPSILON) + vect[0]/=drag_offset[0]-center[0]; + else + vect[0]=1; + if(abs(drag_offset[1]-center[1])>EPSILON) + vect[1]/=drag_offset[1]-center[1]; + else + vect[1]=1; + } + else + { - //vect[0]=vect[1]=vect.mag()*0.707106781; - Real amount(vect.mag()/(drag_offset-center).mag()); ++ Real amount; ++ if((drag_offset-center).mag() < EPSILON) ++ amount = 1; ++ else ++ amount = vect.mag()/(drag_offset-center).mag(); ++ + vect[0]=vect[1]=amount; + } + + if(vect[0]-EPSILON) + vect[0]=1; + if(vect[1]-EPSILON) + vect[1]=1; + + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p, time); + } + for(i=0,iter=selected_ducks.begin();iter!=selected_ducks.end();++iter,i++) + { + if(!((*iter)->get_type()!=Duck::TYPE_VERTEX&&(*iter)->get_type()!=Duck::TYPE_POSITION))continue; + + Vector p(positions[i]-center); + + p[0]*=vect[0]; + p[1]*=vect[1]; + p+=center; + (*iter)->set_trans_point(p, time); + } ++ + } + + // then patch up the tangents for the vertices we've moved + duckmatic->update_ducks(); + + last_move=vect; +} + +bool +DuckDrag_Combo::end_duck_drag(Duckmatic* duckmatic) +{ + if(bad_drag)return false; + + //synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Rotate Ducks")); + + if((last_move-Vector(1,1)).mag()>0.0001) + { + duckmatic->signal_edited_selected_ducks(); + return true; + } + else + { + duckmatic->signal_user_click_selected_ducks(0); + return false; + } +} + +Smach::event_result +StateNormal_Context::event_refresh_tool_options(const Smach::event& /*x*/) +{ + refresh_tool_options(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_stop_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Stop Event"); + canvas_view_->stop(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_refresh_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Refresh Event"); + canvas_view_->rebuild_tables(); + canvas_view_->work_area->queue_render_preview(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_refresh_ducks_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Refresh Ducks"); + canvas_view_->queue_rebuild_ducks(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_undo_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Undo Event"); + canvas_view_->get_instance()->undo(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_redo_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received Redo Event"); + canvas_view_->get_instance()->redo(); + return Smach::RESULT_ACCEPT; +} + +Smach::event_result +StateNormal_Context::event_mouse_button_down_handler(const Smach::event& x) +{ + // synfig::info("STATE NORMAL: Received mouse button down Event"); + + const EventMouse& event(*reinterpret_cast(&x)); + + switch(event.button) + { + case BUTTON_RIGHT: + canvas_view_->popup_main_menu(); + return Smach::RESULT_ACCEPT; + default: + return Smach::RESULT_OK; + } +} + +Smach::event_result ++StateNormal_Context::event_mouse_motion_handler(const Smach::event& x) ++{ ++ // synfig::info("STATE NORMAL: Received mouse button down Event"); ++ ++ const EventMouse& event(*reinterpret_cast(&x)); ++ ++ set_rotate_flag(event.modifier&GDK_CONTROL_MASK); ++ set_scale_flag(event.modifier&GDK_MOD1_MASK); ++ set_constrain_flag(event.modifier&GDK_SHIFT_MASK); ++ ++ return Smach::RESULT_OK; ++} ++ ++Smach::event_result +StateNormal_Context::event_layer_click(const Smach::event& x) +{ + const EventLayerClick& event(*reinterpret_cast(&x)); + + if(event.layer) + { + // synfig::info("STATE NORMAL: Received layer click Event, \"%s\"",event.layer->get_name().c_str()); + } + else + { + // synfig::info("STATE NORMAL: Received layer click Event with an empty layer."); + } + + switch(event.button) + { + case BUTTON_LEFT: + if(!(event.modifier&Gdk::CONTROL_MASK)) + canvas_view_->get_selection_manager()->clear_selected_layers(); + if(event.layer) + { + std::list layer_list(canvas_view_->get_selection_manager()->get_selected_layers()); + std::set layers(layer_list.begin(),layer_list.end()); + if(layers.count(event.layer)) + { + layers.erase(event.layer); + layer_list=std::list(layers.begin(),layers.end()); + canvas_view_->get_selection_manager()->clear_selected_layers(); + canvas_view_->get_selection_manager()->set_selected_layers(layer_list); + } + else + { + canvas_view_->get_selection_manager()->set_selected_layer(event.layer); + } + } + return Smach::RESULT_ACCEPT; + case BUTTON_RIGHT: + canvas_view_->popup_layer_menu(event.layer); + return Smach::RESULT_ACCEPT; + default: + return Smach::RESULT_OK; + } +} + +/* +void +StateNormal_Context::edit_several_waypoints(std::list value_desc_list) +{ + Gtk::Dialog dialog( + "Edit Multiple Waypoints", // Title + true, // Modal + true // use_separator + ); + + Widget_WaypointModel widget_waypoint_model; + widget_waypoint_model.show(); + + dialog.get_vbox()->pack_start(widget_waypoint_model); + + + dialog.add_button(Gtk::StockID("gtk-apply"),1); + dialog.add_button(Gtk::StockID("gtk-cancel"),0); + dialog.show(); + + if(dialog.run()==0) + return; + synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Set Waypoints")); + + std::list::iterator iter; + for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter) + { + synfigapp::ValueDesc value_desc(*iter); + + if(!value_desc.is_valid()) + continue; + + ValueNode_Animated::Handle value_node; + + // If this value isn't a ValueNode_Animated, but + // it is somewhat constant, then go ahead and convert + // it to a ValueNode_Animated. + if(!value_desc.is_value_node() || ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())) + { + ValueBase value; + if(value_desc.is_value_node()) + value=ValueNode_Const::Handle::cast_dynamic(value_desc.get_value_node())->get_value(); + else + value=value_desc.get_value(); + + value_node=ValueNode_Animated::create(value,get_canvas()->get_time()); + + synfigapp::Action::Handle action; + + if(!value_desc.is_value_node()) + { + action=synfigapp::Action::create("ValueDescConnect"); + action->set_param("dest",value_desc); + action->set_param("src",ValueNode::Handle(value_node)); + } + else + { + action=synfigapp::Action::create("ValueNodeReplace"); + action->set_param("dest",value_desc.get_value_node()); + action->set_param("src",ValueNode::Handle(value_node)); + } + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to convert to animated waypoint")); + group.cancel(); + return; + } + } + else + { + if(value_desc.is_value_node()) + value_node=ValueNode_Animated::Handle::cast_dynamic(value_desc.get_value_node()); + } + + + if(value_node) + { + + synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSetSmart")); + + if(!action) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to find WaypointSetSmart action")); + group.cancel(); + return; + } + + + action->set_param("canvas",get_canvas()); + action->set_param("canvas_interface",get_canvas_interface()); + action->set_param("value_node",ValueNode::Handle(value_node)); + action->set_param("time",get_canvas()->get_time()); + action->set_param("model",widget_waypoint_model.get_waypoint_model()); + + if(!get_canvas_interface()->get_instance()->perform_action(action)) + { + get_canvas_view()->get_ui_interface()->error(_("Unable to set a specific waypoint")); + group.cancel(); + return; + } + } + else + { + //get_canvas_view()->get_ui_interface()->error(_("Unable to animate a specific valuedesc")); + //group.cancel(); + //return; + } + + } +} +*/ + +Smach::event_result +StateNormal_Context::event_multiple_ducks_clicked_handler(const Smach::event& /*x*/) +{ + // synfig::info("STATE NORMAL: Received multiple duck click event"); + + //const EventMouse& event(*reinterpret_cast(&x)); + + std::list value_desc_list; + + // Create a list of value_descs associated with selection + const DuckList selected_ducks(get_work_area()->get_selected_ducks()); + DuckList::const_iterator iter; + for(iter=selected_ducks.begin();iter!=selected_ducks.end();++iter) + { + synfigapp::ValueDesc value_desc((*iter)->get_value_desc()); + + if(!value_desc.is_valid()) + continue; + + if(value_desc.get_value_type()==ValueBase::TYPE_BLINEPOINT && value_desc.is_value_node() && ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node())) + { + value_desc_list.push_back( + synfigapp::ValueDesc( + ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()) + ,ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node()) + ->get_link_index_from_name("point") + ) + ); + } + else + value_desc_list.push_back(value_desc); + } + + Gtk::Menu *menu=manage(new Gtk::Menu()); + menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), menu)); + + canvas_view_->get_instance()->make_param_menu(menu,canvas_view_->get_canvas(),value_desc_list); + + /* + synfigapp::Action::ParamList param_list; + param_list=get_canvas_interface()->generate_param_list(value_desc_list); + + canvas_view_->add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_VALUEDESC|synfigapp::Action::CATEGORY_VALUENODE); + + menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Edit Waypoints"), + sigc::bind( + sigc::mem_fun( + *this, + &studio::StateNormal_Context::edit_several_waypoints + ), + value_desc_list + ) + )); + */ + menu->popup(3,gtk_get_current_event_time()); + + return Smach::RESULT_ACCEPT; +} + + diff --cc synfig-studio/src/gui/toolbox.cpp index 12a56a2,0000000..45d735a mode 100644,000000..100644 --- a/synfig-studio/src/gui/toolbox.cpp +++ b/synfig-studio/src/gui/toolbox.cpp @@@ -1,649 -1,0 +1,651 @@@ +/* === S Y N F I G ========================================================= */ +/*! \file toolbox.cpp +** \brief writeme +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2008 Paul Wise +** Copyright (c) 2009 Nikita Kitaev +** +** 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 +** +** === N O T E S =========================================================== +** +** ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "toolbox.h" +#include "instance.h" +#include "app.h" +#include "canvasview.h" +#include "dialogs/dialog_gradient.h" +#include "dialogs/dialog_color.h" +#include "docks/dialog_tooloptions.h" +#include "dialogs/dialog_preview.h" +#include "docks/dockable.h" +#include "docks/dockmanager.h" +#include "docks/dockdialog.h" + +#include "widgets/widget_defaults.h" + +#include + +#include "general.h" + +#endif + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; +using namespace sigc; + +/* === M A C R O S ========================================================= */ + +#define GRAB_HINT_DATA(y,default) { \ + String x; \ + if(synfigapp::Main::settings().get_value(String("pref.")+y+"_hints",x)) \ + { \ + set_type_hint((Gdk::WindowTypeHint)atoi(x.c_str())); \ + } else {\ + set_type_hint(default); \ + } \ + } + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +#define TOGGLE_TOOLBOX_BUTTON(button,stockid,tooltip) \ + button = manage(new class Gtk::ToggleButton()); \ + icon=manage(new Gtk::Image(Gtk::StockID(stockid),Gtk::IconSize(4))); \ + button->add(*icon); \ + tooltips.set_tip(*button,tooltip); \ + icon->show(); \ + button->show() + +#define TOOLBOX_BUTTON(button,stockid,tooltip) \ + button = manage(new class Gtk::Button()); \ + icon=manage(new Gtk::Image(Gtk::StockID(stockid),Gtk::IconSize(4))); \ + button->add(*icon); \ + tooltips.set_tip(*button,tooltip); \ + icon->show(); \ + button->show() + +#define ADD_TOOLBOX_BUTTON(button,stockid,tooltip) Gtk::Button *TOOLBOX_BUTTON(button,stockid,tooltip) + +void +save_selected_instance() +{ + if(!studio::App::get_selected_instance()) + { + App::dialog_error_blocking(_("Cannot save"),_("Nothing to save")); + return; + } + + studio::App::get_selected_instance()->save(); +} + +void +save_as_selected_instance() +{ + if(!studio::App::get_selected_instance()) + { + App::dialog_error_blocking(_("Cannot save as"),_("Nothing to save")); + return; + } + + studio::App::get_selected_instance()->dialog_save_as(); +} + +void +save_all() +{ + std::list >::iterator iter; + for(iter=App::instance_list.begin();iter!=App::instance_list.end();iter++) + (*iter)->save(); +} + +void +close_selected_instance() +{ + etl::handle instance=studio::App::get_selected_instance(); + + if(!instance) + { + App::dialog_error_blocking(_("Cannot close"),_("Nothing to close")); + return; + } + + instance->safe_close(); + + //assert(instance.unique()); +} + + +static void +show_dialog_input() +{ + App::dialog_input->present(); +} + +void _create_stock_dialog1() +{ + DockDialog* dock_dialog(new DockDialog); + dock_dialog->set_contents("canvases history"); + dock_dialog->set_composition_selector(true); + dock_dialog->present(); +} +void _create_stock_dialog2() +{ + DockDialog* dock_dialog(new DockDialog); + dock_dialog->set_contents("layers children keyframes | params"); + dock_dialog->present(); +} + +Toolbox::Toolbox(): + Gtk::Window(Gtk::WINDOW_TOPLEVEL), + dialog_settings(this,"toolbox") +{ + GRAB_HINT_DATA( + "toolbox", +//#ifdef __APPLE__ + Gdk::WINDOW_TYPE_HINT_NORMAL +//#else +// Gdk::WINDOW_TYPE_HINT_UTILITY +//#endif + ); + set_keep_above(false); + set_role("toolbox"); + + + + recent_files_menu= manage(new class Gtk::Menu()); + + Gtk::Menu *filemenu =manage(new class Gtk::Menu()); + + dock_dialogs=manage(new class Gtk::Menu()); + + dock_dialogs->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Vertical Dock: Canvases, History"),sigc::ptr_fun(_create_stock_dialog1))); + dock_dialogs->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Horizontal Dock: Layers, Children, Params"),sigc::ptr_fun(_create_stock_dialog2))); + dock_dialogs->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + dock_dialogs->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Reset Windows to Original Layout"),sigc::ptr_fun(App::reset_initial_window_configuration))); + dock_dialogs->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + + + filemenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::NEW, + sigc::ptr_fun(&studio::App::new_instance))); + filemenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::OPEN, + sigc::bind(sigc::ptr_fun(&studio::App::dialog_open), ""))); + + filemenu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Open Recent"),*recent_files_menu)); + + filemenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-saveall"), + sigc::ptr_fun(save_all))); + filemenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::CLOSE, + sigc::ptr_fun(close_selected_instance))); + filemenu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + filemenu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Panels"),*dock_dialogs)); + + filemenu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Input Devices..."), + sigc::ptr_fun(&show_dialog_input))); + filemenu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Setup..."), + sigc::ptr_fun(&studio::App::show_setup))); ++ filemenu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Reset to default Setup values"), ++ sigc::ptr_fun(&studio::App::reset_initial_preferences))); + + filemenu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + filemenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID(Gtk::Stock::QUIT), + sigc::ptr_fun(studio::App::quit))); + +#define WIKI(title,page) \ + helpmenu->items().push_back(Gtk::Menu_Helpers::MenuElem(title, \ + sigc::bind(sigc::ptr_fun(&studio::App::open_url),String("http://synfig.org/wiki")+page))) + +#define SITE(title,page) \ + helpmenu->items().push_back(Gtk::Menu_Helpers::MenuElem(title, \ + sigc::bind(sigc::ptr_fun(&studio::App::open_url),String("http://synfig.org")+page))) + + Gtk::Menu *helpmenu = manage(new class Gtk::Menu()); + helpmenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::HELP, sigc::ptr_fun(studio::App::dialog_help))); + helpmenu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + + /* TRANSLATORS: Help menu entry */ WIKI(_("Tutorials"), /* TRANSLATORS: a wiki page */ _("/Category:Tutorials") ); + /* TRANSLATORS: Help menu entry */ WIKI(_("Reference"), /* TRANSLATORS: a wiki page */ _("/Category:Reference") ); + /* TRANSLATORS: Help menu entry */ WIKI(_("Frequently Asked Questions"),/* TRANSLATORS: a wiki page */ _("/FAQ") ); + helpmenu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + /* TRANSLATORS: Help menu entry */ SITE(_("Get Support"), /* TRANSLATORS: a website page */ _("/en/support") ); + helpmenu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + helpmenu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-about"), + sigc::ptr_fun(studio::App::dialog_about))); + + Gtk::MenuBar *menubar1 = manage(new class Gtk::MenuBar()); + menubar1->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_File"),*filemenu)); + menubar1->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Help"),*helpmenu)); + + + menubar1->show(); + + Gtk::Image *icon; + + ADD_TOOLBOX_BUTTON(button_new,"gtk-new",_("New...")); + ADD_TOOLBOX_BUTTON(button_open,"gtk-open",_("Open...")); + ADD_TOOLBOX_BUTTON(button_save,"gtk-save",_("Save")); + ADD_TOOLBOX_BUTTON(button_saveas,"gtk-save-as",_("Save As...")); + ADD_TOOLBOX_BUTTON(button_save_all,"synfig-saveall",_("Save All")); + TOOLBOX_BUTTON(button_undo,"gtk-undo",_("Undo")); + TOOLBOX_BUTTON(button_redo,"gtk-redo",_("Redo")); + ADD_TOOLBOX_BUTTON(button_setup,"gtk-properties",_("Setup")); + ADD_TOOLBOX_BUTTON(button_about,"synfig-about",_("About Synfig Studio")); + ADD_TOOLBOX_BUTTON(button_help,"gtk-help",_("Help")); + + button_setup->signal_clicked().connect(sigc::ptr_fun(studio::App::show_setup)); + button_about->signal_clicked().connect(sigc::ptr_fun(studio::App::dialog_about)); + button_help->signal_clicked().connect(sigc::ptr_fun(studio::App::dialog_help)); + button_new->signal_clicked().connect(sigc::ptr_fun(studio::App::new_instance)); + button_open->signal_clicked().connect(sigc::bind(sigc::ptr_fun(studio::App::dialog_open), "")); + button_save->signal_clicked().connect(sigc::ptr_fun(save_selected_instance)); + button_saveas->signal_clicked().connect(sigc::ptr_fun(save_as_selected_instance)); + button_save_all->signal_clicked().connect(sigc::ptr_fun(save_all)); + button_undo->signal_clicked().connect(sigc::ptr_fun(studio::App::undo)); + button_redo->signal_clicked().connect(sigc::ptr_fun(studio::App::redo)); + + // Create the file button cluster + Gtk::Table *file_buttons=manage(new class Gtk::Table()); + - file_buttons->attach(*button_new, 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_open, 1,2, 0,1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_save, 2,3, 0,1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_saveas, 3,4, 0,1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_save_all, 4,5, 0,1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); ++ file_buttons->attach(*button_new, 0,1, 0,1, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_open, 1,2, 0,1, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_save, 2,3, 0,1, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_saveas, 3,4, 0,1, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_save_all, 4,5, 0,1, Gtk::EXPAND, Gtk::EXPAND, 0, 0); + - file_buttons->attach(*button_undo, 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_redo, 1,2, 1,2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_setup, 2,3, 1,2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_about, 3,4, 1,2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - file_buttons->attach(*button_help, 4,5, 1,2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); ++ file_buttons->attach(*button_undo, 0,1, 1,2, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_redo, 1,2, 1,2, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_setup, 2,3, 1,2, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_about, 3,4, 1,2, Gtk::EXPAND, Gtk::EXPAND, 0, 0); ++ file_buttons->attach(*button_help, 4,5, 1,2, Gtk::EXPAND, Gtk::EXPAND, 0, 0); + + file_buttons->show(); + + tool_table=manage(new class Gtk::Table()); + tool_table->show(); + Gtk::HandleBox* handle_tools(manage(new Gtk::HandleBox())); + handle_tools->add(*tool_table); + handle_tools->show(); + handle_tools->set_handle_position(Gtk::POS_TOP); + handle_tools->set_snap_edge(Gtk::POS_TOP); + + Widget_Defaults* widget_defaults(manage(new Widget_Defaults())); + widget_defaults->show(); + Gtk::HandleBox* handle_defaults(manage(new Gtk::HandleBox())); + handle_defaults->add(*widget_defaults); + handle_defaults->show(); + handle_defaults->set_handle_position(Gtk::POS_TOP); + handle_defaults->set_snap_edge(Gtk::POS_TOP); + + // Create the toplevel table + Gtk::Table *table1 = manage(new class Gtk::Table(1, 2, false)); + table1->set_row_spacings(0); + table1->set_col_spacings(0); + table1->attach(*menubar1, 0,1, 0,1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0); + table1->attach(*file_buttons, 0,1, 1,2, Gtk::FILL|Gtk::EXPAND,Gtk::EXPAND|Gtk::FILL, 0, 0); + table1->attach(*handle_tools, 0,1, 2,3, Gtk::FILL|Gtk::EXPAND,Gtk::EXPAND|Gtk::FILL, 0, 0); + table1->attach(*handle_defaults, 0,1, 3,4, Gtk::FILL|Gtk::EXPAND,Gtk::EXPAND|Gtk::FILL, 0, 0); + table1->show_all(); + + + + // Set the parameters for this window + add(*table1); + set_title(_("Synfig Studio")); + set_modal(false); + property_window_position().set_value(Gtk::WIN_POS_NONE); + signal_delete_event().connect(sigc::ptr_fun(App::shutdown_request)); + set_resizable(false); + + + + App::signal_instance_selected().connect( + sigc::hide( + sigc::mem_fun(*this,&studio::Toolbox::update_undo_redo) + ) + ); + + App::signal_recent_files_changed().connect( + sigc::mem_fun(*this,&studio::Toolbox::on_recent_files_changed) + ); + + button_undo->set_sensitive(false); + button_redo->set_sensitive(false); + + std::list listTargets; + listTargets.push_back( Gtk::TargetEntry("text/plain") ); + listTargets.push_back( Gtk::TargetEntry("image") ); +// listTargets.push_back( Gtk::TargetEntry("image/x-sif") ); + + drag_dest_set(listTargets); + signal_drag_data_received().connect( sigc::mem_fun(*this, &studio::Toolbox::on_drop_drag_data_received) ); + + App::dock_manager->signal_dockable_registered().connect(sigc::mem_fun(*this,&Toolbox::dockable_registered)); + + changing_state_=false; + + + add_accel_group(App::ui_manager()->get_accel_group()); + + App::signal_present_all().connect(sigc::mem_fun0(*this,&Toolbox::present)); +} + +Toolbox::~Toolbox() +{ + hide(); + //studio::App::cb.task(_("Toolbox: I was nailed!")); + //studio::App::quit(); + + if(studio::App::toolbox==this) + studio::App::toolbox=NULL; + +} + +void +Toolbox::set_active_state(const synfig::String& statename) +{ + std::map::iterator iter; + + changing_state_=true; + + synfigapp::Main::set_state(statename); + + try + { + + for(iter=state_button_map.begin();iter!=state_button_map.end();++iter) + { + if(iter->first==statename) + { + if(!iter->second->get_active()) + iter->second->set_active(true); + } + else + { + if(iter->second->get_active()) + iter->second->set_active(false); + } + } + } + catch(...) + { + changing_state_=false; + throw; + } + changing_state_=false; +} + +void +Toolbox::change_state(const synfig::String& statename) +{ + etl::handle canvas_view(studio::App::get_selected_canvas_view()); + if(canvas_view) + { + if(statename==canvas_view->get_smach().get_state_name()) + { + return; + } + + if(state_button_map.count(statename)) + { + state_button_map[statename]->clicked(); + } + else + { + synfig::error("Unknown state \"%s\"",statename.c_str()); + } + } +} + +void +Toolbox::change_state_(const Smach::state_base *state) +{ + if(changing_state_) + return; + changing_state_=true; + + try + { + etl::handle canvas_view(studio::App::get_selected_canvas_view()); + if(canvas_view) + canvas_view->get_smach().enter(state); + else + refresh(); + } + catch(...) + { + changing_state_=false; + throw; + } + + changing_state_=false; +} + +void +Toolbox::add_state(const Smach::state_base *state) +{ + Gtk::Image *icon; + + assert(state); + + String name=state->get_name(); + + Gtk::StockItem stock_item; + Gtk::Stock::lookup(Gtk::StockID("synfig-"+name),stock_item); + + Gtk::ToggleButton* button; + button=manage(new class Gtk::ToggleButton()); + + icon=manage(new Gtk::Image(stock_item.get_stock_id(),Gtk::IconSize(4))); + button->add(*icon); + tooltips.set_tip(*button,stock_item.get_label()); + icon->show(); + button->show(); + + int row=state_button_map.size()/5; + int col=state_button_map.size()%5; + - tool_table->attach(*button,col,col+1,row,row+1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); ++ tool_table->attach(*button,col,col+1,row,row+1, Gtk::EXPAND, Gtk::EXPAND, 0, 0); + + state_button_map[name]=button; + + button->signal_clicked().connect( + sigc::bind( + sigc::mem_fun(*this,&studio::Toolbox::change_state_), + state + ) + ); + + refresh(); +} + + +void +Toolbox::update_undo_redo() +{ + etl::handle instance=App::get_selected_instance(); + if(instance) + { + button_undo->set_sensitive(instance->get_undo_status()); + button_redo->set_sensitive(instance->get_redo_status()); + } + + // This should probably go elsewhere, but it should + // work fine here with no troubles. + // These next several lines just adjust the tool buttons + // so that they are only clickable when they should be. + if(instance && App::get_selected_canvas_view()) + { + std::map::iterator iter; + + for(iter=state_button_map.begin();iter!=state_button_map.end();++iter) + iter->second->set_sensitive(true); + } + else + { + std::map::iterator iter; + + for(iter=state_button_map.begin();iter!=state_button_map.end();++iter) + iter->second->set_sensitive(false); + } + + etl::handle canvas_view=App::get_selected_canvas_view(); + if(canvas_view && canvas_view->get_smach().get_state_name()) + { + set_active_state(canvas_view->get_smach().get_state_name()); + } + else + set_active_state("none"); + +} + +void +Toolbox::on_recent_files_changed() +{ + while(recent_files_menu->get_children().size()) + recent_files_menu->remove(**recent_files_menu->get_children().begin()); + + list::const_iterator iter; + for(iter=App::get_recent_files().begin();iter!=App::get_recent_files().end();iter++) + { + string raw = basename(*iter), quoted; + size_t pos = 0, last_pos = 0; + + // replace _ in filenames by __ or it won't show up in the menu + for (pos = last_pos = 0; (pos = raw.find('_', pos)) != string::npos; last_pos = pos) + quoted += raw.substr(last_pos, ++pos - last_pos) + '_'; + quoted += raw.substr(last_pos); + + recent_files_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(quoted, + sigc::hide_return(sigc::bind(sigc::ptr_fun(&App::open),*iter)) + )); + } + + // HACK + show(); +} + +void +Toolbox::on_drop_drag_data_received(const Glib::RefPtr& context, int /*x*/, int /*y*/, const Gtk::SelectionData& selection_data_, guint /*info*/, guint time) +{ + // We will make this true once we have a solid drop + bool success(false); + + if ((selection_data_.get_length() >= 0) && (selection_data_.get_format() == 8)) + { + synfig::String selection_data((gchar *)(selection_data_.get_data())); + + // For some reason, GTK hands us a list of URLs separated + // by not only Carriage-Returns, but also Line-Feeds. + // Line-Feeds will mess us up. Remove all the line-feeds. + while(selection_data.find_first_of('\r')!=synfig::String::npos) + selection_data.erase(selection_data.begin()+selection_data.find_first_of('\r')); + + std::stringstream stream(selection_data); + + while(stream) + { + synfig::String filename,URI; + getline(stream,filename); + + // If we don't have a filename, move on. + if(filename.empty()) + continue; + + // Make sure this URL is of the "file://" type. + URI=String(filename.begin(),filename.begin()+sizeof("file://")-1); + if(URI!="file://") + { + synfig::warning("Unknown URI (%s) in \"%s\"",URI.c_str(),filename.c_str()); + continue; + } + + // Strip the "file://" part from the filename + filename=synfig::String(filename.begin()+sizeof("file://")-1,filename.end()); + + synfig::info("Attempting to open "+filename); + if(App::open(filename)) + success=true; + else + synfig::error("Drop failed: Unable to open "+filename); + } + } + else + synfig::error("Drop failed: bad selection data"); + + // Finish the drag + context->drag_finish(success, false, time); +} + +void +Toolbox::dockable_registered(Dockable* x) +{ + dock_dialogs->items().push_back( + Gtk::Menu_Helpers::MenuElem( + x->get_local_name(), + sigc::mem_fun( + *x, + &Dockable::present + ) + ) + ); +}