⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mathdrawer.cpp

📁 graph是一款linux/unix下绘制数据曲线图形的程序
💻 CPP
字号:
/* * mathdrawer.cpp - все, что касается отрисовки графиков * Copyright (C) 2007 lester *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA *  */#include "mathdrawer.h"#include "function.h"#include "tree_view.h"#include <iostream>GdkPixbuf *pixbuf;GdkGC *gc;HMGL mgl = NULL;GladeXML *gladexml; // Хм...GtkWidget *area;extern GtkWidget *splash; // Нафиг это тут? не могу вспомнить, зачем-то надо ж былоfloat xmin = -2, xmax=2, ymin=-2, ymax=2;gint width,height;gint mousex, mousey;gboolean do_scale = FALSE;gboolean mouse_in = FALSE;gboolean begin_scale = FALSE;gint start_scalex, start_scaley;// походу это масштаб на весь экран. А там поглядимgfloat zx1=0.2, zy1=0.2, zx2=0.8, zy2=0.8;voidgraph_get_dims (float &xmin_, float &xmax_, float &ymin_, float &ymax_){    xmin_ = xmin;    xmax_ = xmax;    ymin_ = ymin;    ymax_ = ymax;}voidgraph_set_dims (float xmin_, float xmax_, float ymin_, float ymax_){    xmin = xmin_;    xmax = xmax_;    ymin = ymin_;    ymax = ymax_;    GtkWidget *spin;    // бггг я сошел с ума. Ух-ля-ля.    spin = glade_xml_get_widget (gladexml, "xmin_spin");    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), xmin );    // Дерг глейду    spin = glade_xml_get_widget (gladexml, "xmax_spin");    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), xmax );    // ...и еще раз...    spin = glade_xml_get_widget (gladexml, "ymin_spin");    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), ymin );    // ...и пока оно не сдохло, еще раз. Крута.    spin = glade_xml_get_widget (gladexml, "ymax_spin");    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), ymax );    set_modified (TRUE);    graph_update_axis();}CDECL voidon_graph_drawing_area_size_allocate (GtkWidget *widget,                                    GtkAllocation *allocation,                                    gpointer data){    width = allocation->width;    height = allocation->height;    if (mgl != NULL)    graph_render_to_pixbuf ();}CDECL gbooleanon_graph_drawing_area_motion_notify_event (GtkWidget *widget,                                        GdkEventMotion *event,                                        gpointer user_data){    mousex = static_cast<gint>(event->x);    mousey = static_cast<gint>(event->y);    gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);    return TRUE;}CDECL gbooleanon_graph_drawing_area_button_press_event (GtkWidget      *widget,                                        GdkEventButton *event,                                        gpointer        user_data){	// ноченаем мастштаб    if (event->button == 1 && do_scale)    {        begin_scale = TRUE;        start_scalex = static_cast<int>(event->x);        start_scaley = static_cast<int>(event->y);    }    // тыц на правую копачку одновременно с левой - отменяем масштаб    if (event->button == 3 && do_scale && begin_scale )    {        begin_scale = FALSE;        gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);    }    return TRUE;}CDECL gbooleanon_graph_drawing_area_button_release_event (GtkWidget      *widget,                                        GdkEventButton *event,                                        gpointer        user_data){    if (event->button == 1 && begin_scale)    {        begin_scale = FALSE;         float _x1,_x2,_y1,_y2;    // Дальше все нагло стырено у Алексея Балакина :)    _x1 = zx1+(zx2-zx1)*(start_scalex)/float(width);    _y1 = zy2-(zy2-zy1)*(event->y)/float(height);    _x2 = zx1+(zx2-zx1)*(event->x)/float(width);    _y2 = zy2-(zy2-zy1)*(start_scaley)/float(height);    std::cout << _x1 << " " << _y1 << " " << _x2 << " " << _y2 << std::endl;    if ( fabs(_x2-_x1) < 0.10 || fabs(_y2-_y1) < 0.10 ) return TRUE;    zx1=_x1;         zx2=_x2;         zy1=_y1;         zy2=_y2;    if(zx1>zx2)       {       _x1=zx1; zx1=zx2;  zx2=_x1; }    if(zy1>zy2)       {       _x1=zy1; zy1=zy2;  zy2=_x1; }        graph_render_to_pixbuf ();    }        gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);    return TRUE;}CDECL voidon_tlb_zoom_in_toggled (GtkToggleToolButton *button, gpointer data){    do_scale = gtk_toggle_tool_button_get_active (button);}CDECL gbooleanon_graph_drawing_area_enter_notify_event (GtkWidget *widget,                                        GdkEventCrossing *event,                                        gpointer user_data){    mouse_in = TRUE;    gtk_widget_queue_draw_area(area, 0, 0, widget->allocation.width,                                            widget->allocation.height);    return TRUE;}CDECL gbooleanon_graph_drawing_area_leave_notify_event (GtkWidget *widget,                                        GdkEventCrossing *event,                                        gpointer user_data){    mouse_in = FALSE;    gtk_widget_queue_draw_area(area, 0, 0, widget->allocation.width,                                            widget->allocation.height);    return TRUE;}CDECL voidon_tlb_unscale_button_clicked (GtkWidget *widget,                                gpointer user_data){    zx1 = 0.2;    zy1 = 0.2;    zx2 = 0.8;    zy2 = 0.8;    graph_render_to_pixbuf ();}CDECL gbooleanon_drawingarea_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data){    gdk_draw_pixbuf (area->window, gc, pixbuf, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);    if (mouse_in)    {        if (begin_scale)        {            gint x = 0,y = 0;            gint _w = 0, _h = 0;                x = start_scalex < mousex? start_scalex : mousex;                y = start_scaley < mousey? start_scaley : mousey;                _w = abs(mousex - start_scalex);                _h = abs(mousey - start_scaley);        gdk_gc_set_line_attributes (gc,                    1,                    GDK_LINE_ON_OFF_DASH,                    GDK_CAP_BUTT, // нафиг это надо? но пусть будет                    GDK_JOIN_BEVEL);//        gdk_gc_set_foreground (gc, &color);        gdk_draw_rectangle (area->window, gc, false, x,                            y,                            _w,                            _h);        }        gdk_gc_set_line_attributes (gc,                    1,                    GDK_LINE_SOLID,                    GDK_CAP_BUTT,                    GDK_JOIN_BEVEL);//        gdk_gc_set_foreground (gc, &color);        gdk_draw_line (area->window, gc, mousex, 0, mousex, area->allocation.height);        gdk_draw_line (area->window, gc, 0, mousey, area->allocation.width, mousey);    }    return TRUE;}CDECL voidon_graph_drawing_area_realize(GtkWidget *widget, gpointer data){    //width = widget->allocation.width;    //height = widget->allocation.height;    area = widget;    mgl = mgl_create_graph_zb(width, height);    mgl_set_size (mgl, width, height);    mgl_set_axis(mgl, xmin, ymin, 0, xmax, ymax, 0, 0, 0, 0);    mgl->dx = 1.0f;    mgl->dy = 1.0f;    mgl->NSx = 10;    mgl->NSy = 10;    mgl->Cut = true;    mgl_set_font_size (mgl, 3);    gc = gdk_gc_new(area->window);	// если удалить эту шнягу в конце,     					// поймаем сегфолт :( Хз че с ней делать    graph_render_to_pixbuf();    }CDECL voidon_spinbuttonxmin_change_value(GtkSpinButton *spin, gpointer data){    xmin = gtk_spin_button_get_value(spin);    if (xmin > xmax)    gtk_spin_button_set_value(spin, xmin-1);    graph_update_axis(); // Да, во мне живет быдлокодер}CDECL voidon_spinbuttonxmax_change_value(GtkSpinButton *spin, gpointer data){    xmax = gtk_spin_button_get_value(spin);    if (xmax < xmin)    gtk_spin_button_set_value(spin, xmax+1);    graph_update_axis();}CDECL voidon_spinbuttonymin_change_value(GtkSpinButton *spin, gpointer data){    ymin = gtk_spin_button_get_value(spin);    if (ymin > ymax)    gtk_spin_button_set_value(spin, ymin-1);    graph_update_axis();}CDECL voidon_spinbuttonymax_change_value(GtkSpinButton *spin, gpointer data){    ymax = gtk_spin_button_get_value(spin);    if (ymax < ymin)    gtk_spin_button_set_value(spin, ymax+1);    graph_update_axis();}CDECL voidon_update_graph_clicked(GtkWidget *widget, gpointer data){    gtk_widget_queue_draw_area(area, 0, 0, width, height);}CDECL voidon_export_image_activate (GtkMenuItem *menuitem, gpointer data){    GtkWidget *dlg = gtk_file_chooser_dialog_new ("Сохранить",                                    NULL,                                    GTK_FILE_CHOOSER_ACTION_SAVE,                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,                                    GTK_STOCK_SAVE, GTK_RESPONSE_OK,                                    NULL);    GtkFileFilter *filter = gtk_file_filter_new ();    gtk_file_filter_set_name (filter, "Рисунок PNG");    gtk_file_filter_add_mime_type (filter, "image/png");    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dlg), filter);    filter = gtk_file_filter_new ();    gtk_file_filter_set_name (filter, "Все файлы");    gtk_file_filter_add_pattern (filter, "*.*");    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dlg), filter);    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER(dlg), TRUE);    gint resp = gtk_dialog_run (GTK_DIALOG(dlg));    if (resp == GTK_RESPONSE_OK)    {        gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dlg));        mgl_write_png (mgl, filename, NULL);        g_free (filename); // Надо?    }    gtk_widget_destroy (dlg);}voidgraph_update_axis(){    mgl_set_axis(mgl, xmin, ymin, 0, xmax, ymax, 0, 0, 0, 0);    set_modified (TRUE);    graph_render_to_pixbuf();}voidgraph_delete_graph_drawer(){    mgl_delete_graph(mgl);    functions_delete();    g_object_unref(G_OBJECT(pixbuf));}voidprepare_mathdraw (GladeXML *_xml) // Опа, а это зачем? Пусть будет пока{    gladexml = _xml;}voidgraph_new_sheet (){        tree_view_clear ();        functions_delete ();        graph_set_dims (-2, 2, -2, 2);        graph_update_axis ();}voidgraph_render_to_pixbuf(){    FunctionList::iterator it;    FunctionList &list = functions_get_function_list();    if (mgl_get_height(mgl) != height || mgl_get_width(mgl) != width)    {       mgl_set_size(mgl, width, height);    }    //mgl_clf(mgl); // зум вроде сам чистит пикчу, так-что это не надо    mgl->Zoom (zx1, zy1, zx2, zy2);    //mgl_new_frame(mgl, 0);    mgl_box(mgl, true); // Может нафиг границы?    mgl_axis(mgl, "xy");    for (it = list.begin(); it != list.end(); ++it)    {        if ((*it)->show) // ой как я люблю побыдлокодерствовать        {            switch ((*it)->dmethod)            {                case DM_PLOT:                mgl_plot_xy(mgl, (*it)->data_x, (*it)->data_y, (*it)->style);                break;                case DM_AREA:                mgl_area_xy (mgl, (*it)->data_x, (*it)->data_y, (*it)->style);                break;                case DM_STEM:                mgl_stem_xy(mgl, (*it)->data_x, (*it)->data_y, (*it)->style);                break;                case DM_STEP:                mgl_step_xy(mgl, (*it)->data_x, (*it)->data_y, (*it)->style);                break;                case DM_BARS:                mgl_bars_xy(mgl, (*it)->data_x, (*it)->data_y, (*it)->style);                break;                default:                    std::cout << "Shit! This shouldn't ever happen!" << std::endl;            }        }    }    //mgl_end_frame(mgl);    	int w, h; // Нафиг это?	w = mgl_get_width(mgl);    h = mgl_get_height(mgl);        // Хренова тварь, я даже не знаю, удаляется пиксбуф в памяти    // или нет, а вызывать g_free как-то стрёмно    gdk_pixbuf_unref(pixbuf);    const guchar * data = mgl_get_rgb(mgl); // чё дальше делать с этим куском памяти					    // после создания пиксбуфа?	pixbuf = gdk_pixbuf_new_from_data (	data, GDK_COLORSPACE_RGB,        false, 8, w, h, w*3, NULL, NULL);    gtk_widget_queue_draw_area(area, 0, 0, w, h);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -