2008-12-05 11:07:01 +01:00
/*
2011-12-23 03:55:01 +01:00
NotificationService - public service allowing to push information into the GUI
2010-12-17 23:28:49 +01:00
2008-12-05 11:07:01 +01:00
Copyright ( C ) Lumiera . org
2008 , Hermann Vosseler < Ichthyostega @ web . de >
2010-12-17 23:28:49 +01:00
2008-12-05 11:07:01 +01: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-12-05 11:07:01 +01: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-12-05 11:07:01 +01: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-12-05 11:07:01 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-12-12 02:20:58 +01:00
/** @file notification-service.cpp
* * Implementation of notifications and updates within the GUI .
* * This is the actual service implementation and runs within the GUI plugin .
* *
2017-08-10 19:26:47 +02:00
* * Since GTK is _not threadsafe by design , _ any external invocation passed through
* * this facade service will be dispatched explicitly into the GTK event loop thread .
* * The implementation of this dispatch is based upon ` Glib : : Dispatcher ` and thus
* * requires this service instance to be created from within the thread performing
* * the GTK event loop . Moreover , to avoid segmentation faults on shutdown , the
* * lifespan of this service instance must exceed the running of the event loop ,
* * since otherwise the event loop might invoke a lambda bound to the ` this `
* * pointer of a NotificationService already decommissioned . The setup of the
* * standard Lumiera UI top - level context ensures this is the case , since the
* * UiManager : : performMainLoop ( ) maintains the NotificationService instance
* * and also performs the blocking ` gtk_main ( ) ` call . Consequently , any
* * invocation added from other threads after leaving the GTK main loop
* * but before closing the GuiNotification facade will just be enqueued ,
* * but then dropped on destruction of the UiDispatcher PImpl .
* *
2017-01-20 04:18:57 +01:00
* * @ todo 1 / 2017 find a solution for passing diff messages /////////////////////////////////////////////////TICKET #1066
* *
2017-08-10 19:26:47 +02:00
* * @ see ui - dispatcher . hpp
* *
2016-12-12 02:20:58 +01:00
*/
2008-12-05 11:07:01 +01:00
2016-11-03 18:20:10 +01:00
2017-08-04 19:07:05 +02:00
# include "gui/ctrl/ui-manager.hpp"
2017-08-10 16:24:36 +02:00
# include "gui/ctrl/ui-dispatcher.hpp"
2017-08-11 02:00:54 +02:00
# include "gui/ctrl/mutation-message.hpp"
2009-01-10 15:29:11 +01:00
# include "gui/notification-service.hpp"
2017-08-10 17:14:44 +02:00
# include "lib/diff/gen-node.hpp"
2009-01-25 00:24:42 +01:00
# include "include/logging.h"
2008-12-17 17:53:32 +01:00
# include "lib/util.hpp"
2008-12-05 11:07:01 +01:00
2008-12-06 02:19:52 +01:00
extern " C " {
2014-10-15 19:45:12 +02:00
# include "common/interface-descriptor.h"
2008-12-06 02:19:52 +01:00
}
2008-12-05 11:07:01 +01:00
# include <string>
2017-08-10 17:14:44 +02:00
using lib : : diff : : GenNode ;
2017-08-04 19:07:05 +02:00
using lib : : diff : : TreeMutator ;
2017-08-11 02:00:54 +02:00
using gui : : ctrl : : MutationMessage ;
2017-08-10 16:24:36 +02:00
using gui : : ctrl : : UiDispatcher ;
2017-08-04 19:07:05 +02:00
using gui : : ctrl : : BusTerm ;
using std : : string ;
using util : : cStr ;
2009-01-10 15:29:11 +01:00
2008-12-05 11:07:01 +01:00
namespace gui {
2009-01-10 15:29:11 +01:00
2017-08-10 17:14:44 +02:00
/** @internal helper to _move_ a given UI-Bus message (GenNode)
* into the closure of an event - lambda , which then is handed over
* to the UI event thread through the dispatcher queue .
*/
void
NotificationService : : dispatchMsg ( ID uiElement , lib : : diff : : GenNode & & uiMessage )
{
dispatch_ - > event ( [ = ] ( )
{
this - > mark ( uiElement , uiMessage ) ;
} ) ;
}
2009-01-10 15:29:11 +01:00
void
2017-08-10 20:29:13 +02:00
NotificationService : : displayInfo ( NotifyLevel severity , string const & text )
2009-01-10 15:29:11 +01:00
{
2017-08-10 19:26:47 +02:00
INFO ( gui , " @GUI: display '%s' as notification message. " , cStr ( text ) ) ; ///////////////////////////////////TICKET #1102 : build a message display box in the UI
2017-08-04 19:07:05 +02:00
////////////////////////TODO actually push the information to the GUI ///////////////////////////////////TICKET #1098 : use a suitable Dispatcher
2009-01-10 15:29:11 +01:00
}
2017-01-20 04:18:57 +01:00
void
NotificationService : : markError ( ID uiElement , string const & text )
{
2017-08-10 17:14:44 +02:00
dispatchMsg ( uiElement , GenNode { " Error " , text } ) ;
2017-01-20 04:18:57 +01:00
}
void
NotificationService : : markNote ( ID uiElement , string const & text )
{
2017-08-10 17:14:44 +02:00
dispatchMsg ( uiElement , GenNode { " Message " , text } ) ;
2017-01-20 04:18:57 +01:00
}
void
2017-08-11 02:00:54 +02:00
NotificationService : : mutate ( ID uiElement , DiffMessage & & diff )
2017-01-20 04:18:57 +01:00
{
2017-08-11 02:00:54 +02:00
dispatch_ - > event ( [ = ] ( )
{
MutationMessage diffHolder { DiffMessage ( diff ) } ; //////////////////////////////////TICKET #1066 : unnecessary repackaging; could get rid of MutationMessage altogether
this - > change ( uiElement , diffHolder ) ;
} ) ;
2017-01-20 04:18:57 +01:00
}
2009-01-10 15:29:11 +01:00
void
NotificationService : : triggerGuiShutdown ( string const & cause )
{
2009-01-24 03:13:54 +01:00
NOTICE ( gui , " @GUI: shutdown triggered with explanation '%s'.... " , cStr ( cause ) ) ;
2017-08-10 20:57:26 +02:00
displayInfo ( NOTE_ERROR , cause ) ;
dispatch_ - > event ( [ = ] ( )
{
uiManager_ . terminateUI ( ) ;
} ) ;
2009-01-10 15:29:11 +01:00
}
2008-12-05 11:07:01 +01:00
2017-01-19 05:18:06 +01:00
2008-12-06 02:19:52 +01:00
namespace { // facade implementation details
2008-12-05 11:07:01 +01:00
2008-12-06 02:19:52 +01:00
2008-12-07 08:46:44 +01:00
/* ================== define an lumieraorg_GuiNotification instance ======================= */
2008-12-06 02:19:52 +01:00
LUMIERA_INTERFACE_INSTANCE ( lumieraorg_interfacedescriptor , 0
, lumieraorg_GuiNotificationFacade_descriptor
, NULL , NULL , NULL
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( name ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return " GuiNotification " ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( brief ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return " GUI Interface: push state update and notification of events into the GUI " ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( homepage ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return " http://www.lumiera.org/develompent.html " ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( version ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return " 0.1~pre " ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( author ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return " Hermann Vosseler " ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( email ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return " Ichthyostega@web.de " ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( copyright ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
2008-12-06 02:19:52 +01:00
{
2008-12-30 07:28:34 +01:00
( void ) ifa ;
2008-12-06 02:19:52 +01:00
return
" Copyright (C) Lumiera.org \n "
" 2008 Hermann Vosseler <Ichthyostega@web.de> " ;
}
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( license ,
2008-12-30 07:28:34 +01:00
const char * , ( LumieraInterface ifa ) ,
2008-12-06 02:19:52 +01:00
{
2008-12-30 07:28:34 +01:00
( void ) ifa ;
2008-12-06 02:19:52 +01:00
return
" This program is free software; you can redistribute it and/or modify \n "
" it under the terms of the GNU General Public License as published by \n "
" the Free Software Foundation; either version 2 of the License, or \n "
" (at your option) any later version. \n "
" \n "
" This program is distributed in the hope that it will be useful, \n "
" but WITHOUT ANY WARRANTY; without even the implied warranty of \n "
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n "
" GNU General Public License for more details. \n "
" \n "
" You should have received a copy of the GNU General Public License \n "
" along with this program; if not, write to the Free Software \n "
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA " ;
}
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( state ,
2008-12-30 07:28:34 +01:00
int , ( LumieraInterface ifa ) ,
{ ( void ) ifa ; return LUMIERA_INTERFACE_EXPERIMENTAL ; }
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( versioncmp ,
2008-12-06 02:19:52 +01:00
int , ( const char * a , const char * b ) ,
2017-04-01 23:59:37 +02:00
{ ( void ) a ; ( void ) b ; return 0 ; } ////////////////////////////////////////////TODO define version ordering
2008-12-06 02:19:52 +01:00
)
) ;
2009-01-10 15:29:11 +01:00
using lumiera : : facade : : LUMIERA_ERROR_FACADE_LIFECYCLE ;
typedef lib : : SingletonRef < GuiNotification > : : Accessor InstanceRef ;
2017-01-20 04:18:57 +01:00
2009-01-10 15:29:11 +01:00
InstanceRef _instance ; ///< a backdoor for the C Language impl to access the actual GuiNotification implementation...
2009-01-19 02:21:41 +01:00
LUMIERA_INTERFACE_INSTANCE ( lumieraorg_GuiNotification , 0
2009-02-01 00:43:21 +01:00
, lumieraorg_GuiNotificationService
2008-12-06 02:19:52 +01:00
, LUMIERA_INTERFACE_REF ( lumieraorg_interfacedescriptor , 0 , lumieraorg_GuiNotificationFacade_descriptor )
2008-12-06 07:35:37 +01:00
, NULL /* on open */
, NULL /* on close */
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( displayInfo ,
2017-08-10 20:29:13 +02:00
void , ( uint severity , const char * text ) ,
2017-01-20 04:18:57 +01:00
{
if ( ! _instance ) lumiera_error_set ( LUMIERA_ERROR_FACADE_LIFECYCLE , text ) ;
else
2017-08-10 20:29:13 +02:00
_instance - > displayInfo ( NotifyLevel ( severity ) , text ) ;
2017-01-20 04:18:57 +01:00
}
)
, LUMIERA_INTERFACE_INLINE ( markError ,
void , ( LumieraUid element , const char * text ) ,
{
if ( ! _instance ) lumiera_error_set ( LUMIERA_ERROR_FACADE_LIFECYCLE , text ) ;
else
_instance - > markError ( reinterpret_cast < ID > ( * element ) , text ) ;
}
)
, LUMIERA_INTERFACE_INLINE ( markNote ,
void , ( LumieraUid element , const char * text ) ,
{
2009-01-13 21:23:37 +01:00
if ( ! _instance ) lumiera_error_set ( LUMIERA_ERROR_FACADE_LIFECYCLE , text ) ;
2009-01-10 15:29:11 +01:00
else
2017-01-20 04:18:57 +01:00
_instance - > markNote ( reinterpret_cast < ID > ( * element ) , text ) ;
}
)
, LUMIERA_INTERFACE_INLINE ( mutate ,
void , ( LumieraUid element , void * diff ) ,
{
if ( ! _instance ) lumiera_error_set ( LUMIERA_ERROR_FACADE_LIFECYCLE , " passing diff message " ) ;
else
2017-08-11 02:00:54 +02:00
_instance - > mutate ( reinterpret_cast < ID > ( * element ) , move ( * reinterpret_cast < DiffMessage * > ( diff ) ) ) ;
2009-01-10 15:29:11 +01:00
}
2008-12-06 02:19:52 +01:00
)
2014-03-16 02:21:07 +01:00
, LUMIERA_INTERFACE_INLINE ( triggerGuiShutdown ,
2008-12-06 02:19:52 +01:00
void , ( const char * cause ) ,
2017-01-20 04:18:57 +01:00
{
2009-01-13 21:23:37 +01:00
if ( ! _instance ) lumiera_error_set ( LUMIERA_ERROR_FACADE_LIFECYCLE , cause ) ;
2009-01-10 15:29:11 +01:00
else
2017-01-20 04:18:57 +01:00
_instance - > triggerGuiShutdown ( cause ) ;
2009-01-10 15:29:11 +01:00
}
2008-12-06 02:19:52 +01:00
)
) ;
2017-01-20 04:18:57 +01:00
2008-12-06 02:19:52 +01:00
} // (END) facade implementation details
2009-01-10 15:29:11 +01:00
2017-01-20 02:40:38 +01:00
/**
* When started , NotificationService connects to the [ UI - Bus ] ( ui - bus . hpp ) via
* the provided connection . This is a simple , unidirectional up - link connection ,
* without actively adding NotificationService into the routing tables in [ Nexus ] .
* Yet this simple connection is sufficient to implement this service by talking
* to other facilities within the UI layer .
*/
2017-08-04 19:07:05 +02:00
NotificationService : : NotificationService ( ctrl : : BusTerm & upLink , ctrl : : UiManager & uiManager )
2017-01-20 02:40:38 +01:00
: BusTerm { lib : : idi : : EntryID < NotificationService > { } , upLink }
2017-08-10 16:24:36 +02:00
, dispatch_ { new UiDispatcher { } }
2017-08-04 19:07:05 +02:00
, uiManager_ { uiManager }
2017-01-19 05:18:06 +01:00
, implInstance_ ( this , _instance )
, serviceInstance_ ( LUMIERA_INTERFACE_REF ( lumieraorg_GuiNotification , 0 , lumieraorg_GuiNotificationService ) )
2009-01-10 15:29:11 +01:00
{
2009-01-24 03:13:54 +01:00
INFO ( gui , " GuiNotification Facade opened. " ) ;
2009-01-10 15:29:11 +01:00
}
2017-08-10 16:24:36 +02:00
NotificationService : : ~ NotificationService ( ) { } // emit dtors of embedded objects here...
2008-12-05 11:07:01 +01:00
} // namespace gui