/* WindowManager - Global UI Manager Copyright (C) Lumiera.org 2008, Joel Holdsworth 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. 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. 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., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************/ #include "gui/window-manager.hpp" #include "gui/gtk-lumiera.hpp" #include "gui/workspace/workspace-window.hpp" #include "lib/searchpath.hpp" #include "lib/util.hpp" #include #include #include #include using util::cStr; using std::list; using std::shared_ptr; using namespace Gtk; ///////////////////////////TODO explicit using directives please! using namespace Glib; using namespace gui::workspace; namespace fsys = boost::filesystem; namespace gui { IconSize WindowManager::GiantIconSize = ICON_SIZE_INVALID; IconSize WindowManager::MenuIconSize = ICON_SIZE_INVALID; void WindowManager::init (string const& iconPath, string const& resourcePath) { this->iconSearchPath_ = iconPath; this->resourceSerachPath_ = resourcePath; registerAppIconSizes(); registerStockItems(); } void WindowManager::setTheme (string const& stylesheetName) { auto screen = Gdk::Screen::get_default(); auto css_provider = 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())); } StyleContext::add_provider_for_screen (screen, css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); } void WindowManager::newWindow (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(); updateCloseWindowInMenus(); } 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); Glib::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(); } updateCloseWindowInMenus(); // Unless this is false, the window won't close return false; } void WindowManager::updateCloseWindowInMenus() { bool enable = windowList.size() > 1; list< shared_ptr >::iterator iterator = windowList.begin(); while (iterator != windowList.end()) { shared_ptr workspace_window(*iterator); REQUIRE(workspace_window); workspace_window->set_close_window_sensitive(enable); iterator++; } } Cairo::RefPtr WindowManager::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 WindowManager::registerAppIconSizes() { if(GiantIconSize == ICON_SIZE_INVALID) GiantIconSize = IconSize::register_new ("giant", 48, 48); if(MenuIconSize == ICON_SIZE_INVALID) MenuIconSize = IconSize::register_new ("menu", 16, 16); } void WindowManager::registerStockItems() { Glib::RefPtr factory = IconFactory::create(); addStockIconSet(factory, "panel-assets", "panel_assets", _("_Assets")); addStockIconSet(factory, "panel-timeline", "panel_timeline",_("_Timeline")); addStockIconSet(factory, "panel-viewer", "panel_viewer", _("_Viewer")); 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 WindowManager::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, ICON_SIZE_BUTTON, no_icons); no_icons &= !addStockIcon( icon_set, icon_name, ICON_SIZE_MENU, no_icons); no_icons &= !addStockIcon( icon_set, icon_name, 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)); return true; } bool WindowManager::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 WindowManager::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"); IconInfo info = theme->lookup_icon(icon_name, width, (IconLookupFlags)0); if (!info) return false; // unable to resolve Icon cuString path(info.get_filename()); return addStockIconFromPath(path, icon_set, size, wildcard); } bool WindowManager::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(ustring::compose("%1/%2x%3/%4.png", base_dir, width, height, icon_name)); return addStockIconFromPath(path, icon_set, size, wildcard); } bool WindowManager::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; } } }// namespace gui