diff --git a/SConstruct b/SConstruct index 7a1aa2592..3c49573da 100644 --- a/SConstruct +++ b/SConstruct @@ -93,10 +93,10 @@ def setupBasicEnvironment(): appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb') # setup search path for Lumiera plugins - appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR\\"' - ,'LUMIERA_PLUGIN_PATH=\\"$DESTDIR/lib/lumiera\\"') - appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR\\"' - ,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera\\"') + appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:./.libs\\"' + ,'LUMIERA_PLUGIN_PATH=\\"$DESTDIR/lib/lumiera/:./.libs\\"') + appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR/:.\\"' + ,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera/:.\\"') prepareOptionsHelp(opts,env) opts.Save(OPTIONSCACHEFILE, env) diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 661c92f64..451b0a982 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -18,7 +18,7 @@ liblumieracommon_la_srcdir = $(top_srcdir)/src/common lib_LTLIBRARIES += liblumieracommon.la -liblumieracommon_la_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_CONFIG_PATH="\"$(pkgdatadir)/config\"" -DLUMIERA_PLUGIN_PATH="\"$(pkglibdir)/\"" +liblumieracommon_la_CPPFLAGS = $(AM_CPPFLAGS) -DLUMIERA_CONFIG_PATH="\"$(pkgdatadir)/config:.\"" -DLUMIERA_PLUGIN_PATH="\"$(pkglibdir)/:./.libs\"" liblumieracommon_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror liblumieracommon_la_CXXFLAGS = $(AM_CXXFLAGS) -Wextra -Wall liblumieracommon_la_LIBADD = liblumiera.la diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index fd53d31f7..87e2c34a7 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -65,16 +65,19 @@ GtkLumiera::main(int argc, char *argv[]) Project project; Controller controller(project); - WindowManager window_manager; - window_manager.set_theme("lumiera_ui.rc"); + windowManager.init(); + windowManager.set_theme("lumiera_ui.rc"); + windowManager.new_window(project, controller); - WorkspaceWindow main_window(project, controller); - - kit.run(main_window); - + kit.run(); } +WindowManager& +GtkLumiera::get_window_manager() +{ + return windowManager; +} Glib::ustring GtkLumiera::get_home_data_path() diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index 815b93ddd..e8cefd7b4 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -40,6 +40,8 @@ #include #include "lib/util.hpp" +#include "window-manager.hpp" + extern "C" { #include } @@ -73,6 +75,8 @@ class GtkLumiera : private boost::noncopyable public: void main(int argc, char *argv[]); + WindowManager& get_window_manager(); + static Glib::ustring get_home_data_path(); /** @@ -99,6 +103,12 @@ public: * Returns tn alphabetical list of the application's authors **/ static const std::vector get_app_authors(); + +protected: + /** + * The application window manager object + **/ + WindowManager windowManager; }; /** diff --git a/src/gui/model/track.cpp b/src/gui/model/track.cpp index 7e9a3992b..d94926229 100644 --- a/src/gui/model/track.cpp +++ b/src/gui/model/track.cpp @@ -53,6 +53,7 @@ void Track::set_name(const string &name) { this->name = name; + nameChangedSignal.emit(name); } bool @@ -74,6 +75,12 @@ Track::find_descendant_track_parent( return shared_ptr(); } +sigc::signal +Track::signal_name_changed() const +{ + return nameChangedSignal; +} + string Track::print_branch_recursive(const unsigned int indentation) { diff --git a/src/gui/model/track.hpp b/src/gui/model/track.hpp index ac137d451..c59d06875 100644 --- a/src/gui/model/track.hpp +++ b/src/gui/model/track.hpp @@ -79,7 +79,17 @@ public: **/ virtual boost::shared_ptr find_descendant_track_parent(boost::shared_ptr child); - + +public: + + /** + * A signal which fires when the name changes. + * @return Returns the signal. The signal sends the new name for the + * track. + **/ + sigc::signal signal_name_changed() const; + +public: /** * A debugging helper function that prints this track, and all it's * child tracks in a human-readable form. @@ -109,6 +119,11 @@ private: * The name of this track. **/ std::string name; + + /** + * A signal which fires when the name changes. + **/ + sigc::signal nameChangedSignal; protected: /** diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 6a8f4f023..4dd938184 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -89,6 +89,11 @@ Track::Track(TimelineWidget &timeline_widget, mem_fun(timelineWidget, &TimelineWidget::on_add_track_command) ) ); context_list.push_back( Menu_Helpers::MenuElem(_("_Remove Track"), mem_fun(this, &Track::on_remove_track) ) ); + + // Connect to the model + model_track->signal_name_changed().connect(sigc::mem_fun(this, + &Track::on_name_changed)); + } Gtk::Widget& @@ -241,10 +246,13 @@ Track::on_set_name() _("Set Track Name"), model_track->get_name()); if(dialog.run() == RESPONSE_OK) - { - model_track->set_name(dialog.get_name()); - update_name(); - } + model_track->set_name(dialog.get_name()); +} + +void +Track::on_name_changed(std::string) +{ + update_name(); } void diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index 3c7e4ee6b..43f9db39f 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -135,6 +135,11 @@ private: //----- Event Handlers -----// void on_set_name(); + + /** + * Event handler for when the track name changes + **/ + void on_name_changed(std::string); void on_remove_track(); diff --git a/src/gui/window-manager.cpp b/src/gui/window-manager.cpp index c227d4b5d..0e6319816 100644 --- a/src/gui/window-manager.cpp +++ b/src/gui/window-manager.cpp @@ -22,21 +22,42 @@ #include "window-manager.hpp" #include "include/logging.h" +#include "workspace/workspace-window.hpp" using namespace Gtk; using namespace Glib; +using namespace boost; +using namespace std; +using namespace gui::workspace; namespace gui { IconSize WindowManager::GiantIconSize = ICON_SIZE_INVALID; IconSize WindowManager::MenuIconSize = ICON_SIZE_INVALID; -WindowManager::WindowManager() +void +WindowManager::init() { register_app_icon_sizes(); register_stock_items(); } +void +WindowManager::new_window(gui::model::Project &source_project, + gui::controller::Controller &source_controller) +{ + shared_ptr window( + new WorkspaceWindow(source_project, source_controller)); + REQUIRE(window); + + window->signal_delete_event().connect(sigc::mem_fun( + this, &WindowManager::on_window_closed)); + + windowList.push_back(window); + + window->show(); +} + bool WindowManager::set_theme(Glib::ustring path) { @@ -53,7 +74,44 @@ WindowManager::set_theme(Glib::ustring path) return true; } + +bool +WindowManager::on_window_closed(GdkEventAny* event) +{ + REQUIRE(event); + REQUIRE(event->window); + + list< shared_ptr >::iterator iterator = + windowList.begin(); + + while(iterator != windowList.end()) + { + shared_ptr workspace_window(*iterator); + REQUIRE(workspace_window); + + RefPtr window = workspace_window->get_window(); + REQUIRE(window); + if(window->gobj() == event->window) + { + // This window has been closed + iterator = windowList.erase(iterator); + } + else + iterator++; + } + if(windowList.empty()) + { + // All windows have been closed - we should exit + Main *main = Main::instance(); + REQUIRE(main); + main->quit(); + } + + // Unless this is false, the window won't close + return false; +} + GdkColor WindowManager::read_style_colour_property( Gtk::Widget &widget, const gchar *property_name, @@ -93,6 +151,8 @@ WindowManager::register_stock_items() add_stock_icon_set(factory, "panel-timeline", "panel_timeline", _("_Timeline")); add_stock_icon_set(factory, "panel-viewer", "panel_viewer", _("_Viewer")); + add_stock_icon_set(factory, "window-new", "new_window", _("New _Window")); + add_stock_icon_set(factory, "tool-arrow", "tool_arrow", _("_Arrow")); add_stock_icon_set(factory, "tool-i-beam", "tool_i_beam", _("_I-Beam")); @@ -144,14 +204,19 @@ WindowManager::add_stock_icon_set( bool WindowManager::add_stock_icon(Gtk::IconSet &icon_set, const Glib::ustring& icon_name, Gtk::IconSize size, bool wildcard) -{ +{ + // Try the icon theme + if(add_theme_icon_source(icon_set, icon_name, size, wildcard)) + return true; + // Try the ~/.lumiera/icons folder - if(add_stock_icon_source(icon_set, ustring::compose("%1/%2", + if(add_non_theme_icon_source(icon_set, ustring::compose("%1/%2", GtkLumiera::get_home_data_path(), ustring("icons")), icon_name, size, wildcard)) return true; - if(add_stock_icon_source( + // Try the local directory + if(add_non_theme_icon_source( icon_set, get_current_dir(), icon_name, size, wildcard)) return true; @@ -159,38 +224,70 @@ WindowManager::add_stock_icon(Gtk::IconSet &icon_set, } bool -WindowManager::add_stock_icon_source(Gtk::IconSet &icon_set, - const Glib::ustring& base_dir, const Glib::ustring& icon_name, - Gtk::IconSize size, bool wildcard) +WindowManager::add_theme_icon_source(Gtk::IconSet &icon_set, + const Glib::ustring& icon_name, Gtk::IconSize size, bool wildcard) { - ustring path; - Gtk::IconSource source; - + // Get the size int width = 0, height = 0; if(!IconSize::lookup(size, width, height)) return false; + REQUIRE(width > 0); + + // Try to load the icon + RefPtr theme = Gtk::IconTheme::get_default(); + REQUIRE(theme); + + TODO ("find out how IconInfo could be made const. For example, GTKmm 2.10.10 is missing the const on operator bool() in iconinfo.h"); + IconInfo info = theme->lookup_icon(icon_name, width, + (IconLookupFlags)0); + if(info) + { + const ustring path(info.get_filename()); + if(add_stock_icon_from_path(path, icon_set, size, wildcard)) + return true; + } + + return false; +} + +bool +WindowManager::add_non_theme_icon_source(Gtk::IconSet &icon_set, + const Glib::ustring& base_dir, const Glib::ustring& icon_name, + Gtk::IconSize size, bool wildcard) +{ + // Get the size + int width = 0, height = 0; + if(!IconSize::lookup(size, width, height)) + return false; + REQUIRE(width > 0); + + // Try to load the icon + const ustring path(ustring::compose("%1/%2x%3/%4.png", + base_dir, width, height, icon_name)); + return add_stock_icon_from_path(path, icon_set, size, wildcard); +} + +bool +WindowManager::add_stock_icon_from_path(Glib::ustring path, + Gtk::IconSet &icon_set, Gtk::IconSize size, bool wildcard) +{ + Gtk::IconSource source; try - { - ustring path = ustring::compose("%1/%2x%3/%4.png", - base_dir, width, height, icon_name); - - INFO(gui, "Attempting to load icon: %s", path.c_str()); - + { // This throws an exception if the file is not found: source.set_pixbuf(Gdk::Pixbuf::create_from_file(path)); } catch(const Glib::Exception& ex) { - INFO(gui, "Failed to load icon: %s", path.c_str()); return false; } - + source.set_size(size); source.set_size_wildcarded(wildcard); icon_set.add_source(source); - + return true; } diff --git a/src/gui/window-manager.hpp b/src/gui/window-manager.hpp index 64783d250..341c25fcb 100644 --- a/src/gui/window-manager.hpp +++ b/src/gui/window-manager.hpp @@ -25,13 +25,26 @@ ** @see gtk-lumiera.hpp */ +#include "gtk-lumiera.hpp" +//#include "workspace/workspace-window.hpp" + #ifndef WINDOW_MANAGER_HPP #define WINDOW_MANAGER_HPP -#include "gtk-lumiera.hpp" - namespace gui { +namespace model { + class Project; +} // model + +namespace controller { + class Controller; +} // model + +namespace workspace { + class WorkspaceWindow; +} + /** * The centralised manager of all lumiera-gui's windows. **/ @@ -39,9 +52,18 @@ class WindowManager : private boost::noncopyable { public: /** - * Default constructor + * Initializes the window manager object **/ - WindowManager(); + void init(); + + /** + * Creates a new window connected to a specified project and + * controller + * @param source_project The project to connect the window to. + * @param source_controller The controller to connect the window to. + **/ + void new_window(gui::model::Project &source_project, + gui::controller::Controller &source_controller); /** * Sets the theme of the lumiera-gui's. @@ -49,7 +71,7 @@ public: * will be found. **/ bool set_theme(Glib::ustring path); - + /** * A utility function which reads a colour style from the GTK Style. * @param widget The widget to load the style out of. @@ -62,6 +84,13 @@ public: static GdkColor read_style_colour_property( Gtk::Widget &widget, const gchar *property_name, guint16 red, guint16 green, guint16 blue); + +private: + + /** + * An event handler for when a window has been closed. + **/ + bool on_window_closed(GdkEventAny* event); private: @@ -103,9 +132,21 @@ private: **/ static bool add_stock_icon(Gtk::IconSet &icon_set, const Glib::ustring& icon_name, Gtk::IconSize size, bool wildcard); + + /** + * Loads an icon from a the icon theme + * @param icon_set The icon set to add the icon to. + * @param icon_name The name of the icon to load. + * @param size The size of the icon to load. + * @param wildcard This value is set to true if this icon is + * wildcarded. + * @return Returns true if the icon was loaded successfully. + **/ + static bool add_theme_icon_source(Gtk::IconSet &icon_set, + const Glib::ustring& icon_name, Gtk::IconSize size, bool wildcard); /** - * Loads an icon from a specific path and adds it to an icon set. + * Loads an icon from a non theme set. * @param icon_set The icon set to add the icon to. * @param base_dir The root icons directory to load from. * @param icon_name The file name of the icon to load. @@ -114,9 +155,25 @@ private: * wildcarded. * @return Returns true if the icon was loaded successfully. **/ - static bool add_stock_icon_source(Gtk::IconSet &icon_set, + static bool add_non_theme_icon_source(Gtk::IconSet &icon_set, const Glib::ustring& base_dir, const Glib::ustring& icon_name, Gtk::IconSize size, bool wildcard); + + /** + * Loads an icon from a specific path and adds it to an icon set. + * @param path The path to load from. + * @param icon_set The icon set to add the icon to. + * @param size The size of the icon to load. + * @param wildcard This value is set to true if this icon is + * wildcarded. + * @return Returns true if the icon was loaded successfully. + **/ + static bool add_stock_icon_from_path(Glib::ustring path, + Gtk::IconSet &icon_set, Gtk::IconSize size, bool wildcard); + +private: + + std::list< boost::shared_ptr > windowList; public: diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index 88a440103..e2679b7f1 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -23,6 +23,8 @@ #include "actions.hpp" #include "workspace-window.hpp" +#include "../window-manager.hpp" + #include "../dialogs/render.hpp" #include "../dialogs/preferences-dialog.hpp" #include "../dialogs/name-chooser.hpp" @@ -70,10 +72,10 @@ Actions::Actions(WorkspaceWindow &workspace_window) : // View Menu actionGroup->add(Action::create("ViewMenu", _("_View"))); - assetsPanelAction = ToggleAction::create("ViewAssets", - Gtk::StockID("panel_assets")); + assetsPanelAction = ToggleAction::create("ViewResources", + Gtk::StockID("panel_resources")); assetsPanelAction->signal_toggled().connect( - sigc::mem_fun(*this, &Actions::on_menu_view_assets)); + sigc::mem_fun(*this, &Actions::on_menu_view_resources)); actionGroup->add(assetsPanelAction); timelinePanelAction = ToggleAction::create("ViewTimeline", @@ -88,6 +90,10 @@ Actions::Actions(WorkspaceWindow &workspace_window) : sigc::mem_fun(*this, &Actions::on_menu_view_viewer)); actionGroup->add(viewerPanelAction); + actionGroup->add(Action::create("ViewNewWindow", + Gtk::StockID("new_window")), + sigc::mem_fun(*this, &Actions::on_menu_view_new_window)); + // Sequence Menu actionGroup->add(Action::create("SequenceMenu", _("_Sequence"))); actionGroup->add(Action::create("SequenceAdd", _("_Add...")), @@ -160,7 +166,7 @@ Actions::on_menu_edit_preferences() /* ===== View Menu Event Handlers ===== */ void -Actions::on_menu_view_assets() +Actions::on_menu_view_resources() { if(!is_updating_action_state) workspaceWindow.resourcesPanel->show( @@ -181,6 +187,13 @@ Actions::on_menu_view_viewer() workspaceWindow.viewerPanel->show(viewerPanelAction->get_active()); } +void +Actions::on_menu_view_new_window() +{ + application().get_window_manager().new_window(workspaceWindow.project, + workspaceWindow.controller); +} + /* ===== Sequence Menu Event Handlers ===== */ void diff --git a/src/gui/workspace/actions.hpp b/src/gui/workspace/actions.hpp index 76034ac6e..eb995fc02 100644 --- a/src/gui/workspace/actions.hpp +++ b/src/gui/workspace/actions.hpp @@ -66,9 +66,10 @@ private: void on_menu_edit_preferences(); - void on_menu_view_assets(); + void on_menu_view_resources(); void on_menu_view_timeline(); void on_menu_view_viewer(); + void on_menu_view_new_window(); void on_menu_sequence_add(); diff --git a/src/gui/workspace/workspace-window.cpp b/src/gui/workspace/workspace-window.cpp index 76a67a4d8..d79008367 100644 --- a/src/gui/workspace/workspace-window.cpp +++ b/src/gui/workspace/workspace-window.cpp @@ -117,9 +117,11 @@ WorkspaceWindow::create_ui() " " " " " " - " " + " " " " " " + " " + " " " " " " " "