// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// Licence: GNU General Public License version 2
// $Id: app.cpp 345 2007-08-21 01:09:15Z wojdyr $
// wxwindows headers, see wxwindows samples for description
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/cmdline.h>
#include <wx/config.h>
#include <wx/fs_zip.h>
#include <wx/fileconf.h>
#include <wx/stdpaths.h>
#if wxUSE_TOOLTIPS
#include <wx/tooltip.h>
#endif
#include <vector>
#include <string>
#include "app.h"
#include "cmn.h"
#include "gui.h"
#include "dataedit.h" //DataEditorDlg::read_transforms()
#include "pane.h" // initializations
#include "sidebar.h" // initializations
#include "../logic.h"
#include "../cmd.h"
using namespace std;
IMPLEMENT_APP(FApp)
/// command line options
static const wxCmdLineEntryDesc cmdLineDesc[] = {
{ wxCMD_LINE_SWITCH, wxT("h"), wxT("help"), wxT("show this help message"),
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
{ wxCMD_LINE_SWITCH, wxT("V"), wxT("version"),
wxT("output version information and exit"), wxCMD_LINE_VAL_NONE, 0 },
{ wxCMD_LINE_OPTION, wxT("c"),wxT("cmd"), wxT("script passed in as string"),
wxCMD_LINE_VAL_STRING, 0 },
{ wxCMD_LINE_OPTION, wxT("g"),wxT("config"),
wxT("choose GUI configuration"), wxCMD_LINE_VAL_STRING, 0 },
{ wxCMD_LINE_SWITCH, wxT("I"), wxT("no-init"),
wxT("don't process $HOME/.fityk/init file"), wxCMD_LINE_VAL_NONE, 0 },
{ wxCMD_LINE_SWITCH, wxT("r"), wxT("reorder"),
wxT("reorder data (50.xy before 100.xy)"), wxCMD_LINE_VAL_NONE, 0 },
{ wxCMD_LINE_PARAM, 0, 0, wxT("script or data file"),wxCMD_LINE_VAL_STRING,
wxCMD_LINE_PARAM_OPTIONAL|wxCMD_LINE_PARAM_MULTIPLE },
{ wxCMD_LINE_NONE, 0, 0, 0, wxCMD_LINE_VAL_NONE, 0 }
};
//---------------- C A L L B A C K S --------------------------------------
void gui_show_message(OutputStyle style, const string& s)
{
frame->output_text(style, s + "\n");
}
void gui_do_draw_plot(bool now)
{
frame->refresh_plots(now);
}
void gui_wait(float seconds)
{
wxMilliSleep(iround(seconds*1e3));
}
void gui_refresh()
{
wxSafeYield();
}
Commands::Status gui_exec_command(const string& s)
{
//FIXME should I limit number of displayed lines?
//const int max_lines_in_output_win = 1000;
//don't output plot command - it is generated by every zoom in/out etc.
bool output = strncmp(s.c_str(), "plot", 4) != 0;
if (output)
frame->output_text(os_input, "=-> " + s + "\n");
else
frame->set_status_text(s);
wxBusyCursor wait;
Commands::Status r;
try {
r = parse_and_execute(s);
}
catch(ExitRequestedException) {
frame->Close(true);
return Commands::status_ok;
}
frame->after_cmd_updates();
return r;
}
//-------------------------------------------------------------------------
bool FApp::OnInit(void)
{
SetAppName(wxT("fityk"));
// if options can be parsed
wxCmdLineParser cmdLineParser(cmdLineDesc, argc, argv);
if (cmdLineParser.Parse(false) != 0) {
cmdLineParser.Usage();
return false; //false = exit the application
}
else if (cmdLineParser.Found(wxT("V"))) {
wxMessageOutput::Get()->Printf(wxT("fityk version ")
+ pchar2wx(VERSION) + wxT("\n"));
return false; //false = exit the application
} //the rest of options will be processed in process_argv()
ftk = new Ftk;
// set callbacks
ftk->get_ui()->set_show_message(gui_show_message);
ftk->get_ui()->set_do_draw_plot(gui_do_draw_plot);
ftk->get_ui()->set_wait(gui_wait);
ftk->get_ui()->set_refresh(gui_refresh);
ftk->get_ui()->set_exec_command(gui_exec_command);
wxFileSystem::AddHandler(new wxZipFSHandler);
wxImage::AddHandler(new wxPNGHandler);
//global settings
#if wxUSE_TOOLTIPS
wxToolTip::Enable (true);
wxToolTip::SetDelay (500);
#endif
//create user data directory, if it doesn't exists
wxString fityk_dir = wxStandardPaths::Get().GetUserDataDir();
if (!wxDirExists(fityk_dir))
wxMkdir(fityk_dir);
wxConfig::DontCreateOnDemand();
//prefix for wxConfig. It can be wxFileConfig or wxRegConfig,
// so the prefix on MSW can't be absolute
// On Unix - it is compatible with get_user_conffile()
// On MSW - not compatible, but it uses registry, so it doesn't matter
#ifdef __WXMAC__
wxString prefix = wxStandardPaths::Get().GetUserConfigDir()
+ wxFILE_SEP_PATH + wxT("pl.waw.unipress.fityk.");
#else
wxString prefix = pchar2wx(config_dirname) + wxFILE_SEP_PATH;
#endif
// set default and alternative config names
conf_filename = prefix + wxT("config");
alt_conf_filename = prefix + wxT("alt-config");
// set config file for options automatically saved
// it will be accessed only via wxConfig::Get()
wxConfig *config = new wxConfig(wxT(""), wxT(""),
prefix + wxT("wxoptions"), wxT(""),
wxCONFIG_USE_LOCAL_FILE);
wxConfig::Set(config);
config_dir = get_user_conffile("configs") + wxFILE_SEP_PATH;
if (!wxDirExists(config_dir))
wxMkdir(config_dir);
DataEditorDlg::read_transforms();
// Create the main frame window
frame = new FFrame(NULL, -1, wxT("fityk"), wxDEFAULT_FRAME_STYLE);
wxConfigBase *cf;
wxString g_config;
if (cmdLineParser.Found(wxT("g"), &g_config))
cf = new wxFileConfig(wxT(""), wxT(""), config_dir + g_config,
wxT(""), wxCONFIG_USE_LOCAL_FILE);
else
cf = new wxConfig(wxT(""), wxT(""), conf_filename, wxT(""),
wxCONFIG_USE_LOCAL_FILE);
frame->read_all_settings(cf);
frame->plot_pane->set_mouse_mode(mmd_zoom);
frame->Show(true);
// it does not work earlier, problems with OutputWin colors (wxGTK gtk1.2)
frame->io_pane->output_win->read_settings(cf);
frame->io_pane->output_win->show_fancy_dashes();
// sash inside wxNoteBook can have wrong position (eg. wxGTK 2.7.1)
frame->sidebar->read_settings(cf);
delete cf;
SetTopWindow(frame);
if (!cmdLineParser.Found(wxT("I"))) {
// run initial commands (from ~/.fityk/init file)
wxString startup_file = get_user_conffile(startup_commands_filename);
if (wxFileExists(startup_file)) {
ftk->get_ui()->exec_script(wx2s(startup_file));
}
}
process_argv(cmdLineParser);
frame->after_cmd_updates();
return true;
}
int FApp::OnExit()
{
delete ftk;
wxConfig::Get()->Write(wxT("/FitykVersion"), pchar2wx(VERSION));
delete wxConfig::Set((wxConfig *) NULL);
return 0;
}
namespace {
struct less_filename : public binary_function<string, string, bool> {
int n;
less_filename(int n_) : n(n_) {}
bool operator()(string x, string y)
{
if (isdigit(x[n]) && isdigit(y[n])) {
string xc(x, n), yc(y, n);
return strtod(xc.c_str(), 0) < strtod(yc.c_str(), 0);
}
else
return x < y;
}
};
int find_common_prefix_length(vector<string> const& p)
{
assert(p.size() > 1);
for (size_t n = 0; n < p.begin()->size(); ++n)
for (vector<string>::const_iterator i = p.begin()+1; i != p.end(); ++i)
if (n >= i->size() || (*i)[n] != (*p.begin())[n])
return n;
return p.begin()->size();
}
} // anonymous namespace
/// parse and execute command line switches and arguments
void FApp::process_argv(wxCmdLineParser &cmdLineParser)
{
wxString cmd;
if (cmdLineParser.Found(wxT("c"), &cmd))
ftk->get_ui()->exec_and_log(wx2s(cmd));
//the rest of parameters/arguments are scripts and/or data files
vector<string> p;
for (unsigned int i = 0; i < cmdLineParser.GetParamCount(); i++)
p.push_back(wx2s(cmdLineParser.GetParam(i)));
if (cmdLineParser.Found(wxT("r")) && p.size() > 1) { // reorder
sort(p.begin(), p.end(), less_filename(find_common_prefix_length(p)));
}
for (vector<string>::const_iterator i = p.begin(); i != p.end(); ++i)
ftk->get_ui()->process_cmd_line_filename(*i);
if (ftk->get_ds_count() > 1) {
frame->SwitchSideBar(true);
// zoom to show all loaded datafiles
ftk->view.set_datasets(ftk->get_dsds());
ftk->view.fit();
}
}
#ifndef HELP_DIR
# define HELP_DIR "."
#endif
//TODO when wx>=2.8 -> use GetResourcesDir() on all platforms
string get_full_path_of_help_file (const string &name)
{
#ifdef __WXMAC__
return wx2s(wxStandardPaths::Get().GetResourcesDir() + wxFILE_SEP_PATH)
+ name;
#else
// filename --> path and filename
// if there is no `name' file in HELP_DIR, we are trying a few other dirs
wxString exedir = wxPathOnly(wxGetApp().argv[0]);
if (!exedir.IsEmpty() && exedir.Last() != wxFILE_SEP_PATH)
exedir += wxFILE_SEP_PATH;
wxChar *possible_paths[] = {
wxT(HELP_DIR),
wxT("."),
wxT(".."),
wxT("doc"),
wxT("../doc"),
0
};
for (int flag = 0; flag <= 1; ++flag) {
for (int i = 0; possible_paths[i]; i++) {
wxString path = !flag ? wxString(possible_paths[i])
: exedir + possible_paths[i];
if (!path.IsEmpty() && path.Last() != wxFILE_SEP_PATH)
path += wxFILE_SEP_PATH;
string path_name = wx2s(path) + name;
//wxMessageBox(("Looking for \n" + path_name).c_str());
if (wxFileExists(s2wx(path_name)))
return path_name;
}
}
return name;
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1