# # File:: log_window.rb # Description:: # # Author:: David Muir # Date:: 12 January 2009 # #---------------------------------------------------------------------------- # Uses #---------------------------------------------------------------------------- require 'pipeline/log/log' require 'pipeline/os/path' require 'thread' require 'wx' #---------------------------------------------------------------------------- # Implementation #---------------------------------------------------------------------------- module Pipeline module GUI # # == Description # Generic log window dialog that integrates with our Pipeline::Log # objects for displaying log messages to users. # # === Example Usage # # To auto-popup the display of the log dialog: # Pipeline::GUI::LogWindow::show_dialog( true ) do # # Do something that will log messages, dialog only displayed on # # errors. # end # # # To force the display of the log dialog: # Pipeline::GUI::LogWindow::show_dialog( ) do # # Do something that will log messages # end # class LogWindow < Wx::App THREAD_TIMER_ID = Wx::ID_HIGHEST + 1 #--------------------------------------------------------------------- # Class Methods #--------------------------------------------------------------------- def initialize( log, auto_popup, title = 'Log', &block ) super( ) @log = log @auto_popup = auto_popup @title = title @proc = Proc.new( ) do yield end end # # Use this method to explicitly display a log dialog box. Only # log messages generated after this call will be displayed. # def LogWindow::show_dialog( auto_popup = false, log = Pipeline::LogSystem::instance().rootlog, title = 'Pipeline Log' ) begin dlg = LogWindow.new( log, auto_popup, title ) do yield if ( block_given? ) end dlg.main_loop( ) rescue Exception => ex raise unless ( 'exit' == ex.message ) end end #--------------------------------------------------------------------- # Instance Methods #--------------------------------------------------------------------- def on_init( ) Wx::Timer::every( 25 ) do Thread::pass( ) end dlg = LogWindowDialog::new( @log, @title, @auto_popup ) dlg.show( ) unless ( @auto_popup ) script_thread = Thread.new do @proc.call( ) exit( ) if ( @auto_popup and ( not dlg.is_shown ) ) end script_thread.join( ) end end # # == Description # Generic log window dialog that integrates with our Pipeline::Log # objects for displaying log messages to users. # # === Example Usage # # To auto-popup the display of the log dialog on error messages: # Pipeline::GUI::LogWindow::show_dialog( true ) do # # Do something that will log messages # end # # # To force the display of the log dialog: # Pipeline::GUI::LogWindow::show_dialog( ) do # # Do something that will log messages # end # class LogWindowDialog < Wx::Dialog # # == Description # Internally used Log4r::Formatter to format log messages for our # LogWindowOutputter class below. # class LogWindowFormatter < Log4r::Formatter def initialize( hash = {} ) super( hash ) end # # Pass the Log4r event object straight over to outputter, rather # than serialising it into a String. This saves us having to parse # a log message formatted String using Regexp or similar. # def format( event ) event end end # # == Description # Internally used Log4r::Outputter to log messages into our log # window. # class LogWindowOutputter < Log4r::Outputter attr_reader :dialog def initialize( dialog, _name, hash = {} ) super( _name, hash ) @dialog = dialog end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private def write( data ) # Pass the log data straight to our Log Window for processing. @dialog.append_message( data ) end end #-------------------------------------------------------------------- # Attributes #-------------------------------------------------------------------- attr_reader :auto_popup # # Constructor. # def initialize( log, title, auto_popup ) super( nil, Wx::ID_ANY, title, Wx::DEFAULT_POSITION, Wx::Size.new(500,550), Wx::DEFAULT_DIALOG_STYLE | Wx::DIALOG_NO_PARENT | Wx::MAXIMIZE_BOX | Wx::RESIZE_BORDER | Wx::CLIP_CHILDREN ) @log = log @auto_popup = auto_popup c = Pipeline::Config::instance( ) icon = Wx::Icon.new( ) icon.load_file( OS::Path.combine( c.toolslib, 'data', 'icons', 'rs_icon.ico' ), Wx::BITMAP_TYPE_ICO ) set_icon( icon ) #----------------------------------------------------------------- # WIDGETS #----------------------------------------------------------------- @txtCtrl = Wx::TextCtrl.new( self, Wx::ID_ANY, '', Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, Wx::TE_MULTILINE | Wx::TE_RICH2 | Wx::TE_AUTO_URL ) btnClose = Wx::Button.new( self, Wx::ID_ANY, 'Close' ) btnClose.set_default( ) #----------------------------------------------------------------- # EVENTS #----------------------------------------------------------------- evt_button( btnClose.get_id( ) ) do |event| close( ) end evt_close( ) do |event| @log.remove( @outputter ) event.skip( ) # continue closing exit( ) end #----------------------------------------------------------------- # LOG OUTPUTTER INIT #----------------------------------------------------------------- @outputter = LogWindowOutputter.new( self, 'log_window' ) @outputter.formatter = LogWindowFormatter.new( ) @log.add( @outputter ) #----------------------------------------------------------------- # LAYOUT #----------------------------------------------------------------- sizer_vert = Wx::BoxSizer.new( Wx::VERTICAL ) sizer_bottom = Wx::BoxSizer.new( Wx::HORIZONTAL ) sizer_bottom.add_spacer( 1 ) sizer_bottom.add( btnClose, 1, Wx::ALL | Wx::ALIGN_RIGHT ) sizer_vert.add( @txtCtrl, 20, Wx::ALL | Wx::EXPAND | Wx::GROW, 1 ) sizer_vert.add( sizer_bottom, 0, Wx::BOTTOM ) set_sizer( sizer_vert ) end # # Append a log message into our window. Typically called by a log # outputter object (e.g. LogWindowOutputter). # def append_message( event ) @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::BLACK ) ) @txtCtrl.append_text( Time.now.strftime( '%Y-%m-%d %H:%M:%S ' ) ) case event.level when 5, 4 # fatal, error @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::RED ) ) show( ) if ( @auto_popup ) when 3 # warning @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::Colour.new( 255, 127, 0 ) ) ) when 2 # info @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::Colour.new( 0, 140, 30 ) ) ) when 1 # debug @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::BLUE ) ) else # info and catch all @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::BLACK ) ) end @txtCtrl.append_text( "#{Log4r::LNAMES[event.level]}" ) @txtCtrl.set_default_style( Wx::TextAttr.new( Wx::BLACK ) ) @txtCtrl.append_text( " #{event.logger.name}" ) if ( event.methods.include?( 'logger' ) ) @txtCtrl.append_text( " at #{event.tracer[0]}" ) unless ( event.tracer.nil? ) @txtCtrl.append_text( ": #{event.data}\n" ) end end end # GUI module end # Pipeline module # log_window.rb