2008-04-20 00:16:27 +02:00
/*
2015-05-29 04:44:58 +02:00
WindowManager - Global UI Manager
2010-12-17 23:28:49 +01:00
2008-04-20 00:16:27 +02:00
Copyright ( C ) Lumiera . org
2008 , Joel Holdsworth < joel @ airwebreathe . org . uk >
2010-12-17 23:28:49 +01:00
2008-04-20 00:16:27 +02:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
published by the Free Software Foundation ; either version 2 of
the License , or ( at your option ) any later version .
2008-04-20 00:16:27 +02:00
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 .
2010-12-17 23:28:49 +01:00
2008-04-20 00:16:27 +02:00
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 0213 9 , USA .
2010-12-17 23:28:49 +01:00
2008-04-20 00:16:27 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-02-06 21:23:34 +01:00
# include "gui/window-manager.hpp"
# include "gui/gtk-lumiera.hpp"
# include "gui/workspace/workspace-window.hpp"
2011-02-07 00:54:16 +01:00
# include "lib/searchpath.hpp"
# include "lib/util.hpp"
2014-10-07 03:13:58 +02:00
# include <gtkmm/stylecontext.h>
2011-02-07 00:54:16 +01:00
# include <boost/filesystem.hpp>
2014-04-03 22:42:48 +02:00
# include <memory>
# include <list>
2011-02-07 00:54:16 +01:00
using util : : cStr ;
2014-04-03 22:42:48 +02:00
using std : : list ;
using std : : shared_ptr ;
2008-04-20 00:16:27 +02:00
2015-05-29 04:44:58 +02:00
using namespace Gtk ; ///////////////////////////TODO explicit using directives please!
2008-08-13 20:15:13 +02:00
using namespace Glib ;
2009-01-31 19:12:04 +01:00
using namespace gui : : workspace ;
2008-08-13 20:15:13 +02:00
2011-02-07 00:54:16 +01:00
namespace fsys = boost : : filesystem ;
2008-04-20 00:16:27 +02:00
namespace gui {
2008-10-10 11:56:07 +02:00
2015-05-29 04:44:58 +02:00
IconSize WindowManager : : GiantIconSize = ICON_SIZE_INVALID ;
IconSize WindowManager : : MenuIconSize = ICON_SIZE_INVALID ;
2011-02-07 00:54:16 +01:00
2014-10-07 03:13:58 +02:00
2015-05-29 04:44:58 +02:00
void
WindowManager : : init ( string const & iconPath , string const & resourcePath )
{
this - > iconSearchPath_ = iconPath ;
this - > resourceSerachPath_ = resourcePath ;
registerAppIconSizes ( ) ;
registerStockItems ( ) ;
}
2009-01-31 19:12:04 +01:00
2015-05-29 04:44:58 +02:00
void
WindowManager : : setTheme ( string const & stylesheetName )
{
auto screen = Gdk : : Screen : : get_default ( ) ;
auto css_provider = CssProvider : : create ( ) ;
2015-11-03 05:04:06 +01:00
try
{
css_provider - > load_from_path ( lib : : resolveModulePath ( stylesheetName , resourceSerachPath_ ) ) ;
2015-05-29 04:44:58 +02:00
/////////////////////////////////TICKET #953 should detect and notify CSS parsing errors. CssProvider offers a signal for this purpose
2015-11-03 05:04:06 +01:00
/////////////////////////////////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 ( ) ) ) ;
}
2015-05-29 04:44:58 +02:00
StyleContext : : add_provider_for_screen ( screen , css_provider ,
GTK_STYLE_PROVIDER_PRIORITY_USER ) ;
}
2009-01-31 19:12:04 +01:00
2009-01-31 19:49:44 +01:00
2015-05-29 04:44:58 +02:00
void
WindowManager : : newWindow ( gui : : model : : Project & source_project , gui : : controller : : Controller & source_controller )
{
shared_ptr < WorkspaceWindow > 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 ) ;
2016-12-23 04:23:03 +01:00
list < shared_ptr < WorkspaceWindow > > : : iterator iterator { windowList . begin ( ) } ;
2015-05-29 04:44:58 +02:00
while ( iterator ! = windowList . end ( ) )
{
shared_ptr < WorkspaceWindow > workspace_window ( * iterator ) ;
REQUIRE ( workspace_window ) ;
Glib : : RefPtr < Gdk : : Window > 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 ;
2016-12-23 04:23:03 +01:00
list < shared_ptr < WorkspaceWindow > > : : iterator iterator { windowList . begin ( ) } ;
2015-05-29 04:44:58 +02:00
while ( iterator ! = windowList . end ( ) )
{
shared_ptr < WorkspaceWindow > workspace_window ( * iterator ) ;
REQUIRE ( workspace_window ) ;
workspace_window - > set_close_window_sensitive ( enable ) ;
2009-01-31 19:12:04 +01:00
iterator + + ;
2015-05-29 04:44:58 +02:00
}
}
2008-08-13 20:15:13 +02:00
2015-05-29 04:44:58 +02:00
Cairo : : RefPtr < Cairo : : SolidPattern >
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 < Cairo : : SolidPattern > 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 ;
}
2008-08-13 20:15:13 +02:00
2009-01-31 17:31:15 +01:00
2015-05-29 04:44:58 +02:00
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 ) ;
}
2008-10-23 00:11:23 +02:00
2008-08-13 20:15:13 +02:00
2015-05-29 04:44:58 +02:00
void
WindowManager : : registerStockItems ( )
{
Glib : : RefPtr < IconFactory > factory = IconFactory : : create ( ) ;
addStockIconSet ( factory , " panel-assets " , " panel_assets " , _ ( " _Assets " ) ) ;
addStockIconSet ( factory , " panel-viewer " , " panel_viewer " , _ ( " _Viewer " ) ) ;
2016-10-26 19:33:00 +02:00
addStockIconSet ( factory , " panel-timeline " , " panel_timeline " , _ ( " _Timeline " ) ) ;
addStockIconSet ( factory , " panel-timeline " , " panel_timeline_obsolete " , _ ( " _ZombieTimeline " ) ) ;
2015-05-29 04:44:58 +02:00
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.
}
2008-10-10 11:56:07 +02:00
2015-05-29 04:44:58 +02:00
bool
WindowManager : : addStockIconSet ( Glib : : RefPtr < IconFactory > const & factory
, cuString & icon_name
, cuString & id
, cuString & label )
{
Glib : : RefPtr < Gtk : : IconSet > 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 ) ;
2016-10-26 19:33:00 +02:00
Gtk : : Stock : : add ( Gtk : : StockItem ( stock_id , label ) ) ; //////////////////////TICKET #1030 : use "icon names" instead of Gtk::StockItem
2009-01-31 17:31:15 +01:00
return true ;
2015-05-29 04:44:58 +02:00
}
2008-08-13 20:15:13 +02:00
2015-05-29 04:44:58 +02:00
bool
WindowManager : : addStockIcon ( Glib : : RefPtr < Gtk : : IconSet > const & icon_set
, cuString & icon_name
, Gtk : : IconSize size
, bool wildcard )
{
// Try the icon theme
if ( addThemeIconSource ( icon_set , icon_name , size , wildcard ) )
2011-02-07 00:54:16 +01:00
return true ;
2015-05-29 04:44:58 +02:00
// 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
}
2011-02-07 00:54:16 +01:00
2009-01-31 17:31:15 +01:00
2015-05-29 04:44:58 +02:00
bool
WindowManager : : addThemeIconSource ( Glib : : RefPtr < Gtk : : IconSet > 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 < Gtk : : IconTheme > theme = Gtk : : IconTheme : : get_default ( ) ;
REQUIRE ( theme ) ;
2016-10-26 19:33:00 +02:00
///////////////////////////////////////////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
2015-05-29 04:44:58 +02:00
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 ) ;
}
2009-02-01 19:56:49 +01:00
2011-02-07 00:54:16 +01:00
2015-05-29 04:44:58 +02:00
bool
WindowManager : : addNonThemeIconSource ( Glib : : RefPtr < Gtk : : IconSet > 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 ) ;
}
2009-01-31 17:31:15 +01:00
2008-10-08 00:02:27 +02:00
2015-05-29 04:44:58 +02:00
bool
WindowManager : : addStockIconFromPath ( string path
, Glib : : RefPtr < Gtk : : IconSet > 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 ;
}
}
2011-02-07 00:54:16 +01:00
2015-05-29 04:44:58 +02:00
} // namespace gui