Typo: 'outselves' -> 'ourselves'.
[synfig.git] / synfig-studio / trunk / src / gtkmm / app.cpp
index 033e285..b36162d 100644 (file)
@@ -6,6 +6,7 @@
 **
 **     \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
@@ -252,6 +253,7 @@ studio::Dock_Curves* dock_curves;
 std::list< etl::handle< studio::Module > > module_list_;
 
 bool studio::App::use_colorspace_gamma=true;
+bool studio::App::single_threaded=false;
 
 static int max_recent_files_=25;
 int studio::App::get_max_recent_files() { return max_recent_files_; }
@@ -260,6 +262,25 @@ 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 %x", (unsigned int)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 %x", (unsigned int)widget);
+       Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(&really_delete_widget), widget), 50);
+}
+
 }; // END of namespace studio
 studio::StateManager* state_manager;
 
@@ -352,7 +373,7 @@ public:
        }
 
        virtual bool
-       amount_complete(int current, int total)
+       amount_complete(int /*current*/, int /*total*/)
        {
                while(studio::App::events_pending())studio::App::iteration(false);
                return true;
@@ -458,7 +479,15 @@ int v_key_check(const char* key, U32* serial, U32 appid)
 }
 
 
+#ifdef _WIN32
+# ifdef LICENSE_KEY_REQUIRED
 int check_license(String basedir)
+# else
+int check_license(String /*basedir*/)
+# endif
+#else
+int check_license(String /*basedir*/)
+#endif
 {
 #ifdef LICENSE_KEY_REQUIRED
        String key;
@@ -592,6 +621,11 @@ public:
                        value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
                        return true;
                }
+               if(key=="single_threaded")
+               {
+                       value=strprintf("%i",(int)App::single_threaded);
+                       return true;
+               }
                if(key=="auto_recover_backup_interval")
                {
                        value=strprintf("%i",App::auto_recover->get_timeout());
@@ -647,6 +681,12 @@ public:
                        App::distance_system=Distance::ident_system(value);;
                        return true;
                }
+               if(key=="single_threaded")
+               {
+                       int i(atoi(value.c_str()));
+                       App::single_threaded=i;
+                       return true;
+               }
 
                return synfigapp::Settings::set_value(key,value);
        }
@@ -659,6 +699,7 @@ public:
                ret.push_back("distance_system");
                ret.push_back("file_history.size");
                ret.push_back("use_colorspace_gamma");
+               ret.push_back("single_threaded");
                ret.push_back("auto_recover_backup_interval");
                return ret;
        }
@@ -719,7 +760,8 @@ init_ui_manager()
        DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
        DEFINE_ACTION("sound", _("Sound File"));
        DEFINE_ACTION("options", _("Options"));
-       DEFINE_ACTION("close", _("Close"));
+       DEFINE_ACTION("close", _("Close View"));
+       DEFINE_ACTION("close-document", _("Close Document"));
 
 
        DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
@@ -749,7 +791,7 @@ init_ui_manager()
        DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
        DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
        DEFINE_ACTION("play", _("Play"));
-       DEFINE_ACTION("pause", _("Pause"));
+       // DEFINE_ACTION("pause", _("Pause"));
        DEFINE_ACTION("stop", _("Stop"));
        DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
        DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
@@ -839,6 +881,7 @@ init_ui_manager()
 "              <separator name='bleh04'/>"
 "              <menuitem action='options' />"
 "              <menuitem action='close' />"
+"              <menuitem action='close-document' />"
 "      </menu>"
 "      <menu action='menu-edit'>"
 "              <menuitem action='undo'/>"
@@ -877,7 +920,7 @@ init_ui_manager()
 "              </menu>"
 "              <separator name='bleh08'/>"
 "              <menuitem action='play'/>"
-"              <menuitem action='pause'/>"
+//"            <menuitem action='pause'/>"
 "              <menuitem action='stop'/>"
 "              <menuitem action='dialog-flipbook'/>"
 "              <separator name='bleh09'/>"
@@ -906,8 +949,6 @@ init_ui_manager()
 "      </menu>"
 "      <menu action='menu-canvas'>"
 "              <menuitem action='canvas-new'/>"
-       "       <menuitem action='amount-inc'/>"
-       "       <menuitem action='amount-dec'/>"
 "      </menu>"
 "      <menu name='menu-state' action='menu-state'>"
 "      </menu>"
@@ -920,6 +961,8 @@ init_ui_manager()
 //"            <menuitem action='paste'/>"
 //"            <separator name='bleh06'/>"
 "              <menu action='menu-layer-new'></menu>"
+"              <menuitem action='amount-inc'/>"
+"              <menuitem action='amount-dec'/>"
 "      </menu>"
 "      <menu action='menu-keyframe'>"
 "              <menuitem action='keyframe-properties'/>"
@@ -1032,16 +1075,30 @@ init_ui_manager()
        ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
        ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
        ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
+       ACCEL("<Actions>//play",              "<Control>p");
        ACCEL("<Actions>//seek-begin","Home");
        ACCEL("<Actions>//seek-end","End");
-       ACCEL("<Actions>//state-normal","<Mod1>a");
-       ACCEL("<Actions>//state-rotate","<Mod1>s");
-       ACCEL("<Actions>//state-scale","<Mod1>d");
-       ACCEL("<Actions>//state-bline","<Mod1>b");
-       ACCEL("<Actions>//state-fill","<Mod1>f");
-       ACCEL("<Actions>//state-eyedrop","<Mod1>e");
-       ACCEL("<Actions>//state-gradient","<Mod1>g");
-       ACCEL("<Actions>//state-zoom","<Mod1>z");
+
+       ACCEL("<Actions>//state-normal",      "<Mod1>a");
+       ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
+       ACCEL("<Actions>//state-scale",       "<Mod1>d");
+       ACCEL("<Actions>//state-rotate",      "<Mod1>s");
+
+       ACCEL("<Actions>//state-bline",       "<Mod1>b");
+       ACCEL("<Actions>//state-circle",      "<Mod1>c");
+       ACCEL("<Actions>//state-rectangle",   "<Mod1>r");
+       ACCEL("<Actions>//state-gradient",    "<Mod1>g");
+
+       ACCEL("<Actions>//state-eyedrop",     "<Mod1>e");
+       ACCEL("<Actions>//state-fill",        "<Mod1>f");
+       ACCEL("<Actions>//state-zoom",        "<Mod1>z");
+       ACCEL("<Actions>//state-polygon",     "<Mod1>p");
+
+       ACCEL("<Actions>//state-draw",        "<Mod1>w");
+       ACCEL("<Actions>//state-sketch",      "<Mod1>k");
+       ACCEL("<Actions>//state-width",       "<Mod1>t");
+       ACCEL("<Actions>//state-mirror",      "<Mod1>m");
+
        ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
 
 #undef ACCEL
@@ -1055,7 +1112,7 @@ init_ui_manager()
 
 App::App(int *argc, char ***argv):
        Gtk::Main(argc,argv),
-       IconControler(etl::dirname((*argv)[0]))
+       IconController(etl::dirname((*argv)[0]))
 {
        app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
 
@@ -1067,7 +1124,10 @@ App::App(int *argc, char ***argv):
 
        gdk_rgb_init();
 
-       Glib::thread_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;
 
@@ -1226,15 +1286,16 @@ App::App(int *argc, char ***argv):
 
                state_manager->add_state(&state_zoom);
 
-               // Disabled this tool because it should be
-               // considered deprecated. Use the bline tool instead.
-               if(getenv("SYNFIG_ENABLE_POLYGON")) state_manager->add_state(&state_polygon);
+               // Enabled - it's useful to be able to work with polygons without tangent ducks getting in the way.
+               // I know we can switch tangent ducks off, but why not allow this kind of layer as well?
+               if(!getenv("SYNFIG_DISABLE_POLYGON")) state_manager->add_state(&state_polygon);
+
+               // Enabled for now.  Let's see whether they're good enough yet.
+               if(!getenv("SYNFIG_DISABLE_DRAW"   )) state_manager->add_state(&state_draw);
+               if(!getenv("SYNFIG_DISABLE_SKETCH" )) state_manager->add_state(&state_sketch);
 
-               // These tools are disabled by default for now,
-               // because they tend to confuse users.
-               if(getenv("SYNFIG_ENABLE_DRAW"  )) state_manager->add_state(&state_draw);
-               if(getenv("SYNFIG_ENABLE_SKETCH")) state_manager->add_state(&state_sketch);
-               if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
+               // Disabled by default - it doesn't work properly?
+               if(getenv("SYNFIG_ENABLE_WIDTH"    )) state_manager->add_state(&state_width);
 
                studio_init_cb.task("Init ModPalette...");
                module_list_.push_back(new ModPalette()); module_list_.back()->start();
@@ -1383,7 +1444,7 @@ App::add_recent_file(const std::string &file_name)
        if(basename(filename)[0]=='.')
                return;
 
-       // If we aren't an absolute path, turn outselves into one
+       // If we aren't an absolute path, turn ourselves into one
        if(!is_absolute_path(filename))
                filename=absolute_path(filename);
 
@@ -1496,19 +1557,7 @@ App::load_settings()
                        //if(!synfigapp::Main::settings().load_from_file(filename))
                        {
                                gamma.set_gamma(1.0/2.2);
-                               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.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("pref.distance_system","pt");
-                               synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
-                               synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
+                               reset_initial_window_configuration();
                        }
                }
        setlocale(LC_NUMERIC,old_locale);
@@ -1519,6 +1568,25 @@ App::load_settings()
        }
 }
 
+void
+App::reset_initial_window_configuration()
+{
+       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.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("pref.distance_system","pt");
+       synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
+       synfigapp::Main::settings().set_value("pref.single_threaded","0");
+       synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
+}
+
 bool
 App::shutdown_request(GdkEventAny*)
 {
@@ -1614,8 +1682,8 @@ App::show_setup()
        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;}
+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
@@ -1678,13 +1746,17 @@ App::dialog_open_file(const std::string &title, std::string &filename)
        synfig::String prev_path;
        if(!_preferences.get_value("curr_path",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::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
-    dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
+    dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+    dialog->add_button(Gtk::Stock::OPEN,   Gtk::RESPONSE_ACCEPT);
     if(!filename.empty())
-        dialog->set_filename(filename);
+               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();
         delete dialog;
@@ -1704,7 +1776,7 @@ App::dialog_open_file(const std::string &title, std::string &filename)
 
        if(basename(filename)==filename)
        {
-               gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
+               gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPARATOR).c_str());
        }
        else
                gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
@@ -1742,7 +1814,7 @@ App::dialog_open_file(const std::string &title, std::string &filename)
 bool
 App::dialog_save_file(const std::string &title, std::string &filename)
 {
-#ifdef USE_WIN32_FILE_DIALOGS
+#if USE_WIN32_FILE_DIALOGS
        static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
 
        GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
@@ -1780,6 +1852,7 @@ App::dialog_save_file(const std::string &title, std::string &filename)
        if(GetSaveFileName(&ofn))
        {
                filename=szFilename;
+               _preferences.set_value("curr_path",dirname(filename));
                return true;
        }
        return false;
@@ -1787,82 +1860,31 @@ App::dialog_save_file(const std::string &title, std::string &filename)
        synfig::String prev_path;
        if(!_preferences.get_value("curr_path",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::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
-    dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
+    dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+    dialog->add_button(Gtk::Stock::SAVE,   Gtk::RESPONSE_ACCEPT);
     if(!filename.empty())
-        dialog->set_filename(filename);
-    if(dialog->run()==GTK_RESPONSE_ACCEPT) {
-        filename=dialog->get_filename();
-        delete dialog;
-        return true;
-    }
-    delete dialog;
-    return false;
-//     return dialog_open_file(title, filename);
-#endif
-}
-
-bool
-App::dialog_saveas_file(const std::string &title, std::string &filename)
-{
-#if USE_WIN32_FILE_DIALOGS
-       static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
-
-       GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
-       HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
-       HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
-
-       ofn.lStructSize=sizeof(OPENFILENAME);
-       ofn.hwndOwner = hWnd;
-       ofn.hInstance = hInstance;
-       ofn.lpstrFilter = szFilter;
-//     ofn.lpstrCustomFilter=NULL;
-//     ofn.nMaxCustFilter=0;
-//     ofn.nFilterIndex=0;
-//     ofn.lpstrFile=NULL;
-       ofn.nMaxFile=MAX_PATH;
-//     ofn.lpstrFileTitle=NULL;
-//     ofn.lpstrInitialDir=NULL;
-//     ofn.lpstrTitle=NULL;
-       ofn.Flags=OFN_OVERWRITEPROMPT;
-//     ofn.nFileOffset=0;
-//     ofn.nFileExtension=0;
-       ofn.lpstrDefExt=TEXT("sif");
-//     ofn.lCustData = 0l;
-       ofn.lpfnHook=NULL;
-//     ofn.lpTemplateName=NULL;
-
-       CHAR szFilename[MAX_PATH];
-       CHAR szTitle[500];
-       strcpy(szFilename,filename.c_str());
-       strcpy(szTitle,title.c_str());
-
-       ofn.lpstrFile=szFilename;
-       ofn.lpstrFileTitle=szTitle;
-
-       if(GetSaveFileName(&ofn))
        {
-               filename=szFilename;
-               return true;
+               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));
        }
-       return false;
-#else
-       synfig::String prev_path;
-       if(!_preferences.get_value("curr_path",prev_path))
-               prev_path=".";
-
-    Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
-    dialog->set_current_folder(prev_path);
-    dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
-    dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
-    if(!filename.empty())
-        dialog->set_filename(filename);
     if(dialog->run()==GTK_RESPONSE_ACCEPT) {
         filename=dialog->get_filename();
         delete dialog;
+               _preferences.set_value("curr_path",dirname(filename));
         return true;
     }
     delete dialog;
@@ -1975,6 +1997,9 @@ 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)
 {
@@ -2030,9 +2055,9 @@ void
 App::new_instance()
 {
        handle<synfig::Canvas> canvas=synfig::Canvas::create();
-       canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
+       canvas->set_name(strprintf("%s%d", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
 
-       String file_name(strprintf("untitled%d.sif",Instance::get_count()));
+       String file_name(strprintf("%s%d.sifz", DEFAULT_FILENAME_PREFIX, Instance::get_count()+1));
 
        canvas->rend_desc().set_frame_rate(24.0);
        canvas->rend_desc().set_time_start(0.0);