📄 mathdrawer.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 + -