// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// Licence: GNU General Public License version 2
// $Id: plot.h 288 2007-04-22 02:14:02Z wojdyr $

#ifndef FITYK__WX_PLOT__H__
#define FITYK__WX_PLOT__H__

#include <limits.h>
#include <vector>
#include <wx/config.h>
#include "../data.h" //Point

// INT_MIN, given as coordinate, is invalid value, means "cancel drawing"

class Sum;
class Data;
class View;

enum MouseActEnum  { mat_start, mat_stop, mat_move, mat_redraw };

void draw_line_with_style(wxDC& dc, int style, 
                          wxCoord X1, wxCoord Y1, wxCoord X2, wxCoord Y2);

// convention here: lowercase coordinates of point are real values,
// and uppercase ones are coordinates of point on screen (integers).


class BufferedPanel : public wxPanel
{
public:
    BufferedPanel(wxWindow *parent)
       : wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, 
                 wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE) {}
    void refresh(bool now=false);
    void buffered_draw();
    virtual void draw(wxDC &dc, bool monochrome=false) = 0;

protected:
    wxColour backgroundCol;

private:
    wxMemoryDC memory_dc;
    wxBitmap buffer;

    bool resize_buffer(wxDC &dc);
    void clear_and_draw();
};


/// convertion between pixels and logical values
class Scale
{
public:
    double scale, origin; 
    bool logarithm, reversed;

    Scale() : scale(1.), origin(0.), logarithm(false), reversed(false) {}

    /// value -> pixel
    int px(double val) const 
    {
        if (logarithm) {
            if (val <= 0)
                return inf_px(scale);
            val = log(val);
        }
        double t = (val - origin) * scale;
        return fabs(t) < SHRT_MAX ? static_cast<int>(t) : inf_px(t);
    }

    /// pixel -> value
    double val(int px) const
    { 
        fp a = px / scale + origin; 
        return logarithm ? exp(a) : a; 
    }

    // set scale using minimum and maximum logical values and width/height 
    // of the screen in pixels.
    // In case of y scale, where pixel=0 is at the top, m and M are switched 
    void set(fp m, fp M, int pixels);

private:
    static int inf_px(float t) { return t > 0 ? SHRT_MAX : SHRT_MIN; }
};



/// This class has no instances, MainPlot and AuxPlot are derived from it
class FPlot : public BufferedPanel 
{
public:
    FPlot (wxWindow *parent)
       : BufferedPanel(parent),
         draw_sigma(false), 
         mouse_press_X(INT_MIN), mouse_press_Y(INT_MIN),
         vlfc_prev_x(INT_MIN), vlfc_prev_x0(INT_MIN)   {}
         
    ~FPlot() {}
    wxColour const& get_bg_color() const { return backgroundCol; }
    void draw_crosshair(int X, int Y);
    void set_scale();
    int get_special_point_at_pointer(wxMouseEvent& event);
    std::vector<wxPoint> const& get_special_points() const
                                                { return special_points; }
    Scale const& get_x_scale() const { return xs; }
    Scale const& get_y_scale() const { return ys; }
    virtual void save_settings(wxConfigBase *cf) const;
    virtual void read_settings(wxConfigBase *cf);

protected:
    Scale xs, ys;
    wxColour activeDataCol, inactiveDataCol, xAxisCol;
    wxFont ticsFont;
    int point_radius;
    bool line_between_points;
    bool draw_sigma;
    bool x_axis_visible, y_axis_visible, xtics_visible, ytics_visible,
         xminor_tics_visible, yminor_tics_visible;
    bool x_grid, y_grid;
    int x_max_tics, y_max_tics, x_tic_size, y_tic_size;
    int mouse_press_X, mouse_press_Y;
    int vlfc_prev_x, vlfc_prev_x0; //vertical lines following cursor
    std::vector<wxPoint> special_points; //used to mark positions of peak tops

    void draw_dashed_vert_line(int X, int style=wxSHORT_DASH);
    bool vert_line_following_cursor(MouseActEnum ma, int x=0, int x0=INT_MIN);
    void draw_xtics (wxDC& dc, View const& v, bool set_pen=true);
    void draw_ytics (wxDC& dc, View const &v, bool set_pen=true);
    double get_max_abs_y(double (*compute_y)(std::vector<Point>::const_iterator,
                                             Sum const*),
                         std::vector<Point>::const_iterator first,
                         std::vector<Point>::const_iterator last,
                         Sum const* sum);
    void draw_data (wxDC& dc, 
                    double (*compute_y)(std::vector<Point>::const_iterator, 
                                        Sum const*),
                    Data const* data, 
                    Sum const* sum, 
                    wxColour const& color = wxNullColour,
                    wxColour const& inactive_color = wxNullColour,
                    int Y_offset = 0,
                    bool cumulative=false);
    void change_tics_font();

    DECLARE_EVENT_TABLE()
};

// utilities

inline wxColour invert_colour(const wxColour& col)
{ return wxColour(255 - col.Red(), 255 - col.Green(), 255 - col.Blue()); }

std::vector<double> scale_tics_step (double beg, double end, int max_tics, 
                                 std::vector<double> &minors, bool log=false);

#endif 



syntax highlighted by Code2HTML, v. 0.9.1