// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// Licence: GNU General Public License version 2
// $Id: dload.cpp 345 2007-08-21 01:09:15Z wojdyr $
/// In this file:
/// Custom Data Load Dialog (DLoadDlg) and helpers
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <fstream>
#include <vector>
#include <wx/statline.h>
#include <wx/file.h>
#include <wx/filename.h>
#include "dload.h"
#include "gui.h" // frame->add_recent_data_file(get_filename()
#include "plot.h" // scale_tics_step()
#include "../data.h"
#include "../logic.h"
#include "../settings.h"
#include "../common.h" //iround
using namespace std;
enum {
ID_DXLOAD_STDDEV_CB =28000,
ID_DXLOAD_COLX ,
ID_DXLOAD_COLY ,
ID_DXLOAD_SDS ,
ID_DXLOAD_HTITLE ,
ID_DXLOAD_AUTO_TEXT ,
ID_DXLOAD_AUTO_PLOT ,
ID_DXLOAD_OPENHERE ,
ID_DXLOAD_OPENNEW ,
ID_DXLOAD_FN
};
class PreviewPlot : public BufferedPanel
{
public:
auto_ptr<Data> data;
PreviewPlot(wxWindow* parent)
: BufferedPanel(parent), data(new Data(ftk))
{ backgroundCol = *wxBLACK; }
void OnPaint(wxPaintEvent &event);
void draw(wxDC &dc, bool);
private:
double xScale, yScale;
double xOffset, yOffset;
int H;
int getX(double x) { return iround(x * xScale + xOffset); }
int getY(double y) { return iround(y * yScale + yOffset); }
void prepare_scaling(wxDC &dc);
void draw_scale(wxDC &dc);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE (PreviewPlot, wxPanel)
EVT_PAINT (PreviewPlot::OnPaint)
END_EVENT_TABLE()
void PreviewPlot::OnPaint(wxPaintEvent&)
{
buffered_draw();
}
void PreviewPlot::draw(wxDC &dc, bool)
{
if (data->is_empty())
return;
prepare_scaling(dc);
draw_scale(dc);
vector<Point> const& pp = data->points();
dc.SetPen(*wxGREEN_PEN);
for (vector<Point>::const_iterator i = pp.begin(); i != pp.end(); ++i)
dc.DrawPoint(getX(i->x), getY(i->y));
}
void PreviewPlot::prepare_scaling(wxDC &dc)
{
double const margin = 0.1;
double dx = data->get_x_max() - data->get_x_min();
double dy = data->get_y_max() - data->get_y_min();
int W = GetClientSize().GetWidth();
H = GetClientSize().GetHeight();
xScale = (1 - 1.2 * margin) * W / dx;
yScale = - (1 - 1.2 * margin) * H / dy;
xOffset = - data->get_x_min() * xScale + margin * W;
yOffset = H - data->get_y_min() * yScale - margin * H;
}
void PreviewPlot::draw_scale(wxDC &dc)
{
dc.SetPen(*wxWHITE_PEN);
dc.SetTextForeground(*wxWHITE);
dc.SetFont(*wxSMALL_FONT);
vector<double> minors;
vector<double> tics
= scale_tics_step(data->get_x_min(), data->get_x_max(), 4, minors);
for (vector<double>::const_iterator i = tics.begin(); i != tics.end(); ++i){
int X = getX(*i);
wxString label = s2wx(S(*i));
if (label == wxT("-0"))
label = wxT("0");
wxCoord tw, th;
dc.GetTextExtent (label, &tw, &th);
int Y = dc.DeviceToLogicalY(H - th - 2);
dc.DrawText (label, X - tw/2, Y + 1);
dc.DrawLine (X, Y, X, Y - 4);
}
tics = scale_tics_step(data->get_y_min(), data->get_y_max(), 4, minors);
for (vector<double>::const_iterator i = tics.begin(); i != tics.end(); ++i){
int Y = getY(*i);
wxString label = s2wx(S(*i));
if (label == wxT("-0"))
label = wxT("0");
wxCoord tw, th;
dc.GetTextExtent (label, &tw, &th);
dc.DrawText (label, dc.DeviceToLogicalX(5), Y - th/2);
dc.DrawLine (dc.DeviceToLogicalX(0), Y, dc.DeviceToLogicalX(4), Y);
}
}
BEGIN_EVENT_TABLE(DLoadDlg, wxDialog)
EVT_CHECKBOX (ID_DXLOAD_STDDEV_CB, DLoadDlg::OnStdDevCheckBox)
EVT_CHECKBOX (ID_DXLOAD_HTITLE, DLoadDlg::OnHTitleCheckBox)
EVT_CHECKBOX (ID_DXLOAD_AUTO_TEXT, DLoadDlg::OnAutoTextCheckBox)
EVT_CHECKBOX (ID_DXLOAD_AUTO_PLOT, DLoadDlg::OnAutoPlotCheckBox)
EVT_SPINCTRL (ID_DXLOAD_COLX, DLoadDlg::OnColumnChanged)
EVT_SPINCTRL (ID_DXLOAD_COLY, DLoadDlg::OnColumnChanged)
EVT_BUTTON (wxID_CLOSE, DLoadDlg::OnClose)
EVT_BUTTON (ID_DXLOAD_OPENHERE, DLoadDlg::OnOpenHere)
EVT_BUTTON (ID_DXLOAD_OPENNEW, DLoadDlg::OnOpenNew)
EVT_TREE_SEL_CHANGED (-1, DLoadDlg::OnPathSelectionChanged)
EVT_TEXT_ENTER(ID_DXLOAD_FN, DLoadDlg::OnPathTextChanged)
END_EVENT_TABLE()
DLoadDlg::DLoadDlg (wxWindow* parent, wxWindowID id, int n, Data* data)
: wxDialog(parent, id, wxT("Data load (custom)"),
wxDefaultPosition, wxSize(600, 500),
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER),
data_nr(n), initialized(false)
{
// +------------------------------------------+
// | | |
// | | rupper_panel |
// | | |
// | left_panel | |
// | +-----------------------+
// | | |
// | | rbottom_panel |
// | | |
// | | |
// +------------------------------------------+
// | buttons here, directly on the *this |
// +------------------------------------------+
wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL);
splitter = new ProportionalSplitter(this, -1, 0.5);
left_panel = new wxPanel(splitter, -1);
wxBoxSizer *left_sizer = new wxBoxSizer(wxVERTICAL);
right_splitter = new ProportionalSplitter(splitter, -1, 0.5);
rupper_panel = new wxPanel(right_splitter, -1);
wxBoxSizer *rupper_sizer = new wxBoxSizer(wxVERTICAL);
rbottom_panel = new wxPanel(right_splitter, -1);
wxBoxSizer *rbottom_sizer = new wxBoxSizer(wxVERTICAL);
// ----- left panel -----
dir_ctrl = new wxGenericDirCtrl(left_panel, -1, wxDirDialogDefaultFolderStr,
wxDefaultPosition, wxDefaultSize,
// On MSW wxGenericDirCtrl with filteres vanishes
//#ifndef __WXMSW__
// wxDIRCTRL_SHOW_FILTERS,
//#else
0,
//#endif
// multiple wildcards, eg.
// |*.dat;*.DAT;*.xy;*.XY;*.fio;*.FIO
// are not supported by wxGenericDirCtrl
wxT("all files (*)|*")
wxT("|ASCII x y files (*)|*" )
wxT("|rit files (*.rit)|*.rit")
wxT("|cpi files (*.cpi)|*.cpi")
wxT("|mca files (*.mca)|*.mca")
wxT("|Siemens/Bruker (*.raw)|*.raw"));
left_sizer->Add(dir_ctrl, 1, wxALL|wxEXPAND, 5);
wxFileName path = s2wx(data->get_filename());
path.Normalize();
dir_ctrl->SetPath(path.GetFullPath());
filename_tc = new KFTextCtrl(left_panel, ID_DXLOAD_FN, path.GetFullPath());
left_sizer->Add (filename_tc, 0, wxALL|wxEXPAND, 5);
// selecting columns
columns_panel = new wxPanel (left_panel, -1);
wxStaticBoxSizer *h2a_sizer = new wxStaticBoxSizer(wxHORIZONTAL,
columns_panel, wxT("Select columns (0 for point index):"));
h2a_sizer->Add (new wxStaticText (columns_panel, -1, wxT("x")),
0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
x_column = new SpinCtrl (columns_panel, ID_DXLOAD_COLX, 1, 0, 99, 50);
h2a_sizer->Add (x_column, 0, wxALL|wxALIGN_LEFT, 5);
h2a_sizer->Add (new wxStaticText (columns_panel, -1, wxT("y")),
0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
y_column = new SpinCtrl (columns_panel, ID_DXLOAD_COLY, 2, 0, 99, 50);
h2a_sizer->Add (y_column, 0, wxALL|wxALIGN_LEFT, 5);
std_dev_cb = new wxCheckBox(columns_panel, ID_DXLOAD_STDDEV_CB,
wxT("std.dev."));
std_dev_cb->SetValue(false);
h2a_sizer->Add(std_dev_cb, 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL,5);
s_column = new SpinCtrl(columns_panel, -1, 3, 1, 99, 50);
h2a_sizer->Add(s_column, 0, wxALL|wxALIGN_LEFT, 5);
columns_panel->SetSizer(h2a_sizer);
left_sizer->Add (columns_panel, 0, wxALL|wxEXPAND, 5);
if (data->get_given_cols().size() > 1) {
x_column->SetValue(data->get_given_cols()[0]);
y_column->SetValue(data->get_given_cols()[1]);
if (data->get_given_cols().size() > 2) {
std_dev_cb->SetValue(true);
s_column->SetValue(data->get_given_cols()[2]);
}
}
bool def_sqrt = (ftk->get_settings()->getp("data-default-sigma") == "sqrt");
sd_sqrt_cb = new wxCheckBox(left_panel, ID_DXLOAD_SDS,
wxT("set std. dev. as max(sqrt(y), 1.0)"));
sd_sqrt_cb->SetValue(def_sqrt);
left_sizer->Add (sd_sqrt_cb, 0, wxALL|wxEXPAND, 5);
wxStaticBoxSizer *dt_sizer = new wxStaticBoxSizer(wxVERTICAL,
left_panel, wxT("Data title (optional):"));
htitle_cb = new wxCheckBox(left_panel, ID_DXLOAD_HTITLE,
wxT("get from 1st line"));
dt_sizer->Add(htitle_cb, 0, wxALL, 5);
title_tc = new wxTextCtrl(left_panel, -1, wxT(""));
dt_sizer->Add(title_tc, 0, wxALL|wxEXPAND, 5);
left_sizer->Add (dt_sizer, 0, wxALL|wxEXPAND, 5);
StdDevCheckBoxChanged();
// ----- right upper panel -----
text_preview = new wxTextCtrl(rupper_panel, -1, wxT(""),
wxDefaultPosition, wxDefaultSize,
wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE);
rupper_sizer->Add(text_preview, 1, wxEXPAND|wxALL, 5);
auto_text_cb = new wxCheckBox(rupper_panel, ID_DXLOAD_AUTO_TEXT,
wxT("view the first 64kB of file as text"));
auto_text_cb->SetValue(false);
rupper_sizer->Add(auto_text_cb, 0, wxALL, 5);
// ----- right bottom panel -----
plot_preview = new PreviewPlot(rbottom_panel);
rbottom_sizer->Add(plot_preview, 1, wxEXPAND|wxALL, 5);
auto_plot_cb = new wxCheckBox(rbottom_panel, ID_DXLOAD_AUTO_PLOT,
wxT("plot"));
auto_plot_cb->SetValue(false);
rbottom_sizer->Add(auto_plot_cb, 0, wxALL, 5);
// ------ finishing layout (+buttons) -----------
left_panel->SetSizerAndFit(left_sizer);
rupper_panel->SetSizerAndFit(rupper_sizer);
rbottom_panel->SetSizerAndFit(rbottom_sizer);
splitter->SplitVertically(left_panel, right_splitter);
right_splitter->SplitHorizontally(rupper_panel, rbottom_panel);
top_sizer->Add(splitter, 1, wxEXPAND);
top_sizer->Add (new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5);
wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
open_here = new wxButton(this, ID_DXLOAD_OPENHERE,
s2wx("&Replace dataset @"+S(data_nr)));
open_new = new wxButton(this, ID_DXLOAD_OPENNEW,
wxT("&Open as new dataset"));
button_sizer->Add(open_here, 0, wxALL, 5);
button_sizer->Add(open_new, 0, wxALL, 5);
button_sizer->Add(new wxButton(this, wxID_CLOSE, wxT("&Close")),
0, wxALL, 5);
top_sizer->Add(button_sizer, 0, wxALL|wxALIGN_CENTER, 0);
initialized = true;
SetSizer(top_sizer);
on_filter_change();
}
void DLoadDlg::StdDevCheckBoxChanged()
{
bool v = std_dev_cb->GetValue();
s_column->Enable(v);
sd_sqrt_cb->Enable(!v);
}
void DLoadDlg::OnHTitleCheckBox (wxCommandEvent& event)
{
if (event.IsChecked())
update_title_from_file();
title_tc->Enable(!event.IsChecked());
}
void DLoadDlg::update_title_from_file()
{
assert (htitle_cb->GetValue());
ifstream f(dir_ctrl->GetFilePath().fn_str());
int col = columns_panel->IsEnabled() ? y_column->GetValue() : 0;
string title = Data::read_one_line_as_title(f, col);
title_tc->SetValue(s2wx(title));
}
void DLoadDlg::OnAutoTextCheckBox (wxCommandEvent& event)
{
if (event.IsChecked())
update_text_preview();
else
text_preview->Clear();
}
void DLoadDlg::OnAutoPlotCheckBox (wxCommandEvent&)
{
update_plot_preview();
}
void DLoadDlg::OnColumnChanged (wxSpinEvent&)
{
if (auto_plot_cb->GetValue())
update_plot_preview();
if (htitle_cb->GetValue())
update_title_from_file();
}
void DLoadDlg::OnClose (wxCommandEvent&)
{
close_it(this);
}
void DLoadDlg::OnOpenHere (wxCommandEvent&)
{
ftk->exec(get_command("@" + S(data_nr), data_nr));
frame->add_recent_data_file(get_filename());
}
void DLoadDlg::OnOpenNew (wxCommandEvent&)
{
int d_nr = ftk->get_ds_count();
if (d_nr == 1 && !ftk->get_ds(0)->has_any_info())
d_nr = 0; // special case, @+ will not add new data slot
ftk->exec(get_command("@+", d_nr));
frame->add_recent_data_file(get_filename());
}
void DLoadDlg::update_text_preview()
{
static char buffer[65536];
int buf_size = sizeof(buffer)/sizeof(buffer[0]);
fill(buffer, buffer+buf_size, 0);
wxString path = dir_ctrl->GetFilePath();
text_preview->Clear();
if (wxFileExists(path)) {
wxFile(path).Read(buffer, buf_size-1);
text_preview->SetValue(pchar2wx(buffer));
}
}
void DLoadDlg::update_plot_preview()
{
if (auto_plot_cb->GetValue()) {
std::vector<int> cols;
if (columns_panel->IsEnabled()) {
cols.push_back(x_column->GetValue());
cols.push_back(y_column->GetValue());
}
ftk->get_ui()->keep_quiet = true;
try {
plot_preview->data->load_file(wx2s(dir_ctrl->GetFilePath()),
"", cols, true);
} catch (ExecuteError&) {
plot_preview->data->clear();
}
ftk->get_ui()->keep_quiet = false;
}
else {
plot_preview->data->clear();
}
plot_preview->refresh();
}
void DLoadDlg::on_filter_change()
{
int idx = dir_ctrl->GetFilterIndex();
wxString path = dir_ctrl->GetFilePath();
bool is_text = (idx == 0 && !path.IsEmpty()
&& Data::guess_file_type(wx2s(path)) == "text")
|| idx == 1;
enable_text_options(is_text);
}
void DLoadDlg::enable_text_options(bool is_text)
{
columns_panel->Enable(is_text);
htitle_cb->Enable(is_text);
if (!is_text && htitle_cb->IsChecked())
htitle_cb->SetValue(false);
sd_sqrt_cb->Enable(!(is_text && std_dev_cb->GetValue()));
}
void DLoadDlg::on_path_change()
{
if (!initialized)
return;
wxString path = dir_ctrl->GetFilePath();
filename_tc->SetValue(path);
if (dir_ctrl->GetFilterIndex() == 0) { // all files
bool is_text = !path.IsEmpty()
&& Data::guess_file_type(wx2s(path)) == "text";
enable_text_options(is_text);
}
open_here->Enable(!path.IsEmpty());
open_new->Enable(!path.IsEmpty());
if (auto_text_cb->GetValue())
update_text_preview();
if (auto_plot_cb->GetValue())
update_plot_preview();
if (htitle_cb->GetValue())
update_title_from_file();
}
void DLoadDlg::OnPathTextChanged(wxCommandEvent&)
{
wxString path = filename_tc->GetValue().Trim();
if (wxDirExists(path) || wxFileExists(path)) {
dir_ctrl->SetPath(path);
on_path_change();
}
else
filename_tc->SetValue(dir_ctrl->GetFilePath());
}
string DLoadDlg::get_filename()
{
return wx2s(filename_tc->GetValue());
}
string DLoadDlg::get_command(string const& ds, int d_nr)
{
string cmd;
string cols;
if (columns_panel->IsEnabled()) { // a:b[:c]
int x = x_column->GetValue();
int y = y_column->GetValue();
bool has_s = std_dev_cb->GetValue();
// default parameter values are not passed explicitely
if (x != 1 || y != 2 || has_s) {
cols = " " + S(x) + "," + S(y);
if (has_s)
cols += S(",") + S(s_column->GetValue());
}
}
string filetype;
if (htitle_cb->IsChecked())
filetype = " htext";
bool def_sqrt = (ftk->get_settings()->getp("data-default-sigma") == "sqrt");
bool set_sqrt = sd_sqrt_cb->GetValue();
bool sigma_in_file = (columns_panel->IsEnabled() && std_dev_cb->GetValue());
if (!sigma_in_file && set_sqrt != def_sqrt) {
if (set_sqrt)
cmd = "with data-default-sigma=sqrt ";
else
cmd = "with data-default-sigma=one ";
}
cmd += ds + " < '" + get_filename() + "'" + filetype + cols;
if (title_tc->IsEnabled()) {
wxString t = title_tc->GetValue().Trim();
if (!t.IsEmpty())
cmd += "; @" + S(d_nr) + ".title = '" + wx2s(t) + "'";
}
return cmd;
}
syntax highlighted by Code2HTML, v. 0.9.1