You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
652 lines
27 KiB
C++
652 lines
27 KiB
C++
//-----------------------------------------------------------------------------
|
|
#ifndef wxAbstractionH
|
|
#define wxAbstractionH wxAbstractionH
|
|
//-----------------------------------------------------------------------------
|
|
#include <apps/Common/Info.h>
|
|
#include <apps/Common/mvIcon.xpm>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "wxIncludePrologue.h"
|
|
#include <wx/button.h>
|
|
#include <wx/combobox.h>
|
|
#include <wx/config.h>
|
|
#include <wx/dialog.h>
|
|
#include <wx/dynlib.h>
|
|
#include <wx/hyperlink.h>
|
|
#include <wx/listctrl.h>
|
|
#include <wx/log.h>
|
|
#include <wx/notebook.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/sizer.h>
|
|
#include <wx/splash.h>
|
|
#include <wx/socket.h>
|
|
#include <wx/stattext.h>
|
|
#include <wx/string.h>
|
|
#include <wx/textctrl.h>
|
|
#include <wx/timer.h>
|
|
#include <wx/window.h>
|
|
#include "wxIncludeEpilogue.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
struct ConvertedString : wxString
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
#if wxUSE_UNICODE
|
|
ConvertedString( const char* s ) :
|
|
wxString( s, wxConvUTF8 ) {}
|
|
ConvertedString( const std::string& s ) :
|
|
wxString( s.c_str(), wxConvUTF8 ) {}
|
|
ConvertedString( const wxString& s ) :
|
|
# if wxCHECK_VERSION(2,9,0)
|
|
wxString( s.mb_str(), wxConvUTF8 ) {}
|
|
# else
|
|
wxString( s.c_str(), wxConvUTF8 ) {}
|
|
# endif
|
|
#else
|
|
ConvertedString( const char* s ) :
|
|
wxString( s ) {}
|
|
ConvertedString( const std::string& s ) :
|
|
wxString( s.c_str() ) {}
|
|
ConvertedString( const wxString& s ) :
|
|
# if wxCHECK_VERSION(2,9,0)
|
|
wxString( s.mb_str() ) {}
|
|
# else
|
|
wxString( s.c_str() ) {}
|
|
# endif
|
|
#endif
|
|
};
|
|
|
|
#if ( wxMINOR_VERSION > 6 ) && ( wxMAJOR_VERSION < 3 ) && !WXWIN_COMPATIBILITY_2_6
|
|
#include <wx/filedlg.h>
|
|
enum
|
|
{
|
|
wxOPEN = wxFD_OPEN,
|
|
wxSAVE = wxFD_SAVE,
|
|
wxOVERWRITE_PROMPT = wxFD_OVERWRITE_PROMPT,
|
|
wxFILE_MUST_EXIST = wxFD_FILE_MUST_EXIST,
|
|
wxMULTIPLE = wxFD_MULTIPLE,
|
|
wxCHANGE_DIR = wxFD_CHANGE_DIR
|
|
};
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
enum TApplicationColors
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
acRedPastel = ( 200 << 16 ) | ( 200 << 8 ) | 255,
|
|
acYellowPastel = ( 180 << 16 ) | ( 255 << 8 ) | 255,
|
|
acBluePastel = ( 255 << 16 ) | ( 220 << 8 ) | 200,
|
|
acDarkBluePastel = ( 255 << 16 ) | ( 100 << 8 ) | 80,
|
|
acGreenPastel = ( 200 << 16 ) | ( 255 << 8 ) | 200,
|
|
acGreyPastel = ( 200 << 16 ) | ( 200 << 8 ) | 200,
|
|
acDarkGrey = ( 100 << 16 ) | ( 100 << 8 ) | 100
|
|
};
|
|
|
|
//=============================================================================
|
|
//================= Implementation FramePositionStorage =======================
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
class FramePositionStorage
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxWindow* m_pWin;
|
|
public:
|
|
FramePositionStorage( wxWindow* pWin ) : m_pWin( pWin ) {}
|
|
void Save( void ) const
|
|
{
|
|
Save( m_pWin );
|
|
}
|
|
static void Save( wxWindow* pWin, const wxString& windowName = wxT( "MainFrame" ) )
|
|
{
|
|
wxConfigBase* pConfig( wxConfigBase::Get() );
|
|
int Height, Width, XPos, YPos;
|
|
pWin->GetSize( &Width, &Height );
|
|
pWin->GetPosition( &XPos, &YPos );
|
|
// when we e.g. try to write config stuff on a read-only file system the result can
|
|
// be an annoying message box. Therefore we switch off logging during the storage operation.
|
|
wxLogNull logSuspendScope;
|
|
pConfig->Write( wxString::Format( wxT( "/%s/h" ), windowName.c_str() ), Height );
|
|
pConfig->Write( wxString::Format( wxT( "/%s/w" ), windowName.c_str() ), Width );
|
|
pConfig->Write( wxString::Format( wxT( "/%s/x" ), windowName.c_str() ), XPos );
|
|
pConfig->Write( wxString::Format( wxT( "/%s/y" ), windowName.c_str() ), YPos );
|
|
if( dynamic_cast<wxTopLevelWindow*>( pWin ) )
|
|
{
|
|
pConfig->Write( wxString::Format( wxT( "/%s/maximized" ), windowName.c_str() ), dynamic_cast<wxTopLevelWindow*>( pWin )->IsMaximized() );
|
|
}
|
|
pConfig->Flush();
|
|
}
|
|
static wxRect Load( const wxRect& defaultDimensions, bool& boMaximized, const wxString& windowName = wxT( "MainFrame" ) )
|
|
{
|
|
wxConfigBase* pConfig( wxConfigBase::Get() );
|
|
wxRect rect;
|
|
rect.height = pConfig->Read( wxString::Format( wxT( "/%s/h" ), windowName.c_str() ), defaultDimensions.height );
|
|
rect.width = pConfig->Read( wxString::Format( wxT( "/%s/w" ), windowName.c_str() ), defaultDimensions.width );
|
|
rect.x = pConfig->Read( wxString::Format( wxT( "/%s/x" ), windowName.c_str() ), defaultDimensions.x );
|
|
rect.y = pConfig->Read( wxString::Format( wxT( "/%s/y" ), windowName.c_str() ), defaultDimensions.y );
|
|
boMaximized = pConfig->Read( wxString::Format( wxT( "/%s/maximized" ), windowName.c_str() ), 1l ) != 0;
|
|
int displayWidth = 0;
|
|
int displayHeight = 0;
|
|
wxDisplaySize( &displayWidth, &displayHeight );
|
|
if( ( rect.x >= displayWidth ) || ( ( rect.x + rect.width ) < 0 ) )
|
|
{
|
|
rect.x = 0;
|
|
}
|
|
if( ( rect.y >= displayHeight ) || ( ( rect.y + rect.height ) < 0 ) )
|
|
{
|
|
rect.y = 0;
|
|
}
|
|
return rect;
|
|
}
|
|
};
|
|
|
|
//=============================================================================
|
|
//================= Implementation SplashScreenScope ==========================
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
class SplashScreenScope
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxSplashScreen* pSplash_;
|
|
wxStopWatch stopWatch_;
|
|
public:
|
|
explicit SplashScreenScope( const wxBitmap& bmp ) : pSplash_( 0 ), stopWatch_()
|
|
{
|
|
pSplash_ = new wxSplashScreen( ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_SMALL ) ? wxBitmap( mvIcon_xpm ) : bmp, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, NULL, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER );
|
|
pSplash_->Update();
|
|
}
|
|
virtual ~SplashScreenScope()
|
|
{
|
|
const unsigned long startupTime_ms = static_cast<unsigned long>( stopWatch_.Time() );
|
|
const unsigned long minSplashDisplayTime_ms = 3000;
|
|
if( startupTime_ms < minSplashDisplayTime_ms )
|
|
{
|
|
wxMilliSleep( minSplashDisplayTime_ms - startupTime_ms );
|
|
}
|
|
delete pSplash_;
|
|
}
|
|
};
|
|
|
|
//=============================================================================
|
|
//================= Implementation SocketInitializeScope ======================
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
class SocketInitializeScope
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
public:
|
|
explicit SocketInitializeScope()
|
|
{
|
|
// This has to be called in order to be able to initialize sockets outside of
|
|
// the main thread ( http://www.litwindow.com/Knowhow/wxSocket/wxsocket.html )
|
|
wxSocketBase::Initialize();
|
|
}
|
|
~SocketInitializeScope()
|
|
{
|
|
// Must apparently be done since we called wxSocketBase::Initialize(),
|
|
// otherwise memory leaks occur when closing the application.
|
|
wxSocketBase::Shutdown();
|
|
}
|
|
};
|
|
|
|
//=============================================================================
|
|
//================= Implementation miscellaneous helper functions =============
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
inline wxString LoadGenTLProducer( wxDynamicLibrary& lib )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
#ifdef _WIN32
|
|
const wxString libName( wxT( "mvGenTLProducer.cti" ) );
|
|
#else
|
|
const wxString libName( wxT( "libmvGenTLProducer.so" ) );
|
|
#endif
|
|
|
|
const wxString GenTLPathVariable( ( sizeof( void* ) == 8 ) ? wxT( "GENICAM_GENTL64_PATH" ) : wxT( "GENICAM_GENTL32_PATH" ) );
|
|
#if defined(linux) || defined(__linux) || defined(__linux__)
|
|
const wxChar PATH_SEPARATOR( wxT( ':' ) );
|
|
#elif defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
|
|
const wxChar PATH_SEPARATOR( wxT( ';' ) );
|
|
#else
|
|
# error Unsupported target platform
|
|
#endif
|
|
wxString GenTLPath;
|
|
wxArrayString potentialLocations;
|
|
if( ::wxGetEnv( GenTLPathVariable, &GenTLPath ) )
|
|
{
|
|
potentialLocations = wxSplit( GenTLPath, PATH_SEPARATOR );
|
|
}
|
|
|
|
wxString message;
|
|
// when we e.g. trying to load a shared library that cannot be found the result can
|
|
// be an annoying message box. Therefore we switch off logging during the load attempts.
|
|
wxLogNull logSuspendScope;
|
|
const size_t potentialLocationCount = potentialLocations.Count();
|
|
for( size_t i = 0; i < potentialLocationCount; i++ )
|
|
{
|
|
lib.Load( potentialLocations[i] + wxT( "/" ) + libName, wxDL_VERBATIM );
|
|
if( lib.IsLoaded() )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !lib.IsLoaded() )
|
|
{
|
|
lib.Load( libName, wxDL_VERBATIM );
|
|
}
|
|
if( !lib.IsLoaded() )
|
|
{
|
|
message = wxString::Format( wxT( "Could not connect to '%s'. Check your installation.\n\n" ), libName.c_str() );
|
|
}
|
|
return message;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void AddSourceInfo( wxWindow* pParent, wxSizer* pParentSizer )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxBoxSizer* pSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( "The complete source code belonging to this application can be obtained by contacting " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, COMPANY_NAME, COMPANY_WEBSITE ) );
|
|
pParentSizer->Add( pSizer, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void AddSupportInfo( wxWindow* pParent, wxSizer* pParentSizer )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxBoxSizer* pSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( "Support contact: " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, COMPANY_SUPPORT_MAIL, COMPANY_SUPPORT_MAIL ) );
|
|
pParentSizer->Add( pSizer, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void AddwxWidgetsInfo( wxWindow* pParent, wxSizer* pParentSizer )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxBoxSizer* pSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( "This tool has been written using " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, wxT( "wxWidgets" ), wxT( "http://www.wxwidgets.org" ) ) );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxString::Format( wxT( " %d.%d.%d." ), wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER ) ) );
|
|
pParentSizer->Add( pSizer, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void AddIconInfo( wxWindow* pParent, wxSizer* pParentSizer )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxBoxSizer* pSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( "This tool uses modified icons downloaded from here " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, wxT( "icons8" ), wxT( "https://icons8.com/" ) ) );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( " and here " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, wxT( "Freepik" ), wxT( "http://www.freepik.com" ) ) );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( ". The " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, wxT( "Material Design" ), wxT( "https://material.io/resources/icons/?style=outline" ) ) );
|
|
pSizer->Add( new wxStaticText( pParent, wxID_ANY, wxT( " icons are published under " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( pParent, wxID_ANY, wxT( "Apache 2.0 license." ), wxT( "https://www.apache.org/licenses/LICENSE-2.0.html" ) ) );
|
|
pParentSizer->Add( pSizer, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void AddListControlToAboutNotebook( wxNotebook* pNotebook, const wxString& pageTitle, bool boSelectPage, const wxString& col0, const wxString& col1, const std::vector<std::pair<wxString, wxString> >& v )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxListCtrl* pListCtrl = new wxListCtrl( pNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxBORDER_NONE );
|
|
pListCtrl->InsertColumn( 0, col0 );
|
|
pListCtrl->InsertColumn( 1, col1 );
|
|
const unsigned long cnt = static_cast<unsigned long>( v.size() );
|
|
for( unsigned long i = 0; i < cnt; i++ )
|
|
{
|
|
long index = pListCtrl->InsertItem( i, v[i].first, i );
|
|
pListCtrl->SetItem( index, 1, v[i].second );
|
|
}
|
|
for( unsigned int i = 0; i < 2; i++ )
|
|
{
|
|
pListCtrl->SetColumnWidth( i, wxLIST_AUTOSIZE );
|
|
}
|
|
pNotebook->AddPage( pListCtrl, pageTitle, boSelectPage );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void AppendPathSeparatorIfNeeded( wxString& path )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if( !path.EndsWith( wxT( "/" ) ) && !path.EndsWith( wxT( "\\" ) ) )
|
|
{
|
|
path.append( wxT( "/" ) );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void WriteToTextCtrl( wxTextCtrl* pTextCtrl, const wxString& msg, const wxTextAttr& style = wxTextAttr( *wxBLACK ) )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if( pTextCtrl )
|
|
{
|
|
// If you want the control to show the last line of text at the bottom, you can add "ScrollLines(1)"
|
|
// right after the AppendText call. AppendText will ensure the new line is visible, and ScrollLines
|
|
// will ensure the scroll bar is at the real end of the range, not further.
|
|
long posBefore = pTextCtrl->GetLastPosition();
|
|
pTextCtrl->AppendText( msg );
|
|
long posAfter = pTextCtrl->GetLastPosition();
|
|
pTextCtrl->SetStyle( posBefore, posAfter, style );
|
|
pTextCtrl->ScrollLines( 1 );
|
|
pTextCtrl->ShowPosition( pTextCtrl->GetLastPosition() ); // ensure that this position is really visible
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
struct AboutDialogInformation
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxWindow* pParent_;
|
|
wxString applicationName_;
|
|
wxString briefDescription_;
|
|
unsigned int yearOfInitialRelease_;
|
|
std::vector<std::pair<wxString, wxTextAttr> > usageHints_;
|
|
std::vector<std::pair<wxString, wxString> > keyboardShortcuts_;
|
|
std::vector<std::pair<wxString, wxString> > availableCommandLineOptions_;
|
|
bool boAddIconInfo_;
|
|
bool boAddExpatInfo_;
|
|
bool boAddFFmpegInfo_;
|
|
explicit AboutDialogInformation( wxWindow* pParent = 0 ) : pParent_( pParent ), applicationName_(),
|
|
briefDescription_(), yearOfInitialRelease_( 2005 ), usageHints_(), keyboardShortcuts_(),
|
|
availableCommandLineOptions_(), boAddIconInfo_( false ), boAddExpatInfo_( false ), boAddFFmpegInfo_( false ) {}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void DisplayCommandLineProcessingInformation( wxTextCtrl* pTextCtrl, const wxString& processedCommandLineParameters, const wxString& parserErrors, const wxTextAttr& style )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
WriteToTextCtrl( pTextCtrl, wxT( "\n" ) );
|
|
WriteToTextCtrl( pTextCtrl, wxT( "Press 'F1' for help.\n" ), style );
|
|
WriteToTextCtrl( pTextCtrl, wxT( "\n" ) );
|
|
const wxString none( wxT( "none" ) );
|
|
WriteToTextCtrl( pTextCtrl, wxString::Format( wxT( "Processed command line parameters: %s\n" ), ( processedCommandLineParameters.length() > 0 ) ? processedCommandLineParameters.c_str() : none.c_str() ), style );
|
|
WriteToTextCtrl( pTextCtrl, wxT( "\n" ) );
|
|
if( !parserErrors.IsEmpty() )
|
|
{
|
|
WriteToTextCtrl( pTextCtrl, parserErrors, wxTextAttr( *wxRED ) );
|
|
WriteToTextCtrl( pTextCtrl, wxT( "\n" ) );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void DisplayCommonAboutDialog( const AboutDialogInformation& info )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxBoxSizer* pTopDownSizer;
|
|
wxDialog dlg( info.pParent_, wxID_ANY, wxString( wxString::Format( wxT( "About %s" ), info.applicationName_.c_str() ) ), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX );
|
|
wxIcon icon( mvIcon_xpm );
|
|
dlg.SetIcon( icon );
|
|
pTopDownSizer = new wxBoxSizer( wxVERTICAL );
|
|
wxStaticText* pText = new wxStaticText( &dlg, wxID_ANY, info.briefDescription_ );
|
|
pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
pText = new wxStaticText( &dlg, wxID_ANY, wxString::Format( wxT( "(C) %u - %s by %s" ), info.yearOfInitialRelease_, CURRENT_YEAR, COMPANY_NAME ) );
|
|
pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
pText = new wxStaticText( &dlg, wxID_ANY, wxString::Format( wxT( "Version %s" ), VERSION_STRING ) );
|
|
pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
AddSupportInfo( &dlg, pTopDownSizer );
|
|
AddwxWidgetsInfo( &dlg, pTopDownSizer );
|
|
if( info.boAddIconInfo_ )
|
|
{
|
|
AddIconInfo( &dlg, pTopDownSizer );
|
|
}
|
|
if( info.boAddExpatInfo_ )
|
|
{
|
|
pText = new wxStaticText( &dlg, wxID_ANY, wxT( "The expat wrapper class used internally has been written by Descartes Systems Sciences, Inc." ) );
|
|
pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
}
|
|
if( info.boAddFFmpegInfo_ )
|
|
{
|
|
wxBoxSizer* pSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
pSizer->Add( new wxStaticText( &dlg, wxID_ANY, wxT( "The video recording functionality of this application requires libraries from the " ) ) );
|
|
pSizer->Add( new wxHyperlinkCtrl( &dlg, wxID_ANY, wxT( "FFmpeg" ), wxT( "https://www.ffmpeg.org/" ) ) );
|
|
pSizer->Add( new wxStaticText( &dlg, wxID_ANY, wxT( " project under the LGPLv2.1. These must be installed separately" ) ) );
|
|
pTopDownSizer->Add( pSizer, 0, wxALL | wxALIGN_CENTER, 5 );
|
|
}
|
|
AddSourceInfo( &dlg, pTopDownSizer );
|
|
wxNotebook* pNotebook = new wxNotebook( &dlg, wxID_ANY, wxDefaultPosition, wxDefaultSize );
|
|
wxTextCtrl* pUsageHints = new wxTextCtrl( pNotebook, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxBORDER_NONE | wxTE_RICH | wxTE_READONLY );
|
|
pNotebook->AddPage( pUsageHints, wxT( "Usage Hints" ), true );
|
|
std::vector<std::pair<wxTextAttr, wxString> >::size_type usageHintStringCount = info.usageHints_.size();
|
|
for( std::vector<std::pair<wxString, wxTextAttr> >::size_type i = 0; i < usageHintStringCount; i++ )
|
|
{
|
|
WriteToTextCtrl( pUsageHints, info.usageHints_[i].first, info.usageHints_[i].second );
|
|
}
|
|
pUsageHints->ScrollLines( -( 256 * 256 ) ); // make sure the text control always shows the beginning of the help text
|
|
if( !info.keyboardShortcuts_.empty() )
|
|
{
|
|
AddListControlToAboutNotebook( pNotebook, wxT( "Keyboard Shortcuts" ), false, wxT( "Shortcut" ), wxT( "Command" ), info.keyboardShortcuts_ );
|
|
}
|
|
if( !info.availableCommandLineOptions_.empty() )
|
|
{
|
|
AddListControlToAboutNotebook( pNotebook, wxT( "Available Command Line Options" ), false, wxT( "Command" ), wxT( "Description" ), info.availableCommandLineOptions_ );
|
|
}
|
|
pTopDownSizer->AddSpacer( 10 );
|
|
pTopDownSizer->Add( pNotebook, wxSizerFlags( 5 ).Expand() );
|
|
pTopDownSizer->AddSpacer( 10 );
|
|
wxButton* pBtnOK = new wxButton( &dlg, wxID_OK, wxT( "OK" ) );
|
|
pBtnOK->SetDefault();
|
|
pTopDownSizer->Add( pBtnOK, 0, wxALL | wxALIGN_RIGHT, 15 );
|
|
dlg.SetSizer( pTopDownSizer );
|
|
dlg.SetSizeHints( 720, 500 );
|
|
dlg.SetSize( -1, -1, 800, 500 );
|
|
dlg.ShowModal();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline wxTextAttr GetCommonTextStyle( const bool boBold, const bool boUnderlined, wxTextCtrl*
|
|
#if wxCHECK_VERSION(2, 9, 5)
|
|
#else
|
|
pParent
|
|
#endif // #if wxCHECK_VERSION(2, 9, 5)
|
|
)
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxTextAttr theStyle;
|
|
#if wxCHECK_VERSION(2, 9, 5)
|
|
wxFontInfo fontInfo( 10 );
|
|
if( boBold )
|
|
{
|
|
fontInfo.Bold();
|
|
}
|
|
if( boUnderlined )
|
|
{
|
|
fontInfo.Underlined();
|
|
}
|
|
wxFont theFont( fontInfo );
|
|
#else
|
|
pParent->GetStyle( pParent->GetLastPosition(), theStyle );
|
|
wxFont theFont( theStyle.GetFont() );
|
|
if( boBold )
|
|
{
|
|
theFont.SetWeight( wxFONTWEIGHT_BOLD );
|
|
}
|
|
theFont.SetPointSize( 10 );
|
|
if( boUnderlined )
|
|
{
|
|
theFont.SetUnderlined( true );
|
|
}
|
|
#endif // #if wxCHECK_VERSION(2, 9, 5)
|
|
theStyle.SetFont( theFont );
|
|
return theStyle;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline wxTextAttr GetBoldStyle( wxTextCtrl* pParent )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return GetCommonTextStyle( true, false, pParent );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline wxTextAttr GetBoldUnderlinedStyle( wxTextCtrl* pParent )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return GetCommonTextStyle( true, true, pParent );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline wxTextAttr GetDefaultStyle( wxTextCtrl* pParent )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return GetCommonTextStyle( false, false, pParent );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline wxTextAttr GetUnderlinedStyle( wxTextCtrl* pParent )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return GetCommonTextStyle( false, true, pParent );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool IsListOfChoicesEmpty( wxComboBox* pCB )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
#if wxCHECK_VERSION(2, 9, 3)
|
|
return pCB->IsListEmpty();
|
|
#else
|
|
return pCB->IsEmpty();
|
|
#endif // #if wxCHECK_VERSION(2, 9, 3)
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void StopTimer( wxTimer& timer )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if( timer.IsRunning() )
|
|
{
|
|
timer.Stop();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//===================== Implementation Version helper functions ===============
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
struct Version
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
long major_;
|
|
long minor_;
|
|
long subMinor_;
|
|
long release_;
|
|
explicit Version() : major_( -1 ), minor_( -1 ), subMinor_( -1 ), release_( 0 ) {}
|
|
explicit Version( long ma, long mi, long smi, long re ) : major_( ma ), minor_( mi ), subMinor_( smi ), release_( re ) {}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool operator<( const Version& a, const Version& b )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if( a.major_ < b.major_ )
|
|
{
|
|
return true;
|
|
}
|
|
else if( a.major_ == b.major_ )
|
|
{
|
|
if( a.minor_ < b.minor_ )
|
|
{
|
|
return true;
|
|
}
|
|
else if( a.minor_ == b.minor_ )
|
|
{
|
|
if( a.subMinor_ < b.subMinor_ )
|
|
{
|
|
return true;
|
|
}
|
|
else if( a.subMinor_ == b.subMinor_ )
|
|
{
|
|
if( a.release_ < b.release_ )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool operator==( const Version& a, const Version& b )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return ( ( a.major_ == b.major_ ) && ( a.minor_ == b.minor_ ) && ( a.subMinor_ == b.subMinor_ ) && ( a.release_ == b.release_ ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool operator!=( const Version& a, const Version& b )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return ( ( a.major_ != b.major_ ) || ( a.minor_ != b.minor_ ) || ( a.subMinor_ != b.subMinor_ ) || ( a.release_ != b.release_ ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool operator>( const Version& a, const Version& b )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return ( !( a < b ) && !( a == b ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool operator>=( const Version& a, const Version& b )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return ( a > b ) || ( a == b );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool GetNextVersionNumber( wxString& str, long& number )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
wxString numberString = str.BeforeFirst( wxT( '.' ) );
|
|
str = str.AfterFirst( wxT( '.' ) );
|
|
return numberString.ToLong( &number );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline Version VersionFromString( const wxString& versionAsString )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
Version version;
|
|
wxString tmp( versionAsString );
|
|
GetNextVersionNumber( tmp, version.major_ );
|
|
if( !tmp.empty() )
|
|
{
|
|
GetNextVersionNumber( tmp, version.minor_ );
|
|
if( !tmp.empty() )
|
|
{
|
|
GetNextVersionNumber( tmp, version.subMinor_ );
|
|
if( !tmp.empty() )
|
|
{
|
|
GetNextVersionNumber( tmp, version.release_ );
|
|
}
|
|
}
|
|
}
|
|
return version;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool IsVersionWithinRange( const Version& version, const Version& minVersion, const Version& maxVersion )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if( version < minVersion )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if( version > maxVersion )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif // wxAbstractionH
|