Files
2025-09-29 00:52:08 +02:00

244 lines
7.6 KiB
Ruby
Executable File

#
# File:: log_window.rb
# Description::
#
# Author:: David Muir <david.muir@rockstarnorth.com>
# 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