diff --git a/src/gui/ui-bus.cpp b/src/gui/ui-bus.cpp index 69ed41f70..f5a38d7ba 100644 --- a/src/gui/ui-bus.cpp +++ b/src/gui/ui-bus.cpp @@ -68,6 +68,14 @@ namespace controller { // emit administrative code here... UiBus::~UiBus() { } + + ctrl::BusTerm& + UiBus::getAccessPoint() + { + return *coreService_; + } + + namespace ctrl { CoreService::~CoreService() { } diff --git a/src/gui/ui-bus.hpp b/src/gui/ui-bus.hpp index 68c9a6b0f..db01ee4ab 100644 --- a/src/gui/ui-bus.hpp +++ b/src/gui/ui-bus.hpp @@ -138,6 +138,7 @@ namespace gui { ///////////////////////////////////////////////////////////////////////////////////TICKET #959 : scheduled for termination.... namespace ctrl { class CoreService; + class BusTerm; } @@ -159,7 +160,8 @@ namespace gui { public: UiBus(); ~UiBus(); - + + ctrl::BusTerm& getAccessPoint(); }; diff --git a/src/gui/workspace/interaction-director.cpp b/src/gui/workspace/interaction-director.cpp index ab394577b..08f567de5 100644 --- a/src/gui/workspace/interaction-director.cpp +++ b/src/gui/workspace/interaction-director.cpp @@ -2,7 +2,6 @@ interactionDirector - Global UI Manager Copyright (C) Lumiera.org - 2008, Joel Holdsworth 2017, Hermann Vosseler This program is free software; you can redistribute it and/or @@ -27,326 +26,49 @@ */ -#include "gui/gtk-lumiera.hpp" -#include "gui/config-keys.hpp" -#include "gui/ui-bus.hpp" +#include "gui/gtk-base.hpp" #include "gui/workspace/interaction-director.hpp" -#include "gui/workspace/actions.hpp" -#include "gui/workspace/window-list.hpp" -#include "gui/workspace/workspace-window.hpp" -#include "lib/searchpath.hpp" -#include "lib/util.hpp" +#include "gui/ui-bus.hpp" +#include "gui/ctrl/bus-term.hpp" +#include "proc/mobject/session/root.hpp" +#include "lib/diff/tree-mutator.hpp" +//#include "gui/ui-bus.hpp" +//#include "lib/util.hpp" -#include -#include -#include -#include +//#include +//#include -using Gtk::IconSize; -using Gtk::IconFactory; - -using util::cStr; -using util::isnil; -using std::list; -using std::shared_ptr; +//using util::isnil; +//using std::list; +//using std::shared_ptr; +using lib::diff::TreeMutator; namespace gui { namespace workspace { - namespace fsys = boost::filesystem; - IconSize UiManager::GiantIconSize = Gtk::ICON_SIZE_INVALID; - IconSize UiManager::MenuIconSize = Gtk::ICON_SIZE_INVALID; - - - // dtors via smart-ptr invoked from here... + // emit VTables here... InteractionDirector::~InteractionDirector() { } InteractionDirector::InteractionDirector (UiBus& bus) - : Gtk::UIManager() - , uiBus_(bus) - , windowList_{new WindowList{*this}} - , actions_{new Actions{[this]() ->WorkspaceWindow& { return windowList_->findActiveWindow();}}} - , iconSearchPath_{Config::get (KEY_ICON_PATH)} - , resourceSerachPath_{Config::get (KEY_UIRES_PATH)} - { - initGlobalUI(); - } + : model::Controller(proc::mobject::session::Root::getID(), bus.getAccessPoint()) + { } - /** - * Initialise the interface manager on application start. - * Register the icon configuration and sizes and lookup - * all the icons -- either from the default theme of via - * the given Lumiera icon search paths (see \c setup.ini ). - * @see lumiera::Config - */ void - UiManager::initGlobalUI () + InteractionDirector::buildMutator (TreeMutator::Handle buffer) { - Glib::set_application_name (Config::get (KEY_TITLE)); +// using Attrib = std::pair; +// using lib::diff::collection; - registerAppIconSizes(); - registerStockItems(); - - setTheme (Config::get (KEY_STYLESHEET)); - - actions_->populateMainActions (*this); - } - - - /** - * @remarks this function is invoked once from the main application object, - * immediately prior to starting the GTK event loop. */ - void - UiManager::createApplicationWindow() - { - if (windowList_->empty()) - windowList_->newWindow(); - } - - - void - UiManager::updateWindowFocusRelatedActions() - { - UNIMPLEMENTED ("how to handle activation of menu entries depending on window focus"); ////////TICKET #1076 find out how to handle this properly - //////see Actions::updateActionState() + buffer.create ( + TreeMutator::build() + ); + UNIMPLEMENTED ("create a sensible binding between root-controller and root-model element"); } - - void - UiManager::setTheme (string const& stylesheetName) - { - auto screen = Gdk::Screen::get_default(); - auto css_provider = Gtk::CssProvider::create(); - try - { - css_provider->load_from_path (lib::resolveModulePath (stylesheetName, resourceSerachPath_)); - /////////////////////////////////TICKET #953 should detect and notify CSS parsing errors. CssProvider offers a signal for this purpose - /////////////////////////////////TICKET #953 ...seems to be supported properly starting with gtkmm 3.18 (Debian/Jessie has 3.14) - } - catch(Glib::Error const& failure) - { - WARN(gui, "Failure while loading stylesheet '%s': %s", cStr(stylesheetName), cStr(failure.what())); - } - - Gtk::StyleContext::add_provider_for_screen (screen, css_provider, - GTK_STYLE_PROVIDER_PRIORITY_USER); - } - - - - Cairo::RefPtr - UiManager::readStyleColourProperty (Gtk::Widget& widget - ,const gchar * property_name - ,guint16 red, guint16 green, guint16 blue) - { - REQUIRE (property_name); - - // TODO: Can we get rid of the GdkColor completely here? - GdkColor *color; - gtk_widget_style_get(widget.gobj(), property_name, &color, NULL); - - Cairo::RefPtr pattern; - // Did the color load successfully? - if (color != NULL) - { - pattern = Cairo::SolidPattern::create_rgb ( (double)color->red / 0xFFFF, - (double)color->green / 0xFFFF, - (double)color->blue / 0xFFFF); - } - else - { - WARN(gui, "%s style value failed to load", property_name); - - pattern = Cairo::SolidPattern::create_rgb ( red, green, blue ); - } - - return pattern; - } - - - void - UiManager::registerAppIconSizes() - { - if(GiantIconSize == Gtk::ICON_SIZE_INVALID) - GiantIconSize = IconSize::register_new ("giant", 48, 48); - if(MenuIconSize == Gtk::ICON_SIZE_INVALID) - MenuIconSize = IconSize::register_new ("menu", 16, 16); - } - - - /** - * Registers application stock items: - * icons and labels associated with IDs - */ - void - UiManager::registerStockItems() - { - Glib::RefPtr factory = Gtk::IconFactory::create(); - - addStockIconSet(factory, "panel-assets", "panel_assets", _("_Assets")); - addStockIconSet(factory, "panel-viewer", "panel_viewer", _("_Viewer")); - addStockIconSet(factory, "panel-timeline", "panel_timeline",_("_Timeline")); - addStockIconSet(factory, "panel-timeline", "panel_timeline_obsolete",_("_ZombieTimeline")); - - addStockIconSet(factory, "window-new", "new_window", _("New _Window")); - - addStockIconSet(factory, "tool-arrow", "tool_arrow", _("_Arrow")); - addStockIconSet(factory, "tool-i-beam", "tool_i_beam", _("_I-Beam")); - - addStockIconSet(factory, "track-disabled", "track_disabled",_("Track Disabled")); - addStockIconSet(factory, "track-enabled", "track_enabled", _("Track Enabled")); - addStockIconSet(factory, "track-locked", "track_locked", _("Track Locked")); - addStockIconSet(factory, "track-unlocked", "track_unlocked",_("Track Unlocked")); - - factory->add_default(); //Add factory to list of factories. - } - - - bool - UiManager::addStockIconSet (Glib::RefPtr const& factory - ,cuString& icon_name - ,cuString& id - ,cuString& label) - { - Glib::RefPtr icon_set = Gtk::IconSet::create(); - - // Load all the sizes, wildcarding the first, largest icon to be loaded - bool no_icons = true; - no_icons &= !addStockIcon( - icon_set, icon_name, GiantIconSize, no_icons); - no_icons &= !addStockIcon( - icon_set, icon_name, Gtk::ICON_SIZE_BUTTON, no_icons); - no_icons &= !addStockIcon( - icon_set, icon_name, Gtk::ICON_SIZE_MENU, no_icons); - no_icons &= !addStockIcon( - icon_set, icon_name, Gtk::ICON_SIZE_LARGE_TOOLBAR, no_icons); - no_icons &= !addStockIcon( - icon_set, icon_name, MenuIconSize, no_icons); - - if(no_icons) - { - // No icons were loaded - ERROR (gui, "Unable to load icon '%s'", cStr(icon_name)); - return false; - } - - // Add the icon set to the icon factory - const Gtk::StockID stock_id(id); - factory->add(stock_id, icon_set); - Gtk::Stock::add(Gtk::StockItem(stock_id, label)); //////////////////////TICKET #1030 : use "icon names" instead of Gtk::StockItem - return true; - } - - - bool - UiManager::addStockIcon (Glib::RefPtr const& icon_set - ,cuString& icon_name - ,Gtk::IconSize size - ,bool wildcard) - { - // Try the icon theme - if (addThemeIconSource(icon_set, icon_name, size, wildcard)) - return true; - - // Try to resolve the icon via the configured search path - lib::SearchPathSplitter iconLocations (iconSearchPath_); - while (iconLocations) - if (addNonThemeIconSource (icon_set - ,iconLocations.next() - ,icon_name - ,size - ,wildcard)) - return true; - - return false; // icon not found - } - - - bool - UiManager::addThemeIconSource (Glib::RefPtr const& icon_set - ,cuString& 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 - Glib::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 - Gtk::IconInfo info = theme->lookup_icon(icon_name, width, (Gtk::IconLookupFlags)0); - - if (!info) return false; // unable to resolve Icon - - cuString path(info.get_filename()); - return addStockIconFromPath(path, icon_set, size, wildcard); - } - - - bool - UiManager::addNonThemeIconSource (Glib::RefPtr const& icon_set - ,cuString& base_dir - ,cuString& 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 - cuString path(Glib::ustring::compose("%1/%2x%3/%4.png", - base_dir, width, height, icon_name)); - return addStockIconFromPath(path, icon_set, size, wildcard); - } - - - bool - UiManager::addStockIconFromPath (string path - ,Glib::RefPtr const& icon_set - ,Gtk::IconSize size - ,bool wildcard) - { - if (!fsys::exists (path)) return false; - - try { - Gtk::IconSource source; - source.set_pixbuf(Gdk::Pixbuf::create_from_file(path)); - source.set_size_wildcarded(wildcard); - source.set_size(size); - - icon_set->add_source(source); - - return true; - } - - catch(Glib::Exception const& ex) - { - WARN (gui, "Failure when accessing icon '%s'. Problem: %s", cStr(path), cStr(ex.what())); - return false; - } - } - - - void - UiManager::allowCloseWindow (bool yes) - { - this->get_action("/MenuBar/WindowMenu/WindowCloseWindow") - ->set_sensitive (yes); - } - - }}// namespace gui::workspace diff --git a/src/gui/workspace/interaction-director.hpp b/src/gui/workspace/interaction-director.hpp index 2a0f34063..a5df50837 100644 --- a/src/gui/workspace/interaction-director.hpp +++ b/src/gui/workspace/interaction-director.hpp @@ -2,7 +2,6 @@ INTERACTION-DIRECTOR.hpp - Global UI Manager Copyright (C) Lumiera.org - 2008, Joel Holdsworth 2017, Hermann Vosseler This program is free software; you can redistribute it and/or @@ -24,15 +23,27 @@ /** @file interaction-director.hpp ** The top-level controller to connect model and user interaction state. - ** The central UiManager instance is owned by the GtkLumiera object and initialised in GTK-main. - ** It establishes and wires the top-level entities of the UI-Layer and thus, indirectly offers - ** services to provide Icons and other resources, to open and manage workspace windows, to - ** form and issue (global) actions and to delve into the UI representation of top-level parts - ** of the session model. Notable connections established herein: - ** - connection to the [UI-Bus](\ref ui-bus.hpp) - ** - the global Actions available though the menu - ** - the WindowList - ** - the InteractionDirector (top-level controller) + ** Within the Lumiera UI, relevant entities from the session model are mapped onto and represented + ** by corresponding [UI-Elements](\ref model::Tangible). Consequently, there is a hierarchy of + ** interrelated UI elements mirroring the hierarchy within the session model. And, while in the + ** latter, there is a _conceptual root node_ to correspond to the session itself, within the UI + ** there is a top-level controller to mirror and represent that root element: The InteractionDirector. + ** + ** For one, the InteractionDirector represents and exposes parts of the model as seen from top level. + ** Especially this means that, through the InteractionDirector, it is possible to open and enter the + ** UI to work with the timeline(s), with the assets and with the global session configuration. + ** Moreover, this top-level controller allows to issue likewise global actions regarding those + ** entities: + ** - create / modify / delete timeline(s) + ** - create / modify / sequences + ** - save, close, open and create a session + ** + ** And, secondly, beyond those top-level model-related activities, the InteractionDirector serves + ** as link between model entities, actions to be performed onto them and the transient yet global + ** user interaction state. The latter means anything related to _the current window_, + ** _the current focus_, _the current work-site_, the current interface controller technology used etc. + ** Obviously, the InteractionDirector can not _handle_ all those heavyweight concerns; but it connects + ** the involved parts and (re)directs the information flow towards the proper recipient to handle it. ** ** @see gtk-lumiera.hpp ** @see ui-bus.hpp @@ -42,190 +53,48 @@ #ifndef GUI_WORKSPACE_INTERACTION_DIRECTOR_H #define GUI_WORKSPACE_INTERACTION_DIRECTOR_H -#include "gui/gtk-base.hpp" +//#include "gui/gtk-base.hpp" +#include "gui/model/controller.hpp" -#include -#include -#include +//#include +//#include +//#include #include namespace gui { - namespace model { class Project; } ////////////////////////////////////////////////////TICKET #1048 : rectify UI lifecycle - namespace controller { class Controller; } ////////////////////////////////////////////////////TICKET #1048 : rectify UI lifecycle - class UiBus; namespace workspace { - using std::unique_ptr; - using std::string; +//using std::string; - class Actions; - class WindowList; +//class Actions; +//class WindowList; /** - * Manage global concerns regarding a coherent user interface. - * Offers access to some global UI resources, and establishes - * further global services to create workspace windows, to bind - * menu / command actions and to enter the top-level model parts. + * Top-level controller to establish a link between the model + * and transient user interaction state (focus, current window) */ class InteractionDirector - : public Gtk::UIManager - , boost::noncopyable + : public model::Controller { - UiBus& uiBus_; - unique_ptr windowList_; - unique_ptr actions_; + ////TODO: what is the model equivalent represented here??? - string iconSearchPath_; - string resourceSerachPath_; + /** set up a binding to allow some top-level UI state + * to be treated as part of the session model + * @see tree-mutator.hpp + */ + void buildMutator (lib::diff::TreeMutator::Handle) override; public: - - /** The registered icon size for giant 48x48 px icons. - * @remarks This value is set to BuiltinIconSize::ICON_SIZE_INVALID - * until register_giant_icon_size is called. - */ - static Gtk::IconSize GiantIconSize; - - /** The registered icon size for giant 16x16 px icons. - * @remarks This value is set to BuiltinIconSize::ICON_SIZE_INVALID - * until register_app_icon_sizes is called. - */ - static Gtk::IconSize MenuIconSize; - - - public: - /** - * There is one global UiManager instance, - * which is created by [the Application](\ref GtkLumiera) - * and allows access to the UI-Bus backbone. The UiManager itself - * is _not a ctrl::Controller,_ and thus not directly connected to the Bus. - * Rather, supports the top-level windows for creating a consistent interface. - */ InteractionDirector (UiBus& bus); ~InteractionDirector (); - /** - * Set up the first top-level application window. - * This triggers the build-up of the user interface widgets. - */ - void createApplicationWindow(); - - /** @todo find a solution how to enable/disable menu entries according to focus - * /////////////////////////////////////////////////TICKET #1076 find out how to handle this properly - */ - void updateWindowFocusRelatedActions(); - - /** - * Sets the theme to use for the Lumiera GUI. - * @param stylesheetName GTK CSS stylesheet to load from the resourceSearchPath_ - * @throw error::Config if this stylesheet can't be resolved on the searchpath - * @see #init - * @see lumiera::Config - */ - void setTheme (string const& stylesheetName); - - /** - * A utility function which reads a colour style from the GTK Style. - * @param widget The widget to load the style out of. - * @param property_name The name of the style property to load. - * @param red The fallback red intensity. - * @param green The fallback green intensity. - * @param blue The fallback blue intensity. - * @return The loaded colour. - */ - static Cairo::RefPtr - readStyleColourProperty (Gtk::Widget &widget, const gchar *property_name, - guint16 red, guint16 green, guint16 blue); - - void allowCloseWindow (bool yes); - - private: - void initGlobalUI (); - - void registerAppIconSizes(); - void registerStockItems(); - - /** - * Adds an icon (in different sizes) to the icon factory. - * @param factory The factory to add the icon to. - * @param icon_name The file name of the icon to add. - * @param id The id name of the icon. - * @param label The user readable icon name for this icon. - * @return \c true if the icon was successfully loaded, - * returns \c false otherwise. - */ - bool - addStockIconSet (Glib::RefPtr const& factory - ,cuString& icon_name - ,cuString& id - ,cuString& label); - - /** - * Loads an icon, searching standard icon locations, - * and adds it to an icon set. - * @param icon_set The icon set to add the icon to. - * @param icon_name The file name of the icon to load. - * @param size The size of the icon to load. - * @param wildcard \c true if this icon is to be wildcarded. - * @return \c true if the icon was loaded successfully. - */ - bool - addStockIcon (Glib::RefPtr const& icon_set - ,cuString& 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 \c true if this icon is to be wildcarded. - * @return \c true if the icon was loaded successfully. - */ - bool - addThemeIconSource (Glib::RefPtr const& icon_set - ,cuString& icon_name - ,Gtk::IconSize size - ,bool wildcard); - - /** - * 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. - * @param size The size of the icon to load. - * @param wildcard \c true if this icon is to be wildcarded. - * @return \c true if the icon was loaded successfully. - */ - bool - addNonThemeIconSource (Glib::RefPtr const& icon_set - ,cuString& base_dir - ,cuString& 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 \c true if this icon is to be wildcarded. - * @return \c true if the icon was loaded successfully. - */ - bool - addStockIconFromPath (string path - ,Glib::RefPtr const& icon_set - ,Gtk::IconSize size - ,bool wildcard); - private: diff --git a/src/gui/workspace/ui-manager.cpp b/src/gui/workspace/ui-manager.cpp index 3f3247a14..d89fa86c6 100644 --- a/src/gui/workspace/ui-manager.cpp +++ b/src/gui/workspace/ui-manager.cpp @@ -38,6 +38,7 @@ #include "gui/workspace/actions.hpp" #include "gui/workspace/window-list.hpp" #include "gui/workspace/workspace-window.hpp" +#include "gui/workspace/interaction-director.hpp" #include "lib/searchpath.hpp" #include "lib/util.hpp" @@ -71,7 +72,8 @@ namespace workspace { UiManager::UiManager (UiBus& bus) : Gtk::UIManager() - , uiBus_(bus) + , uiBus_{bus} + , director_{new InteractionDirector{bus}} , windowList_{new WindowList{*this}} , actions_{new Actions{[this]() ->WorkspaceWindow& { return windowList_->findActiveWindow();}}} , iconSearchPath_{Config::get (KEY_ICON_PATH)} diff --git a/src/gui/workspace/ui-manager.hpp b/src/gui/workspace/ui-manager.hpp index 4c145bbea..d5b016d1d 100644 --- a/src/gui/workspace/ui-manager.hpp +++ b/src/gui/workspace/ui-manager.hpp @@ -64,6 +64,7 @@ namespace workspace { class Actions; class WindowList; + class InteractionDirector; @@ -79,8 +80,9 @@ namespace workspace { { UiBus& uiBus_; - unique_ptr windowList_; - unique_ptr actions_; + unique_ptr director_; + unique_ptr windowList_; + unique_ptr actions_; string iconSearchPath_; string resourceSerachPath_; diff --git a/src/proc/mobject/session/root.cpp b/src/proc/mobject/session/root.cpp index 1696b6e85..a40fe6679 100644 --- a/src/proc/mobject/session/root.cpp +++ b/src/proc/mobject/session/root.cpp @@ -25,6 +25,7 @@ #include "common/query/defs-manager.hpp" using lumiera::query::DefsManager; +using lib::idi::EntryID; namespace proc { namespace mobject { @@ -38,6 +39,20 @@ namespace session { } + /** get an unique ID to identify "the model root". + * Actually this ID is statically fixed and will be used by the UI + * to connect to and talk to the session model at top-level + * @return an embedded LUID tagged with the type of the session::Root. + * This ID is suitable to be used in model diff and as ID on + * the UI-Bus to address the corresponding representations + * in Proc-Layer and UI-Layer + */ + lib::idi::EntryID + Root::getID() + { + return EntryID("session"); + } + /** @todo validity self-check of the model root * should do substantial checks; the idea is diff --git a/src/proc/mobject/session/root.hpp b/src/proc/mobject/session/root.hpp index 871bad337..a5dd7bdac 100644 --- a/src/proc/mobject/session/root.hpp +++ b/src/proc/mobject/session/root.hpp @@ -26,6 +26,7 @@ #include "proc/mobject/session/meta.hpp" #include "proc/mobject/builder/buildertool.hpp" +#include "lib/idi/entry-id.hpp" namespace lumiera { @@ -70,6 +71,8 @@ namespace session { public: Root (lumiera::query::DefsManager&); + static lib::idi::EntryID getID(); + DEFINE_PROCESSABLE_BY (builder::BuilderTool); }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index cb0299879..600146c31 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -1670,7 +1670,8 @@ - + + @@ -1847,8 +1848,12 @@ - + + + + + @@ -1944,6 +1949,8 @@ + + @@ -1969,7 +1976,7 @@ - + @@ -1988,6 +1995,11 @@ + + + + + @@ -2059,12 +2071,12 @@ - + - + - + @@ -9973,6 +9985,9 @@ + + +