1
2 /*
3 * Ump - Unnamed Math Program
4 * Copyright (c) 2004-2006 by Mattias Hultgren <mattias_hultgren@tele2.se>
5 *
6 * See main.cpp
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <gtk/gtk.h>
12 #include <sys/time.h>
13 #include "ump_picturewin.h"
14 #include "main.h"
15 #include "vector.h"
16 #include "picture2gtk.h"
17 #include "math2.h"
18 #include "vartypes.h"
19
20 GtkWidget *picturewin = 0, *picwin_status, *picwin_combo_trace, *picwin_combo_action,
21 *picwin_label_trace, *picturewin_vbox, *picturewin_menu;
22 guint pic_statusid;
23 picture2gtk picbild;
24 math::Picture picbild2;
25 Format stdformat;
26 Matrix trace_matrix;
27
28 int32 SNAP_SIZE = 5;
29 struct SnapInfo
30 {
31 enum SnapType { Snap_Root, Snap_Minimum, Snap_Maximum, Snap_Intersection };
32 SnapType snap_type;
33 int32 x, intersect_with;
34 floatx fx, fy;
35 bool calculated;
36 };
37 Vector<SnapInfo> snap_info[10];
38
39 timeval action_combo_changed;
40
41 graph_settings act_settings;
42
43 int32 old_tx, old_ty;
44 int old_best_match_i = -1;
45 guchar *picwin_rowbuffer = 0, *picwin_colbuffer = 0;
46 int picwin_rowbuffer_len = 0, picwin_colbuffer_len = 0;
47
48 bool picwin_first_click_done = false;
49
50 enum LeftClickAction { LeftClickAction_Zoom, LeftClickAction_FindRoot, LeftClickAction_FindMaximumMinimum,
51 LeftClickAction_FindIntersection, LeftClickAction_CalcDerivate, LeftClickAction_CalcIntegral,
52 LeftClickAction_CalcLength };
53
54 bool picturewin_action_dont_show_dialog = false;
55
graph_settings()56 graph_settings::graph_settings() throw(error_obj)
57 {
58 show_code = false;
59 use_antialiasing = true;
60
61 width = 400;
62 height = 400;
63 xmin = "-10";
64 xmax = "10";
65 ymin = "-10";
66 ymax = "10";
67 bgcolor = picture_h::color::WHITE;
68
69 grid_on = true;
70 grid_color = picture_h::color::LIGHT_GRAY;
71 grid_scale1 = "2";
72 grid_scale2 = "2";
73 grid_type = "Rect";
74
75 axes_on = true;
76 axes_color = picture_h::color::BLACK;
77 scalex = "1";
78 scaley = "1";
79 scale_length = 3;
80
81 plot_mode = "Connected";
82 show_active_page_only = true;
83 active_page = 0;
84
85 polar_start = "0";
86 polar_stop = "2pi";
87 polar_steps = "40";
88 par_start = "-10";
89 par_stop = "10";
90 par_steps = "40";
91
92 for( int i=0; i<10; i++ )
93 {
94 func[i].show_this = false;
95 polar[i].show_this = false;
96 func[i].entry = "";
97 polar[i].entry = "";
98 if( i<5 )
99 {
100 par[i].show_this = false;
101 par[i].entry = "";
102 par[i].entry2 = "";
103 }
104 }
105 func[0].color = picture_h::color::BLUE;
106 func[1].color = picture_h::color::RED;
107 func[2].color = picture_h::color::BLACK;
108 func[3].color = picture_h::color::DARK_GREEN;
109 func[4].color = picture_h::color::PINK;
110 func[5].color = picture_h::color::ORANGE;
111 func[6].color = ((picture_h::colorrgb) { 159, 0, 255 });
112 func[7].color = ((picture_h::colorrgb) { 60, 117, 117 });
113 func[8].color = ((picture_h::colorrgb) { 0, 178, 208 });
114 func[9].color = ((picture_h::colorrgb) { 156, 103, 131 });
115
116 polar[0].color = picture_h::color::BLUE;
117 polar[1].color = picture_h::color::RED;
118 polar[2].color = picture_h::color::BLACK;
119 polar[3].color = picture_h::color::DARK_GREEN;
120 polar[4].color = picture_h::color::PINK;
121 polar[5].color = picture_h::color::ORANGE;
122 polar[6].color = ((picture_h::colorrgb) { 159, 0, 255 });
123 polar[7].color = ((picture_h::colorrgb) { 60, 117, 117 });
124 polar[8].color = ((picture_h::colorrgb) { 0, 178, 208 });
125 polar[9].color = ((picture_h::colorrgb) { 156, 103, 131 });
126
127 par[0].color = picture_h::color::BLUE;
128 par[1].color = picture_h::color::RED;
129 par[2].color = picture_h::color::BLACK;
130 par[3].color = picture_h::color::DARK_GREEN;
131 par[4].color = picture_h::color::PINK;
132 }
133
134
135 void picwin_mousedown( const picture2gtk *src, int32 x, int32 y, int32 button );
136 void find_root( int function, floatx guess, Complex &x, Complex &y ) throw(error_obj);
137 bool find_min_or_max( int function, floatx guess, Complex &x, Complex &y ) throw(error_obj); // true if minimum, false if maximum
138 void find_intersection( int f1, int f2, floatx guess, Complex &x, Complex &y ) throw(error_obj);
139
calculate_snap(SnapInfo * snap,int function)140 void calculate_snap( SnapInfo *snap, int function ) throw(error_obj)
141 {
142 Complex x, y;
143 error_obj remove_this_snap_point;
144
145 switch( snap->snap_type )
146 {
147 case SnapInfo::Snap_Root:
148 find_root( function, snap->fx, x, y );
149 break;
150
151 case SnapInfo::Snap_Maximum:
152 if( find_min_or_max( function, snap->fx, x, y ) )
153 snap->snap_type = SnapInfo::Snap_Minimum;
154 break;
155
156 case SnapInfo::Snap_Minimum:
157 if( find_min_or_max( function, snap->fx, x, y ) == false )
158 snap->snap_type = SnapInfo::Snap_Maximum;
159 break;
160
161 case SnapInfo::Snap_Intersection:
162 find_intersection( function, snap->intersect_with, snap->fx, x, y );
163 break;
164
165 default:
166 printf( "Internal error: unhandled snap_type: %ld\n", snap->snap_type );
167 throw remove_this_snap_point;
168 }
169 if( fabsx( floatx(x.real) - snap->fx ) > ( 1.01*(picbild2.get_right() - picbild2.get_left()) / floatx(picbild2.pic.get_width()) ) )
170 throw remove_this_snap_point; // there was an extreme point found but not anywhere near here
171 snap->fx = floatx( x.real );
172 snap->fy = floatx( y.real );
173 snap->calculated = true;
174 }
175
conv_combobox_index_to_function_index(int index)176 int conv_combobox_index_to_function_index(int index)
177 {
178 if(index < 2)
179 return -1;
180
181 index -= 2;
182 for( int i=0; i<10; i++ )
183 {
184 if( act_settings.func[i].show_this )
185 {
186 if( index == 0 )
187 return i;
188 index--;
189 }
190 }
191
192 return -1;
193 }
conv_function_index_to_combobox_index(int index)194 int conv_function_index_to_combobox_index(int index)
195 {
196 int ret = 1;
197
198 if( index < 0 || index >= 10 )
199 return -1;
200
201 if( !act_settings.func[index].show_this )
202 return -1;
203
204 for( int i=0; i<index; i++ )
205 {
206 if( act_settings.func[i].show_this )
207 ret++;
208 }
209 return ret+2;
210 }
211
get_x_value(int32 x,int function,SnapInfo * ptr=0)212 floatx get_x_value( int32 x, int function, SnapInfo *ptr = 0 )
213 {
214 int min_dist = SNAP_SIZE, index = -1;
215
216 if( function == -1 )
217 return floatx(trace_matrix.get_complex( x+1, 1 ).real);
218
219 for( int i=0; i<snap_info[function].get_size(); i++ )
220 {
221 if( abs(snap_info[function][i]->x -x) < min_dist )
222 {
223 if( snap_info[function][i]->calculated == false )
224 {
225 try{ calculate_snap( snap_info[function][i], function ); }
226 catch( ... ) { snap_info[function].remove( i ); i--; continue; } // this snap wasn't calculatable
227 } // let's remove it
228 min_dist = abs(snap_info[function][i]->x -x);
229 index = i;
230 }
231 }
232 if( index != -1 )
233 {
234 if( ptr != 0 )
235 *ptr = *snap_info[function][index];
236 return snap_info[function][index]->fx;
237 }
238 return floatx(trace_matrix.get_complex( x+1, 1 ).real);
239 }
get_y_value(int32 x,int function,SnapInfo * ptr=0)240 floatx get_y_value( int32 x, int function, SnapInfo *ptr = 0 )
241 {
242 int min_dist = SNAP_SIZE, index = -1;
243
244 if( function == -1 )
245 THROW_ERROR( ErrorType_General, "Intern error: Illegal value of function in get_y_value" );
246
247 for( int i=0; i<snap_info[function].get_size(); i++ )
248 {
249 if( abs(snap_info[function][i]->x -x) < min_dist )
250 {
251 if( snap_info[function][i]->calculated == false )
252 {
253 try{ calculate_snap( snap_info[function][i], function ); }
254 catch( ... ) { snap_info[function].remove( i ); i--; continue; } // this snap wasn't calculatable
255 } // let's remove it
256 min_dist = abs(snap_info[function][i]->x -x);
257 index = i;
258 }
259 }
260 if( index != -1 )
261 {
262 if( ptr != 0 )
263 *ptr = *snap_info[function][index];
264 return snap_info[function][index]->fy;
265 }
266 return floatx(trace_matrix.get_complex( x+1, function + 2 ).real);
267 }
268
find_root(int function,floatx guess,Complex & x,Complex & y)269 void find_root( int function, floatx guess, Complex &x, Complex &y ) throw(error_obj)
270 {
271 math::CodeLine code;
272 math::Variable tmpvar;
273 utf8_string str;
274 char char_str[1000];
275
276 snprintf( char_str, 1000, "x = nSolve( y%ld, x, ", function );
277 str = char_str;
278 floatx_to_string( guess, str, stdformat);
279 str.append( ", " );
280 floatx_to_string( (picbild2.get_right() - picbild2.get_left()) / (floatx(picbild2.pic.get_width()) * 5.0), str, stdformat );
281 str.append( " )\n" );
282 if( act_settings.show_code )
283 (*TEXTVIEW_FUNCTION)( str.c_str() );
284 code.set_code_line( str.c_str() );
285 code.calc( 0 );
286
287 x = *math::global_varlist.get_pointer( math::global_varlist.get_id("x") )->get_complex();
288
289 code.set_code_line( act_settings.func[function].entry.c_str() );
290 code.calc( &tmpvar );
291 y = *tmpvar.get_complex();
292 }
293
find_min_or_max(int function,floatx guess,Complex & x,Complex & y)294 bool find_min_or_max( int function, floatx guess, Complex &x, Complex &y ) throw(error_obj)
295 {
296 math::CodeLine code;
297 math::Variable tmpvar;
298 utf8_string str;
299 char char_str[500];
300
301 snprintf( char_str, 500, "ans = \"nDeriv( y%ld, x, x, ", function );
302 str = char_str;
303 floatx_to_string( (picbild2.get_right() - picbild2.get_left()) / (floatx(picbild2.pic.get_width()) * 5.0), str, stdformat );
304 str.append( " )\"\n" );
305 if( act_settings.show_code )
306 (*TEXTVIEW_FUNCTION)( str.c_str() );
307 code.set_code_line( str.c_str() );
308 code.calc( 0 );
309
310 str = "x = nSolve( ans, x, ";
311 floatx_to_string( guess, str, stdformat );
312 str.append( ", " );
313 floatx_to_string( (picbild2.get_right() - picbild2.get_left()) / (floatx(picbild2.pic.get_width()) * 5.0), str, stdformat);
314 str.append( " )\n" );
315 if( act_settings.show_code )
316 (*TEXTVIEW_FUNCTION)( str.c_str() );
317 code.set_code_line( str.c_str() );
318 code.calc( 0 );
319
320 // saves x,y for the solution
321 x = *math::global_varlist.get_pointer( math::global_varlist.get_id("x") )->get_complex();
322 code.set_code_line( act_settings.func[function].entry.c_str() );
323 code.calc( &tmpvar );
324 y = *tmpvar.get_complex();
325
326 str = "x = nDeriv( ans, x, x , ";
327 floatx_to_string( (picbild2.get_right() - picbild2.get_left()) / (floatx(picbild2.pic.get_width()) * 5.0), str, stdformat );
328 str.append( " )\n" );
329 if( act_settings.show_code )
330 (*TEXTVIEW_FUNCTION)( str.c_str() );
331 code.set_code_line( str.c_str() );
332 code.calc( 0 );
333
334 return ( floatx(math::global_varlist.get_pointer( math::global_varlist.get_id("x") )->get_complex()->real) > 0.0);
335 }
336
find_intersection(int f1,int f2,floatx guess,Complex & x,Complex & y)337 void find_intersection( int f1, int f2, floatx guess, Complex &x, Complex &y ) throw(error_obj)
338 {
339 char tmp_str[50];
340 math::Variable tmpvar;
341 math::CodeLine code;
342 utf8_string str;
343
344 snprintf( tmp_str, 50, "x = nSolve( y%ld + \" - (\" + y%ld + \")\", x, ", f1, f2 );
345 str = tmp_str;
346 floatx_to_string( guess, str, stdformat);
347 str.append( ", " );
348 floatx_to_string( (picbild2.get_right() - picbild2.get_left()) / (floatx(picbild2.pic.get_width() * 5.0)), str, stdformat);
349 str.append( " )\n" );
350 if( act_settings.show_code )
351 (*TEXTVIEW_FUNCTION)( str.c_str() );
352 code.set_code_line( str.c_str() );
353 code.calc( 0 );
354
355 x = *math::global_varlist.get_pointer( math::global_varlist.get_id("x") )->get_complex();
356 code.set_code_line( act_settings.func[f1].entry.c_str() );
357 code.calc( &tmpvar );
358 y = *tmpvar.get_complex();
359 }
360
picwin_reload_combos(int combo_action_entries)361 int picwin_reload_combos(int combo_action_entries)
362 {
363 if( combo_action_entries != 0 )
364 {
365 for( int i=0; i<7; i++ )
366 gtk_combo_box_remove_text( GTK_COMBO_BOX(picwin_combo_action), 0 );
367 }
368
369 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Zoom") );
370 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Find root") );
371 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Find maximum/minimum") );
372 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Find intersection") );
373 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Calculate derivate") );
374 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Calculate integral") );
375 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_action), _("Calculate length") );
376
377 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_action), -1 );
378
379
380 for( ; combo_action_entries > 0; combo_action_entries-- ) // removing all entries
381 gtk_combo_box_remove_text( GTK_COMBO_BOX(picwin_combo_trace), 0 );
382
383 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_trace), _("Off") );
384 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_trace), _("Auto") );
385
386 combo_action_entries = 2;
387 if( act_settings.active_page == 0 || !act_settings.show_active_page_only )
388 {
389 char tmp_str[100];
390 const char *trans = _("Locked on y%ld");
391
392 for( int i=0; i<10; i++ )
393 {
394 if( act_settings.func[i].show_this )
395 {
396 snprintf( tmp_str, 100, trans, i );
397
398 gtk_combo_box_append_text( GTK_COMBO_BOX(picwin_combo_trace), tmp_str );
399 combo_action_entries++;
400 }
401 }
402 }
403
404 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), 0 );
405
406 return combo_action_entries;
407 }
408
place_marker(float x,float y,picture_h::colorrgb color)409 void place_marker(float x, float y, picture_h::colorrgb color)
410 {
411 picbild2.pic.line( int32(x)-3, int32(y), int32(x)+3, int32(y), color );
412 picbild2.pic.line( int32(x), int32(y)-3, int32(x), int32(y)+3, color );
413
414 picbild.update_from( picbild2.pic );
415 }
416
picwin_intersection_show(int32 x)417 void picwin_intersection_show(int32 x)
418 {
419 GtkWidget *dialog, *label, *align, *vbox;
420 char tmp_str[50];
421 utf8_string str;
422 int second_function,nr;
423 GtkWidget *radios[10];
424 Complex tmp_value_x, tmp_value_y;
425
426 nr = 0;
427 for( int i=0; i<10; i++ )
428 {
429 if( act_settings.func[i].show_this )
430 nr++;
431 }
432 if( nr < 2 ) // at least 2 functions has to be drawn
433 {
434 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
435 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
436 _("At least 2 functions must be drawn\nto be able to find an intersection") );
437 gtk_window_set_title( GTK_WINDOW(dialog), _("Find intersection") );
438 gtk_dialog_run(GTK_DIALOG(dialog));
439 gtk_widget_destroy(dialog);
440
441 return;
442 }
443 else if( nr > 2 ) // if it's more than 2, dialog must be shown and user should choose which...
444 {
445 dialog = gtk_dialog_new_with_buttons( _("Find intersection"), GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
446 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
447
448 align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
449 gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
450 gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0 );
451
452 vbox = gtk_vbox_new( FALSE, 3 );
453 gtk_container_add( GTK_CONTAINER(align), vbox );
454
455 label = gtk_label_new( _("Find intersection between") );
456 gtk_misc_set_alignment( GTK_MISC(label), 0.0, 0.5 );
457 gtk_box_pack_start( GTK_BOX(vbox), label, FALSE, FALSE, 0) ;
458
459
460 snprintf( tmp_str, 50, "y%ld = \"", old_best_match_i );
461 str = tmp_str;
462 str.append( act_settings.func[old_best_match_i].entry );
463 str.append( "\"" );
464 label = gtk_label_new( str.c_str() );
465 gtk_misc_set_alignment( GTK_MISC(label), 0.05, 0.5 );
466 gtk_box_pack_start( GTK_BOX(vbox), label, FALSE, FALSE, 0 );
467
468 label = gtk_label_new( _("and") );
469 gtk_misc_set_alignment( GTK_MISC(label), 0.0, 0.5 );
470 gtk_box_pack_start( GTK_BOX(vbox), label, FALSE, FALSE, 0 );
471
472 nr = 0;
473 for(int i=0;i<10;i++)
474 {
475 if( act_settings.func[i].show_this && i != old_best_match_i )
476 {
477 snprintf( tmp_str, 50, "y%ld = \"", i );
478 str = tmp_str;
479 str.append( act_settings.func[i].entry );
480 str.append( "\"" );
481
482 label = gtk_label_new( str.c_str() );
483
484 if(nr == 0)
485 {
486 radios[0] = gtk_radio_button_new( NULL );
487 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radios[0]), TRUE );
488 }
489 else
490 radios[nr] = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(radios[0]) );
491
492 gtk_container_add( GTK_CONTAINER(radios[nr]), label );
493
494 gtk_box_pack_start( GTK_BOX(vbox), radios[nr], FALSE, FALSE, 0 );
495
496 nr++;
497 }
498 }
499
500 gtk_widget_show_all( dialog );
501
502 switch( gtk_dialog_run( GTK_DIALOG(dialog) ) )
503 {
504 case GTK_RESPONSE_OK:
505
506 second_function = 0;
507 for(int i=0;i<10;i++)
508 {
509 if( act_settings.func[i].show_this && i != old_best_match_i )
510 {
511 if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(radios[second_function]) ) ==
512 TRUE )
513 {
514 second_function = i;
515 break;
516 }
517 second_function++;
518 }
519 }
520 gtk_widget_destroy(dialog);
521 break;
522
523 default:
524 gtk_widget_destroy(dialog);
525 return;
526 }
527 }
528 else // if(nr == 2)
529 {
530 for( int i=0; i<10; i++ )
531 {
532 if( act_settings.func[i].show_this && i != old_best_match_i )
533 {
534 second_function = i;
535 break;
536 }
537 }
538 }
539
540 try
541 {
542 find_intersection( old_best_match_i, second_function, get_x_value( x, old_best_match_i ), tmp_value_x, tmp_value_y );
543
544 str = _("Intersection found at");
545 str.append( "\nx = " );
546 tmp_value_x.append_to_string( str, format );
547
548 str.append( "\ny = " );
549 tmp_value_y.append_to_string( str, format );
550 if(act_settings.show_code)
551 {
552 (*TEXTVIEW_FUNCTION)( str.c_str() );
553 (*TEXTVIEW_FUNCTION)("\n");
554 }
555 place_marker( picbild2.get_float_x_pixel( floatx(tmp_value_x.real) ),
556 picbild2.get_float_y_pixel( floatx(tmp_value_y.real)),
557 act_settings.func[old_best_match_i].color );
558
559
560 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
561 GTK_BUTTONS_OK, str.c_str() );
562 gtk_window_set_title( GTK_WINDOW(dialog), _("Find intersection") );
563 gtk_dialog_run( GTK_DIALOG(dialog) );
564 gtk_widget_destroy(dialog);
565 }
566 catch(error_obj error)
567 {
568 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
569 GTK_BUTTONS_CLOSE, error.msg );
570 gtk_window_set_title( GTK_WINDOW(dialog), _("Find intersection") );
571 gtk_dialog_run(GTK_DIALOG(dialog));
572 gtk_widget_destroy(dialog);
573 }
574 catch(...)
575 {
576 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
577 catch(error_obj error)
578 {
579 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
580 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg);
581 gtk_window_set_title( GTK_WINDOW(dialog), _("Find intersection") );
582 gtk_dialog_run(GTK_DIALOG(dialog));
583 gtk_widget_destroy(dialog);
584 }
585 }
586 }
587
picwin_calc_derivate(int32 x)588 void picwin_calc_derivate( int32 x )
589 {
590 utf8_string str, str2;
591 math::CodeLine function;
592 GtkWidget *dialog;
593
594 char char_str[1000];
595
596 try
597 {
598 str = "";
599 floatx_to_string( get_x_value( x, old_best_match_i ), str, stdformat );
600 str2 = "";
601 floatx_to_string( ((floatx(trace_matrix.get_complex( 2, 1 ).real) -
602 floatx(trace_matrix.get_complex( 1, 1 ).real))/2.0), str2, stdformat);
603 snprintf( char_str, 1000, "x = nDeriv( y%ld, x, %s, %s )", old_best_match_i, str.c_str(), str2.c_str() );
604
605 function.set_code_line( char_str );
606 function.calc( 0 );
607
608 str2 = "";
609 math::global_varlist.get_pointer( math::global_varlist.get_id("x") )->get_complex()->append_to_string( str2, format );
610
611 snprintf( char_str, 1000, _("Derivate of y%ld at X=%s is\n%s"), old_best_match_i, str.c_str(), str2.c_str() );
612
613 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
614 GTK_BUTTONS_OK, char_str );
615 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate derivate") );
616 gtk_dialog_run( GTK_DIALOG(dialog) );
617 gtk_widget_destroy(dialog);
618 }
619 catch(error_obj error)
620 {
621 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
622 GTK_BUTTONS_CLOSE, error.msg );
623 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate derivate") );
624 gtk_dialog_run(GTK_DIALOG(dialog));
625 gtk_widget_destroy(dialog);
626 }
627 catch(...)
628 {
629 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
630 catch(error_obj error)
631 {
632 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
633 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg);
634 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate deriavte") );
635 gtk_dialog_run(GTK_DIALOG(dialog));
636 gtk_widget_destroy(dialog);
637 }
638 }
639 }
640
picwin_calc_integral(int32 x)641 void picwin_calc_integral( int32 x )
642 {
643 static int32 first_x;
644 static int first_old_best_match_i;
645 utf8_string str, str2, str3;
646 math::CodeLine function;
647 GtkWidget *dialog;
648 Complex tmp_value_x;
649 int tmp_old_best_match_i;
650
651 char char_str[1000];
652
653 try
654 {
655 if( picwin_first_click_done )
656 {
657 picwin_first_click_done = false;
658
659 if( first_old_best_match_i == old_best_match_i )
660 {
661 snprintf( char_str, 1000, "x = nInt( y%ld, x, ", old_best_match_i );
662 str = char_str;
663 floatx_to_string( get_x_value( first_x, old_best_match_i ), str, stdformat );
664 str.append( ", " );
665 floatx_to_string( get_x_value( x, old_best_match_i ), str, stdformat );
666 snprintf( char_str, 1000, ", %ld )", abs(first_x-x)*10 );
667 str.append( char_str );
668
669 function.set_code_line( str.c_str() );
670 function.calc( 0 );
671
672 tmp_value_x = *math::global_varlist.get_pointer(
673 math::global_varlist.get_id("x") )->get_complex();
674
675 snprintf( char_str, 1000, "plot_picture = shade( plot_picture, y%ld, \"0\", x, ", old_best_match_i );
676 str = char_str;
677 floatx_to_string( get_x_value( first_x, old_best_match_i ), str, stdformat );
678 str.append( ", " );
679 floatx_to_string( get_x_value( x, old_best_match_i ), str, stdformat );
680 snprintf( char_str, 1000, ", 0, [[ %f, %f, %f ]] )",
681 act_settings.func[old_best_match_i].color.red/255.0f,
682 act_settings.func[old_best_match_i].color.green/255.0f,
683 act_settings.func[old_best_match_i].color.blue/255.0f );
684 str.append( char_str );
685 function.set_code_line( str.c_str() );
686 function.calc( 0 );
687 }
688 else
689 {
690 snprintf( char_str, 1000, "x = nInt( y%ld + \" - ( \" + y%ld + \" )\", x, ", first_old_best_match_i,
691 old_best_match_i );
692 str = char_str;
693 floatx_to_string( get_x_value( first_x, first_old_best_match_i ), str, stdformat );
694 str.append( ", " );
695 floatx_to_string( get_x_value( x, old_best_match_i ), str, stdformat );
696 snprintf( char_str, 1000, ", %ld )", abs(first_x-x)*10 );
697 str.append( char_str );
698
699 function.set_code_line( str.c_str() );
700 function.calc( 0 );
701
702 tmp_value_x = *math::global_varlist.get_pointer(
703 math::global_varlist.get_id("x") )->get_complex();
704
705 snprintf( char_str, 1000, "plot_picture = shade( plot_picture, y%ld, y%ld, x, ", first_old_best_match_i,
706 old_best_match_i );
707 str = char_str;
708 floatx_to_string( get_x_value( first_x, first_old_best_match_i ), str, stdformat );
709 str.append( ", " );
710 floatx_to_string( get_x_value( x, old_best_match_i ), str, stdformat);
711 snprintf( char_str, 1000, ", 0, [[ %f, %f, %f ]] )",
712 act_settings.func[first_old_best_match_i].color.red/255.0f,
713 act_settings.func[first_old_best_match_i].color.green/255.0f,
714 act_settings.func[first_old_best_match_i].color.blue/255.0f );
715 str.append( char_str );
716 function.set_code_line( str.c_str() );
717 function.calc( 0 );
718 }
719 {
720 int tmp = gtk_combo_box_get_active( GTK_COMBO_BOX(picwin_combo_trace) );
721
722 tmp_old_best_match_i = old_best_match_i; // saving this because it will be reseted to -1 when
723 function.set_code_line("show plot_picture"); // redrawing the picture
724 function.calc( 0 );
725
726 gtk_widget_set_sensitive( picwin_combo_trace, TRUE );
727 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), tmp ); // auto-trace
728 gtk_widget_set_sensitive( picwin_combo_action, TRUE );
729 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_action), LeftClickAction_CalcIntegral );
730
731 picbild.mousedown_func = picwin_mousedown;
732 }
733
734 str = ""; str2 = ""; str3 = "";
735 floatx_to_string( get_x_value( first_x, first_old_best_match_i ), str, stdformat );
736 floatx_to_string( get_x_value( x, tmp_old_best_match_i ), str2, stdformat );
737 tmp_value_x.append_to_string( str3, format );
738
739 snprintf( char_str, 1000, _("Integral from %s to %s is\n%s"), str.c_str(), str2.c_str(), str3.c_str() );
740
741 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
742 GTK_BUTTONS_OK, char_str );
743 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate integral") );
744 gtk_dialog_run( GTK_DIALOG(dialog) );
745 gtk_widget_destroy(dialog);
746 }
747 else
748 {
749 first_x = x;
750 first_old_best_match_i = old_best_match_i;
751 picwin_first_click_done = true;
752
753 gettimeofday( &action_combo_changed, 0 );
754 gtk_label_set_text( GTK_LABEL(picwin_status), _("Select end point") );
755 }
756 }
757 catch(error_obj error)
758 {
759 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
760 GTK_BUTTONS_CLOSE, error.msg );
761 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate integral") );
762 gtk_dialog_run(GTK_DIALOG(dialog));
763 gtk_widget_destroy(dialog);
764 }
765 catch(...)
766 {
767 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
768 catch(error_obj error)
769 {
770 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
771 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg);
772 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate integral") );
773 gtk_dialog_run(GTK_DIALOG(dialog));
774 gtk_widget_destroy(dialog);
775 }
776 }
777 }
778
779
picwin_calc_length(int32 x)780 void picwin_calc_length( int32 x )
781 {
782 static int32 first_x;
783 static int first_old_best_match_i;
784 utf8_string str, str2, str3;
785 math::CodeLine function;
786 GtkWidget *dialog;
787 Complex tmp_value_x;
788
789 char char_str[1000];
790
791 try
792 {
793 if( picwin_first_click_done )
794 {
795 picwin_first_click_done = false;
796
797 if( first_old_best_match_i == old_best_match_i )
798 {
799 snprintf( char_str, 1000, "x = nInt( \"sqrt( 1.0 + nDeriv( y%ld, x, x, ", old_best_match_i );
800 str = char_str;
801 floatx_to_string( ((floatx(trace_matrix.get_complex( 2, 1 ).real) -
802 floatx(trace_matrix.get_complex( 1, 1 ).real))/10.0), str, stdformat);
803 str.append( " ) ^2 )\", x, " );
804 floatx_to_string( get_x_value( first_x, old_best_match_i ), str, stdformat);
805 str.append( ", " );
806 floatx_to_string( get_x_value( x, old_best_match_i ), str, stdformat);
807 snprintf( char_str, 1000, ", %ld )", abs(first_x-x)*10 );
808 str.append( char_str );
809
810 function.set_code_line( str.c_str() );
811 function.calc( 0 );
812
813 tmp_value_x = *math::global_varlist.get_pointer( math::global_varlist.get_id("x") )->get_complex();
814 }
815 else
816 {
817 error_obj error;
818 snprintf( error.msg, ERROR_OBJ_MSG_LEN, _("Start and end point must both\nbe at the same function.") );
819 throw error;
820 }
821
822 str = ""; str2 = ""; str3 = "";
823 floatx_to_string( get_x_value( first_x, old_best_match_i ), str, stdformat);
824 floatx_to_string( get_x_value( x, old_best_match_i ), str2, stdformat);
825 tmp_value_x.append_to_string( str3, format );
826
827 snprintf( char_str, 1000, _("The length of y%ld from %s to %s is\n%s"), old_best_match_i, str.c_str(),
828 str2.c_str(), str3.c_str() );
829
830 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
831 GTK_BUTTONS_OK, char_str );
832 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate length") );
833 gtk_dialog_run( GTK_DIALOG(dialog) );
834 gtk_widget_destroy(dialog);
835 }
836 else
837 {
838 first_x = x;
839 first_old_best_match_i = old_best_match_i;
840 picwin_first_click_done = true;
841
842 gettimeofday( &action_combo_changed, 0 );
843 gtk_label_set_text( GTK_LABEL(picwin_status), _("Select end point") );
844 }
845 }
846 catch(error_obj error)
847 {
848 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
849 GTK_BUTTONS_CLOSE, error.msg );
850 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate length") );
851 gtk_dialog_run(GTK_DIALOG(dialog));
852 gtk_widget_destroy(dialog);
853 }
854 catch(...)
855 {
856 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
857 catch(error_obj error)
858 {
859 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
860 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg);
861 gtk_window_set_title( GTK_WINDOW(dialog), _("Calculate length") );
862 gtk_dialog_run(GTK_DIALOG(dialog));
863 gtk_widget_destroy(dialog);
864 }
865 }
866 }
867
picwin_mousedown(const picture2gtk * src,int32 x,int32 y,int32 button)868 void picwin_mousedown( const picture2gtk *src, int32 x, int32 y, int32 button )
869 {
870 utf8_string str;
871 floatx xcenter, ycenter, width, height;
872 math::Variable tmpvar;
873 char char_str[1000];
874
875 if( old_best_match_i != -1 )
876 {
877 x = old_tx;
878 y = old_ty;
879 }
880
881 switch(button)
882 {
883 case 1: // left button
884 if( GTK_WIDGET_IS_SENSITIVE(picwin_combo_trace) == TRUE )
885 {
886 switch(gtk_combo_box_get_active( GTK_COMBO_BOX(picwin_combo_action) ))
887 {
888 case LeftClickAction_Zoom:
889
890 xcenter = picbild2.get_x_value( x );
891 ycenter = picbild2.get_y_value( y );
892 width = picbild2.get_right() - picbild2.get_left();
893 height = picbild2.get_top() - picbild2.get_bottom();
894 width /= 4.0;
895 height /= 4.0;
896
897 try
898 {
899 floatx_to_string( xcenter-width, str, stdformat);
900 act_settings.xmin = str.c_str();
901
902 str = "";
903 floatx_to_string( xcenter+width, str, stdformat);
904 act_settings.xmax = str.c_str();
905
906 str = "";
907 floatx_to_string( ycenter-height, str, stdformat);
908 act_settings.ymin = str.c_str();
909
910 str = "";
911 floatx_to_string( ycenter+height, str, stdformat);
912 act_settings.ymax = str.c_str();
913
914 {
915 gint tmpint;
916 tmpint = gtk_combo_box_get_active(GTK_COMBO_BOX(picwin_combo_trace));
917 picturewin_show( (graph_settings *)(0) );
918 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), tmpint );
919 }
920 }
921 catch(...) { }
922 break;
923
924 case LeftClickAction_FindRoot:
925 {
926 GtkWidget *dialog;
927 Complex tmp_value_x,tmp_value_y;
928
929 if( old_best_match_i == -1 )
930 return;
931
932 try
933 {
934 find_root( old_best_match_i, get_x_value( x, old_best_match_i ), tmp_value_x, tmp_value_y );
935
936 str = "x = ";
937 tmp_value_x.append_to_string( str, format );
938 if( act_settings.show_code )
939 {
940 (*TEXTVIEW_FUNCTION)( str.c_str() );
941 (*TEXTVIEW_FUNCTION)( "\n" );
942 }
943 place_marker( picbild2.get_float_x_pixel( floatx(tmp_value_x.real) ),
944 picbild2.get_float_y_pixel( floatx(tmp_value_y.real)),
945 act_settings.func[old_best_match_i].color );
946
947 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
948 GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
949 str.c_str() );
950 gtk_window_set_title( GTK_WINDOW(dialog), _("Find root") );
951 gtk_dialog_run( GTK_DIALOG(dialog) );
952 gtk_widget_destroy( dialog );
953 }
954 catch(error_obj error)
955 {
956 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
957 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
958 error.msg );
959 gtk_window_set_title( GTK_WINDOW(dialog), _("Find root") );
960 gtk_dialog_run( GTK_DIALOG(dialog) );
961 gtk_widget_destroy( dialog );
962 }
963 catch(...)
964 {
965 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
966 catch(error_obj error)
967 {
968 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin),
969 GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
970 GTK_BUTTONS_CLOSE, error.msg );
971 gtk_window_set_title( GTK_WINDOW(dialog), _("Find root") );
972 gtk_dialog_run( GTK_DIALOG(dialog) );
973 gtk_widget_destroy( dialog );
974 }
975 }
976 }
977 break; // LeftClickAction_FindRoot
978
979 case LeftClickAction_FindMaximumMinimum:
980 {
981 GtkWidget *dialog;
982 Complex tmp_value_x,tmp_value_y;
983
984 if( old_best_match_i == -1 )
985 return;
986
987 try
988 {
989 if( find_min_or_max( old_best_match_i, get_x_value( x, old_best_match_i ),
990 tmp_value_x, tmp_value_y ) )
991 str = _("Local minimum at");
992 else
993 str = _("Local maximum at");
994
995 str.append( "\nx = " );
996 tmp_value_x.append_to_string( str, format );
997
998 str.append( "\ny = " );
999 tmp_value_y.append_to_string( str, format );
1000 if(act_settings.show_code)
1001 {
1002 (*TEXTVIEW_FUNCTION)( str.c_str() );
1003 (*TEXTVIEW_FUNCTION)( "\n" );
1004 }
1005 place_marker( picbild2.get_float_x_pixel( floatx(tmp_value_x.real) ),
1006 picbild2.get_float_y_pixel( floatx(tmp_value_y.real)),
1007 act_settings.func[old_best_match_i].color );
1008
1009 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
1010 GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
1011 str.c_str() );
1012 gtk_window_set_title( GTK_WINDOW(dialog), _("Find maximum/minimum") );
1013 gtk_dialog_run( GTK_DIALOG(dialog) );
1014 gtk_widget_destroy(dialog);
1015 }
1016 catch(error_obj error)
1017 {
1018 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin), GTK_DIALOG_MODAL,
1019 GTK_MESSAGE_ERROR,
1020 GTK_BUTTONS_CLOSE, error.msg );
1021 gtk_window_set_title( GTK_WINDOW(dialog), _("Find maximum/minimum") );
1022 gtk_dialog_run( GTK_DIALOG(dialog) );
1023 gtk_widget_destroy(dialog);
1024 }
1025 catch(...)
1026 {
1027 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1028 catch(error_obj error)
1029 {
1030 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin),
1031 GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
1032 GTK_BUTTONS_CLOSE, error.msg );
1033 gtk_window_set_title( GTK_WINDOW(dialog), _("Find maximum/minimum") );
1034 gtk_dialog_run( GTK_DIALOG(dialog) );
1035 gtk_widget_destroy(dialog);
1036 }
1037 }
1038 }
1039 break; // LeftClickAction_FindMaximumMinimum
1040
1041 case LeftClickAction_FindIntersection:
1042 if( old_best_match_i == -1 )
1043 return;
1044 picwin_intersection_show( x );
1045 break;
1046
1047 case LeftClickAction_CalcDerivate:
1048 if( old_best_match_i == -1 )
1049 return;
1050 picwin_calc_derivate( x );
1051 break;
1052
1053 case LeftClickAction_CalcIntegral:
1054 if( old_best_match_i == -1 )
1055 return;
1056 picwin_calc_integral( x );
1057 break;
1058
1059 case LeftClickAction_CalcLength:
1060 if( old_best_match_i == -1 )
1061 return;
1062 picwin_calc_length( x );
1063 break;
1064 }
1065 }
1066 break;
1067
1068 case 2: // middle button
1069 if(GTK_WIDGET_IS_SENSITIVE(picwin_combo_trace) == TRUE)
1070 {
1071 switch( gtk_combo_box_get_active(GTK_COMBO_BOX(picwin_combo_trace)) )
1072 {
1073 case 0: // off
1074 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), 1 );
1075 break;
1076
1077 case 1: // auto
1078 if(old_best_match_i != -1)
1079 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace),
1080 conv_function_index_to_combobox_index(old_best_match_i) );
1081 break;
1082
1083
1084 default: // locked
1085 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), 1 );
1086 }
1087 }
1088 break;
1089
1090 case 3: // right button
1091 if(GTK_WIDGET_IS_SENSITIVE(picwin_combo_trace) == TRUE)
1092 {
1093 xcenter = picbild2.get_x_value( x );
1094 ycenter = picbild2.get_y_value( y );
1095 width = picbild2.get_right() - picbild2.get_left();
1096 height = picbild2.get_top() - picbild2.get_bottom();
1097
1098 try
1099 {
1100 str = "";
1101 floatx_to_string( xcenter-width, str, stdformat);
1102 act_settings.xmin = str.c_str();
1103
1104 str = "";
1105 floatx_to_string( xcenter+width, str, stdformat);
1106 act_settings.xmax = str.c_str();
1107
1108 str = "";
1109 floatx_to_string( ycenter-height, str, stdformat);
1110 act_settings.ymin = str.c_str();
1111
1112 str = "";
1113 floatx_to_string( ycenter+height, str, stdformat);
1114 act_settings.ymax = str.c_str();
1115
1116 {
1117 gint tmpint;
1118 tmpint = gtk_combo_box_get_active(GTK_COMBO_BOX(picwin_combo_trace));
1119 picturewin_show( (graph_settings *)(0) );
1120 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), tmpint );
1121 }
1122 }
1123 catch(...) { }
1124 }
1125 break;
1126 }
1127 }
1128
1129
1130
1131
picwin_hline(guchar * buffer,int32 width,int32 height,int32 row,picture_h::colorrgb & color)1132 void picwin_hline( guchar *buffer, int32 width, int32 height, int32 row, picture_h::colorrgb &color)
1133 {
1134 if( row < 0 || row >= height || width <= 0 || height <= 0 || buffer == 0 )
1135 return;
1136
1137 buffer += width*3*row;
1138 for(;width != 0;width--)
1139 {
1140 *buffer++ = guchar(color.red);
1141 *buffer++ = guchar(color.green);
1142 *buffer++ = guchar(color.blue);
1143 }
1144 }
picwin_vline(guchar * buffer,int32 width,int32 height,int32 col,picture_h::colorrgb & color)1145 void picwin_vline( guchar *buffer, int32 width, int32 height, int32 col, picture_h::colorrgb &color)
1146 {
1147 if( col < 0 || col >= width || width <= 0 || height <= 0 || buffer == 0 )
1148 return;
1149
1150 int rowstride = 3*width - 2;
1151 buffer += 3*col;
1152 for(;height != 0;height--, buffer += rowstride)
1153 {
1154 *buffer++ = guchar(color.red);
1155 *buffer++ = guchar(color.green);
1156 *buffer = guchar(color.blue);
1157 }
1158 }
1159
picwin_get_row(const guchar * buffer,int32 width,int32 height,int32 row,guchar * dest)1160 void picwin_get_row( const guchar *buffer, int32 width, int32 height, int32 row, guchar *dest)
1161 {
1162 if( row < 0 || row >= height || width <= 0 || height <= 0 || buffer == 0 )
1163 return;
1164
1165 register int32 tmp = width*3;
1166 buffer += tmp*row;
1167
1168 memcpy(dest, buffer, tmp);
1169 }
1170
picwin_set_row(guchar * buffer,int32 width,int32 height,int32 row,const guchar * src)1171 void picwin_set_row( guchar *buffer, int32 width, int32 height, int32 row, const guchar *src)
1172 {
1173 if( row < 0 || row >= height || width <= 0 || height <= 0 || buffer == 0 )
1174 return;
1175
1176 register int32 tmp = width*3;
1177 buffer += tmp*row;
1178
1179 memcpy(buffer, src, tmp);
1180 }
1181
picwin_get_col(const guchar * buffer,int32 width,int32 height,int32 col,guchar * dest)1182 void picwin_get_col( const guchar *buffer, int32 width, int32 height, int32 col, guchar *dest)
1183 {
1184 if( col < 0 || col >= width || width <= 0 || height <= 0 || buffer == 0 )
1185 return;
1186
1187 int rowstride = 3*width - 2;
1188 buffer += 3*col;
1189 for(;height != 0;height--, buffer += rowstride)
1190 {
1191 *dest++ = *buffer++;
1192 *dest++ = *buffer++;
1193 *dest++ = *buffer;
1194 }
1195 }
1196
picwin_set_col(guchar * buffer,int32 width,int32 height,int32 col,const guchar * src)1197 void picwin_set_col( guchar *buffer, int32 width, int32 height, int32 col, const guchar *src)
1198 {
1199 if( col < 0 || col >= width || width <= 0 || height <= 0 || buffer == 0 )
1200 return;
1201
1202 int rowstride = 3*width - 2;
1203 buffer += 3*col;
1204 for(;height != 0;height--, buffer += rowstride)
1205 {
1206 *buffer++ = *src++;
1207 *buffer++ = *src++;
1208 *buffer = *src++;
1209 }
1210 }
1211
picwin_remove_old_trace_mark(void)1212 void picwin_remove_old_trace_mark( void )
1213 {
1214 if( old_best_match_i != -1 )
1215 {
1216 if( picwin_rowbuffer_len < picbild2.pic.get_width() )
1217 {
1218 delete [] picwin_rowbuffer;
1219 picwin_rowbuffer = 0;
1220 picwin_rowbuffer_len = 0;
1221
1222 try{
1223 picwin_rowbuffer = new guchar [ picbild2.pic.get_width()*3 ];
1224 picwin_rowbuffer_len = picbild2.pic.get_width();
1225 }catch( ... ) { return; }
1226 }
1227 if( picwin_colbuffer_len < picbild2.pic.get_height() )
1228 {
1229 delete [] picwin_colbuffer;
1230 picwin_colbuffer = 0;
1231 picwin_colbuffer_len = 0;
1232
1233 try{
1234 picwin_colbuffer = new guchar [ picbild2.pic.get_height()*3 ];
1235 picwin_colbuffer_len = picbild2.pic.get_height();
1236 }catch( ... ) { return; }
1237 }
1238
1239 picwin_set_col( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1240 picbild2.pic.get_height(), old_tx, picwin_colbuffer );
1241 picwin_set_row( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1242 picbild2.pic.get_height(), old_ty, picwin_rowbuffer );
1243
1244 picbild.force_expose_line( old_ty );
1245 picbild.force_expose_col( old_tx );
1246
1247 old_best_match_i = -1;
1248 }
1249 }
1250
picwin_mousemove(const picture2gtk * src,int32 x,int32 y)1251 void picwin_mousemove( const picture2gtk *src, int32 x, int32 y )
1252 {
1253 const uint32 limit_tiden = 3000000;
1254 uint32 tiden;
1255 {
1256 timeval tmp;
1257 gettimeofday( &tmp ,0 );
1258
1259 tiden = 1000000*(tmp.tv_sec - action_combo_changed.tv_sec) + tmp.tv_usec - action_combo_changed.tv_usec;
1260 }
1261
1262 picwin_remove_old_trace_mark();
1263
1264 if( GTK_WIDGET_IS_SENSITIVE(picwin_combo_trace) == TRUE &&
1265 gtk_combo_box_get_active( GTK_COMBO_BOX(picwin_combo_trace) ) == 0 ) // no trace
1266 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_action), 0 ); // zoom
1267
1268 if( x < 0 || x >= picbild2.pic.get_width() || y < 0 || y >= picbild2.pic.get_height() )
1269 {
1270 if( gtk_combo_box_get_active( GTK_COMBO_BOX(picwin_combo_action) ) < 1 )
1271 gtk_label_set_text( GTK_LABEL(picwin_status), PRG_NAME );
1272 }
1273 else
1274 {
1275 Complex tmp, best_match;
1276 floatx y_value;
1277 int i, best_match_i;
1278 static utf8_string str;
1279 Format tmp_format;
1280
1281 char char_str[300];
1282
1283 tmp_format = format;
1284 tmp_format.show_trailingzeros = true;
1285
1286 if( gtk_combo_box_get_active(GTK_COMBO_BOX(picwin_combo_trace)) != 0 )
1287 {
1288 if( act_settings.active_page != 0 && act_settings.show_active_page_only )
1289 goto picwin_no_trace;
1290
1291 if( gtk_combo_box_get_active(GTK_COMBO_BOX(picwin_combo_trace)) == 1 )
1292 {
1293 y_value = picbild2.get_y_value( y );
1294 best_match_i = -1;
1295 for(i=0;i<10;i++) // this loop finds first (if any) non error trace
1296 {
1297 if(act_settings.func[i].show_this)
1298 {
1299 best_match_i = i;
1300 best_match = trace_matrix.get_complex( x+1, i+2 );
1301 if( floatx(best_match.imaginary) == 0.0 )
1302 break;
1303 }
1304 }
1305 if(best_match_i == -1)
1306 goto picwin_no_trace;
1307 for( i++; i<10; i++ )
1308 {
1309 if(act_settings.func[i].show_this)
1310 {
1311 tmp = trace_matrix.get_complex( x+1, i+2 );
1312 if(floatx(tmp.imaginary) != 0.0) // skip this
1313 continue;
1314 if( fabsx(floatx(tmp.real) - y_value) < fabsx(floatx(best_match.real) - y_value) )
1315 {
1316 best_match_i = i;
1317 best_match = tmp;
1318 }
1319 }
1320 }
1321 }
1322 else // this is a locked trace
1323 {
1324 best_match_i = conv_combobox_index_to_function_index(
1325 gtk_combo_box_get_active(GTK_COMBO_BOX(picwin_combo_trace)) );
1326 best_match = trace_matrix.get_complex( x+1, best_match_i+2 );
1327 }
1328
1329 if(floatx(best_match.imaginary) != 0.0)
1330 {
1331 if( gtk_combo_box_get_active( GTK_COMBO_BOX(picwin_combo_action) ) < 1 || tiden > limit_tiden )
1332 {
1333 str = "X=";
1334 floatx_to_string( get_x_value( x, best_match_i ), str, tmp_format );
1335 str.append( " Y=" );
1336 str.append( _("Error") );
1337 gtk_label_set_text( GTK_LABEL(picwin_status), str.c_str() );
1338 }
1339 }
1340 else
1341 {
1342 if( gtk_combo_box_get_active( GTK_COMBO_BOX(picwin_combo_action) ) < 1 || tiden > limit_tiden )
1343 {
1344 SnapInfo snappen;
1345
1346 snprintf( char_str, 300, "y%ld( ", best_match_i );
1347 str = char_str;
1348
1349 snappen.calculated = false;
1350 floatx_to_string( get_x_value( x, best_match_i ), str, tmp_format );
1351 str.append( " ) = " );
1352 floatx_to_string( get_y_value( x, best_match_i, &snappen ), str, tmp_format );
1353 if( snappen.calculated )
1354 {
1355 str.append( " (" );
1356 switch( snappen.snap_type )
1357 {
1358 case SnapInfo::Snap_Root:
1359 str.append( _("Root") );
1360 break;
1361 case SnapInfo::Snap_Maximum:
1362 str.append( _("Maximum") );
1363 break;
1364 case SnapInfo::Snap_Minimum:
1365 str.append( _("Minimum") );
1366 break;
1367 case SnapInfo::Snap_Intersection:
1368 snprintf( char_str, 300, _("Intersection with y%ld"),
1369 snappen.intersect_with );
1370 str.append( char_str );
1371 break;
1372 }
1373 str.append( ")" );
1374 }
1375 gtk_label_set_text( GTK_LABEL(picwin_status), str.c_str() );
1376 }
1377
1378 try
1379 {
1380 int32 tx,ty;
1381
1382 if( picwin_rowbuffer_len < picbild2.pic.get_width() )
1383 {
1384 delete [] picwin_rowbuffer;
1385 picwin_rowbuffer = 0;
1386 picwin_rowbuffer_len = 0;
1387
1388 picwin_rowbuffer = new guchar [ picbild2.pic.get_width()*3 ];
1389 picwin_rowbuffer_len = picbild2.pic.get_width();
1390 }
1391 if( picwin_colbuffer_len < picbild2.pic.get_height() )
1392 {
1393 delete [] picwin_colbuffer;
1394 picwin_colbuffer = 0;
1395 picwin_colbuffer_len = 0;
1396
1397 picwin_colbuffer = new guchar [ picbild2.pic.get_height()*3 ];
1398 picwin_colbuffer_len = picbild2.pic.get_height();
1399 }
1400
1401 tx = picbild2.get_x_pixel( get_x_value( x, best_match_i ) );
1402
1403 if( tx != old_tx || best_match_i != old_best_match_i )
1404 {
1405 ty = picbild2.get_y_pixel( get_y_value( x, best_match_i ) );
1406
1407 if( old_best_match_i != -1 )
1408 {
1409 picwin_set_col( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1410 picbild2.pic.get_height(), old_tx, picwin_colbuffer );
1411 picwin_set_row( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1412 picbild2.pic.get_height(), old_ty, picwin_rowbuffer );
1413
1414 picbild.force_expose_line( old_ty );
1415 picbild.force_expose_col( old_tx );
1416 }
1417 picwin_get_row( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1418 picbild2.pic.get_height(), ty, picwin_rowbuffer );
1419 picwin_get_col( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1420 picbild2.pic.get_height(), tx, picwin_colbuffer );
1421
1422 picwin_hline( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1423 picbild2.pic.get_height(), ty,
1424 act_settings.func[best_match_i].color );
1425 picwin_vline( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1426 picbild2.pic.get_height(), tx,
1427 act_settings.func[best_match_i].color );
1428
1429 picbild.force_expose_line( ty );
1430 picbild.force_expose_col( tx );
1431
1432 old_tx = tx;
1433 old_ty = ty;
1434 old_best_match_i = best_match_i;
1435 }
1436 }
1437 catch(error_obj error)
1438 {
1439 (*TEXTVIEW_FUNCTION)("\n\nError while updating trace: ");
1440 (*TEXTVIEW_FUNCTION)(error.msg);
1441 (*TEXTVIEW_FUNCTION)("\n\n");
1442 }
1443 catch(...)
1444 {
1445 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1446 catch(error_obj error)
1447 {
1448 (*TEXTVIEW_FUNCTION)("\n\nError while updating trace: ");
1449 (*TEXTVIEW_FUNCTION)(error.msg);
1450 (*TEXTVIEW_FUNCTION)("\n\n");
1451 }
1452 }
1453 }
1454 }
1455 else
1456 {
1457 picwin_no_trace:
1458 bool trailingzeros = stdformat.show_trailingzeros;
1459 stdformat.show_trailingzeros = true;
1460 str = "X=";
1461 floatx_to_string( picbild2.get_x_value( x ), str, stdformat);
1462 str.append( " Y=" );
1463 floatx_to_string( picbild2.get_y_value( y ), str, stdformat);
1464 gtk_label_set_text( GTK_LABEL(picwin_status), str.c_str() );
1465 stdformat.show_trailingzeros = trailingzeros;
1466
1467 if( old_best_match_i != -1 )
1468 {
1469 if( picwin_rowbuffer_len < picbild2.pic.get_width() )
1470 {
1471 delete [] picwin_rowbuffer;
1472 picwin_rowbuffer = 0;
1473 picwin_rowbuffer_len = 0;
1474
1475 picwin_rowbuffer = new guchar [ picbild2.pic.get_width()*3 ];
1476 picwin_rowbuffer_len = picbild2.pic.get_width();
1477 }
1478 if( picwin_colbuffer_len < picbild2.pic.get_height() )
1479 {
1480 delete [] picwin_colbuffer;
1481 picwin_colbuffer = 0;
1482 picwin_colbuffer_len = 0;
1483
1484 picwin_colbuffer = new guchar [ picbild2.pic.get_height()*3 ];
1485 picwin_colbuffer_len = picbild2.pic.get_height();
1486 }
1487
1488 picwin_set_col( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1489 picbild2.pic.get_height(), old_tx, picwin_colbuffer );
1490 picwin_set_row( picbild.get_intern_buffer(), picbild2.pic.get_width(),
1491 picbild2.pic.get_height(), old_ty, picwin_rowbuffer );
1492
1493 picbild.force_expose_line( old_ty );
1494 picbild.force_expose_col( old_tx );
1495
1496 old_best_match_i = -1;
1497 }
1498 }
1499 }
1500 }
1501
picwin_mousenop(const picture2gtk * src,int32 x,int32 y,int32 button)1502 void picwin_mousenop(const picture2gtk *src,int32 x,int32 y,int32 button) { }
1503
picturewin_save_as(void)1504 void picturewin_save_as(void)
1505 {
1506 GtkWidget *file_chooser, *tmp, *tmp2, *hbox, *picwin_save_format;
1507 GtkFileFilter *filter;
1508
1509 file_chooser = gtk_file_chooser_dialog_new( dialog_title_save_as,
1510 GTK_WINDOW(picturewin),
1511 GTK_FILE_CHOOSER_ACTION_SAVE,
1512 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1513 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
1514 NULL );
1515
1516
1517 filter = gtk_file_filter_new();
1518 gtk_file_filter_add_pattern(filter, "*.pcx");
1519 gtk_file_filter_add_pattern(filter, "*.ppm");
1520 gtk_file_filter_set_name(filter, filter_picture_files);
1521 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
1522
1523 filter = gtk_file_filter_new();
1524 gtk_file_filter_add_pattern(filter, "*.pcx");
1525 gtk_file_filter_set_name(filter, filter_pcx_files);
1526 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
1527
1528 filter = gtk_file_filter_new();
1529 gtk_file_filter_add_pattern(filter, "*.ppm");
1530 gtk_file_filter_set_name(filter, filter_ppm_files);
1531 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
1532
1533 filter = gtk_file_filter_new();
1534 gtk_file_filter_add_pattern(filter, "*");
1535 gtk_file_filter_set_name(filter, filter_all_files);
1536 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), filter);
1537
1538 hbox = gtk_hbox_new(FALSE,0);
1539 gtk_widget_show( hbox );
1540
1541 picwin_save_format = gtk_option_menu_new();
1542 gtk_widget_show( picwin_save_format );
1543
1544 tmp = gtk_menu_new();
1545 gtk_widget_show( tmp );
1546
1547 tmp2 = gtk_menu_item_new_with_label( _("PCX") );
1548 gtk_widget_show( tmp2 );
1549 gtk_menu_shell_append(GTK_MENU_SHELL(tmp),tmp2);
1550
1551 tmp2 = gtk_menu_item_new_with_label( _("PPM (binary)") );
1552 gtk_widget_show( tmp2 );
1553 gtk_menu_shell_append(GTK_MENU_SHELL(tmp),tmp2);
1554
1555 tmp2 = gtk_menu_item_new_with_label( _("PPM (text/ascii)") );
1556 gtk_widget_show( tmp2 );
1557 gtk_menu_shell_append(GTK_MENU_SHELL(tmp),tmp2);
1558
1559 gtk_option_menu_set_menu(GTK_OPTION_MENU(picwin_save_format), tmp);
1560
1561 gtk_box_pack_end(GTK_BOX(hbox), picwin_save_format, FALSE, FALSE, 0);
1562
1563
1564 tmp = gtk_label_new( _("File type:") );
1565 gtk_widget_show( tmp );
1566 gtk_box_pack_end(GTK_BOX(hbox), tmp, FALSE, FALSE, 0);
1567
1568 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_chooser), hbox);
1569
1570 if(gtk_dialog_run(GTK_DIALOG(file_chooser)) == GTK_RESPONSE_ACCEPT)
1571 {
1572 gint type;
1573 char *filename;
1574
1575 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
1576
1577 type = gtk_option_menu_get_history(GTK_OPTION_MENU(picwin_save_format));
1578
1579 try
1580 {
1581 switch(type)
1582 {
1583 case 0: // PCX
1584 picbild2.pic.save_pcx(filename);
1585 break;
1586 case 1: // PPM (binary)
1587 picbild2.pic.save_ppm(filename);
1588 break;
1589 case 2: // PPM (ascii)
1590 picbild2.pic.save_ppm(filename,1);
1591 break;
1592 default:
1593 THROW_ERROR( ErrorType_General, _("Unknown format") );
1594 }
1595 }
1596 catch(error_obj error)
1597 {
1598 GtkWidget *dialog;
1599
1600 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin),
1601 GTK_DIALOG_DESTROY_WITH_PARENT,
1602 GTK_MESSAGE_ERROR,
1603 GTK_BUTTONS_CLOSE,
1604 error.msg );
1605 gtk_dialog_run( GTK_DIALOG(dialog) );
1606 gtk_widget_destroy(dialog);
1607 }
1608 g_free(filename);
1609 }
1610 gtk_widget_destroy(file_chooser);
1611 }
1612
find_all_snap_points(void)1613 void find_all_snap_points( void )
1614 {
1615 SnapInfo tmp_snap;
1616 Complex tmp0[10], tmp1[10], tmp2[10];
1617 floatx f0, f1, f2;
1618 bool active[10];
1619
1620 tmp_snap.calculated = false;
1621
1622 for( int32 x=2; x<act_settings.width; x++ )
1623 {
1624 /*
1625 struct SnapInfo
1626 {
1627 enum SnapType { Snap_Root, Snap_Minimum, Snap_Maximum, Snap_Intersection };
1628 SnapType snap_type;
1629 int32 x, intersect_with;
1630 floatx fx, fy;
1631 bool calculated;
1632 };
1633 */
1634 for( int i=0; i<10; i++ )
1635 {
1636 if( act_settings.func[i].show_this == false )
1637 continue;
1638 tmp0[i] = trace_matrix.get_complex( x-1, i+2 );
1639 tmp1[i] = trace_matrix.get_complex( x, i+2 );
1640 tmp2[i] = trace_matrix.get_complex( x+1, i+2 );
1641 }
1642
1643 for( int i=0; i<10; i++ )
1644 {
1645 if( act_settings.func[i].show_this == false )
1646 continue;
1647 for( int a=i; a<10; a++ )
1648 {
1649 if( act_settings.func[a].show_this == false )
1650 {
1651 active[a] = false;
1652 continue;
1653 }
1654 active[a] = bool( floatx(tmp0[a].imaginary) == 0.0 && floatx(tmp1[a].imaginary) == 0.0 &&
1655 floatx(tmp2[a].imaginary) == 0.0 );
1656 }
1657 if( active[i] )
1658 {
1659 f0 = floatx(tmp0[i].real);
1660 f1 = floatx(tmp1[i].real);
1661 f2 = floatx(tmp2[i].real);
1662 if( f1 * f2 < 0.0 ) // they have different signs, here might a root be found
1663 {
1664 tmp_snap.snap_type = SnapInfo::Snap_Root;
1665 tmp_snap.x = x;
1666 tmp_snap.fx = floatx( trace_matrix.get_complex( x, 1 ).real );
1667 snap_info[i].append( tmp_snap );
1668 }
1669 if( f0 <= f1 && f2 < f1 )
1670 {
1671 tmp_snap.snap_type = SnapInfo::Snap_Maximum;
1672 tmp_snap.x = x;
1673 tmp_snap.fx = floatx( trace_matrix.get_complex( x, 1 ).real );
1674 snap_info[i].append( tmp_snap );
1675 }
1676 if( f0 >= f1 && f2 > f1 )
1677 {
1678 tmp_snap.snap_type = SnapInfo::Snap_Minimum;
1679 tmp_snap.x = x;
1680 tmp_snap.fx = floatx( trace_matrix.get_complex( x, 1 ).real );
1681 snap_info[i].append( tmp_snap );
1682 }
1683 for( int a=i; a<10; a++ )
1684 {
1685 if( active[a] == false )
1686 continue;
1687 if( (f1 < floatx(tmp1[a].real)) ^ (f2 < floatx(tmp2[a].real)) )
1688 {
1689 tmp_snap.snap_type = SnapInfo::Snap_Intersection;
1690 tmp_snap.x = x;
1691 tmp_snap.fx = floatx( trace_matrix.get_complex( x, 1 ).real );
1692 tmp_snap.intersect_with = a;
1693 snap_info[i].append( tmp_snap );
1694 tmp_snap.intersect_with = i;
1695 snap_info[a].append( tmp_snap );
1696 }
1697 }
1698 }
1699 }
1700 }
1701 }
1702
1703
picturewin_show(const graph_settings * settings)1704 void picturewin_show( const graph_settings *settings )
1705 {
1706 enum IM_HERE { IM_HERE_picture, IM_HERE_funcion, IM_HERE_polar, IM_HERE_par };
1707 math::CodeLine function;
1708 utf8_string str;
1709 picture_h::colorrgb color;
1710 const Matrix *matr;
1711 IM_HERE Im_here = IM_HERE_picture;
1712 int i;
1713 char char_str[1000];
1714
1715 old_best_match_i = -1;
1716
1717 try
1718 {
1719 for( i=0; i<10; i++ )
1720 snap_info[i].clear();
1721
1722 if(settings != 0)
1723 act_settings = *settings;
1724
1725 snprintf( char_str, 1000, "plot_picture = picture( %ld, %ld, ", act_settings.width, act_settings.height );
1726 str = char_str;
1727 str.append( act_settings.xmin ).append( ", " );
1728 str.append( act_settings.xmax ).append( ", " );
1729 str.append( act_settings.ymin ).append( ", " );
1730 str.append( act_settings.ymax );
1731 snprintf( char_str, 1000, ", [[ %f, %f, %f ]] )\n", act_settings.bgcolor.red/255.0f,
1732 act_settings.bgcolor.green/255.0f, act_settings.bgcolor.blue/255.0f );
1733 str.append( char_str );
1734 if(act_settings.show_code)
1735 (*TEXTVIEW_FUNCTION)( str.c_str() );
1736 function.set_code_line( str.c_str() );
1737 function.calc( 0 ); // resizing the picture
1738
1739 if( act_settings.grid_on )
1740 {
1741 snprintf( char_str, 1000, "plot_picture.grid( \"%s\", %s, %s, %s, [[ %f, %f, %f ]] )\n",
1742 act_settings.grid_type.c_str(), act_settings.grid_scale1.c_str(),
1743 act_settings.grid_scale2.c_str(), (act_settings.use_antialiasing) ? "true" : "false",
1744 act_settings.grid_color.red/255.0f, act_settings.grid_color.green/255.0f,
1745 act_settings.grid_color.blue/255.0f );
1746 if(act_settings.show_code)
1747 (*TEXTVIEW_FUNCTION)( char_str );
1748 function.set_code_line( char_str );
1749 function.calc( 0 ); // adding grid
1750 }
1751
1752 if( act_settings.axes_on )
1753 {
1754 snprintf( char_str, 1000, "plot_picture.axes( %s, %s, %ld, [[ %f, %f, %f ]] )\n",
1755 act_settings.scalex.c_str(), act_settings.scaley.c_str(),
1756 act_settings.scale_length, act_settings.axes_color.red/255.0f,
1757 act_settings.axes_color.green/255.0f, act_settings.axes_color.blue/255.0f );
1758 if(act_settings.show_code)
1759 (*TEXTVIEW_FUNCTION)( char_str );
1760 function.set_code_line( char_str );
1761 function.calc( 0 ); // adding axes
1762 }
1763
1764 if(act_settings.active_page == 0 || act_settings.show_active_page_only == false) // function-page
1765 {
1766 Im_here = IM_HERE_funcion;
1767 for( i=0; i<10; i++ ) // setting up all functions
1768 {
1769 snprintf( char_str, 1000, "y%ld = \"", i );
1770 str = char_str;
1771 str.append( act_settings.func[i].entry ).append( "\"\n" );
1772 if( act_settings.show_code )
1773 (*TEXTVIEW_FUNCTION)( str.c_str() );
1774 function.set_code_line( str.c_str() );
1775 function.calc( 0 );
1776 }
1777 str = "plot_x_matrix = table( \"x\", x, dec( ";
1778 str.append( act_settings.xmin ).append( " ), dec( " );
1779 str.append( act_settings.xmax );
1780 snprintf( char_str, 1000, " ), %ld )\n", act_settings.width );
1781 str.append( char_str );
1782 if( act_settings.show_code )
1783 (*TEXTVIEW_FUNCTION)( str.c_str() );
1784 function.set_code_line( str.c_str() );
1785 function.calc( 0 ); // calculating the x list
1786
1787 trace_matrix.set_size( act_settings.width, 11 );
1788 trace_matrix.fill( Complex( 0.0, 1.0 ) );
1789
1790 matr = math::global_varlist.get_pointer( math::global_varlist.get_id("plot_x_matrix") )->get_matrix();
1791 for( int i2=0; i2<act_settings.width; i2++ )
1792 trace_matrix.set_complex(i2+1,1, matr->get_complex(i2+1,1) );
1793
1794 for( i=0; i<10; i++ )
1795 {
1796 color = act_settings.func[i].color;
1797 if( act_settings.func[i].show_this )
1798 {
1799 snprintf( char_str, 1000, "plot_y_matrix = table( y%ld, x, dec( ", i );
1800 str = char_str;
1801 str.append( act_settings.xmin ).append( " ), dec( " );
1802 str.append( act_settings.xmax );
1803 snprintf( char_str, 1000, " ), %ld, i )\n", act_settings.width );
1804 str.append( char_str );
1805 if( act_settings.show_code )
1806 (*TEXTVIEW_FUNCTION)( str.c_str() );
1807 function.set_code_line( str.c_str() );
1808 function.calc( 0 ); // calculating the y list
1809
1810 matr = math::global_varlist.get_pointer(
1811 math::global_varlist.get_id("plot_y_matrix") )->get_matrix();
1812 for( int i2=0; i2<act_settings.width; i2++ )
1813 trace_matrix.set_complex(i2+1,i+2, matr->get_complex(i2+1,1) );
1814
1815 str = "plot_picture.plot( plot_x_matrix, plot_y_matrix, \"";
1816 str.append( act_settings.plot_mode );
1817 snprintf( char_str, 1000, "\", \"Dot\", 0, false, %s, [[ %f, %f, %f ]] )\n",
1818 (act_settings.use_antialiasing) ? "true" : "false",
1819 color.red/255.0f, color.green/255.0f, color.blue/255.0f );
1820 str.append( char_str );
1821 if( act_settings.show_code )
1822 (*TEXTVIEW_FUNCTION)( str.c_str() );
1823 function.set_code_line( str.c_str() );
1824 function.calc( 0 ); // drawing function
1825 }
1826 }
1827 find_all_snap_points();
1828 }
1829 if( act_settings.active_page == 1 || act_settings.show_active_page_only == false ) // polar-page
1830 {
1831 Im_here = IM_HERE_polar;
1832 bool connected = true;
1833 if( act_settings.plot_mode == "Dots" )
1834 connected = false;
1835 for( i=0; i<10; i++ ) // setting up all functions
1836 {
1837 snprintf( char_str, 1000, "r%ld = \"", i );
1838 str = char_str;
1839 str.append( act_settings.polar[i].entry ).append( "\"\n" );
1840 if( act_settings.show_code )
1841 (*TEXTVIEW_FUNCTION)( str.c_str() );
1842 function.set_code_line( str.c_str() );
1843 function.calc( 0 );
1844 }
1845 for( i=0; i<10; i++ )
1846 {
1847 color = act_settings.polar[i].color;
1848 if( act_settings.polar[i].show_this )
1849 {
1850 snprintf( char_str, 1000, "plot_x_matrix = table( \"r%ld(x)cos x\", x, ", i );
1851 str = char_str;
1852 str.append( act_settings.polar_start ).append( ", " );
1853 str.append( act_settings.polar_stop ).append( ", " );
1854 str.append( act_settings.polar_steps ).append( ", i )\n" );
1855 if( act_settings.show_code )
1856 (*TEXTVIEW_FUNCTION)( str.c_str() );
1857 function.set_code_line( str.c_str() );
1858 function.calc( 0 ); // calculating the x list
1859
1860 snprintf( char_str, 1000, "plot_y_matrix = table( \"r%ld(x)sin x\", x, ", i );
1861 str = char_str;
1862 str.append( act_settings.polar_start ).append( ", " );
1863 str.append( act_settings.polar_stop ).append( ", " );
1864 str.append( act_settings.polar_steps ).append( ", i )\n" );
1865 if( act_settings.show_code )
1866 (*TEXTVIEW_FUNCTION)( str.c_str() );
1867 function.set_code_line( str.c_str() );
1868 function.calc( 0 ); // calculating the x list
1869
1870 snprintf( char_str, 1000, "plot_picture.plot( plot_x_matrix, plot_y_matrix, \"%s\", "
1871 "\"Dot\", 0, false, %s, [[ %f, %f, %f ]] )\n",
1872 connected ? "Connected" : "Dots",
1873 act_settings.use_antialiasing ? "true" : "false",
1874 color.red/255.0f, color.green/255.0f, color.blue/255.0f );
1875 if( act_settings.show_code )
1876 (*TEXTVIEW_FUNCTION)( char_str );
1877 function.set_code_line( char_str );
1878 function.calc( 0 ); // drawing function
1879 }
1880 }
1881 }
1882 if( act_settings.active_page == 2 || act_settings.show_active_page_only == false ) // parameter-page
1883 {
1884 Im_here = IM_HERE_par;
1885 bool connected = (act_settings.plot_mode == "Dots") ? false : true;
1886
1887 for( i=0; i<5; i++ ) // setting up all functions
1888 {
1889 snprintf( char_str, 1000, "xf%ld = \"", i );
1890 str = char_str;
1891 str.append( act_settings.par[i].entry ).append( "\"\n" );
1892 if( act_settings.show_code )
1893 (*TEXTVIEW_FUNCTION)( str.c_str() );
1894 function.set_code_line( str.c_str() );
1895 function.calc( 0 );
1896
1897 snprintf( char_str, 1000, "yf%ld = \"", i );
1898 str = char_str;
1899 str.append( act_settings.par[i].entry2 ).append( "\"\n" );
1900 if( act_settings.show_code )
1901 (*TEXTVIEW_FUNCTION)( str.c_str() );
1902 function.set_code_line( str.c_str() );
1903 function.calc( 0 );
1904 }
1905 for( i=0; i<5; i++ )
1906 {
1907 color = act_settings.par[i].color;
1908 if( act_settings.par[i].show_this )
1909 {
1910 snprintf( char_str, 1000, "plot_x_matrix = table( xf%ld, x, ", i );
1911 str = char_str;
1912 str.append( act_settings.par_start ).append( ", " );
1913 str.append( act_settings.par_stop ).append( ", " );
1914 str.append( act_settings.par_steps ).append( ", i )\n" );
1915 if( act_settings.show_code )
1916 (*TEXTVIEW_FUNCTION)( str.c_str() );
1917 function.set_code_line( str.c_str() );
1918 function.calc( 0 ); // calculating the x list
1919
1920 snprintf( char_str, 1000, "plot_y_matrix = table( yf%ld, x, ", i );
1921 str = char_str;
1922 str.append( act_settings.par_start ).append( ", " );
1923 str.append( act_settings.par_stop ).append( ", " );
1924 str.append( act_settings.par_steps ).append( ", i )\n" );
1925 if( act_settings.show_code )
1926 (*TEXTVIEW_FUNCTION)( str.c_str() );
1927 function.set_code_line( str.c_str() );
1928 function.calc( 0 ); // calculating the y list
1929
1930 snprintf( char_str, 1000, "plot_picture.plot( plot_x_matrix, plot_y_matrix, \"%s\""
1931 ", \"Dot\", 0, false, %s, [[ %f, %f, %f ]] )\n",
1932 connected ? "Connected" : "Dots",
1933 act_settings.use_antialiasing ? "true" : "false",
1934 color.red/255.0f, color.green/255.0f, color.blue/255.0f );
1935 if( act_settings.show_code )
1936 (*TEXTVIEW_FUNCTION)( char_str );
1937 function.set_code_line( char_str );
1938 function.calc( 0 ); // drawing parameter function
1939 }
1940 }
1941 }
1942 if( act_settings.show_code )
1943 (*TEXTVIEW_FUNCTION)("show plot_picture\n\n");
1944 function.set_code_line("show plot_picture");
1945 function.calc( 0 );
1946
1947 gtk_widget_set_sensitive( picwin_combo_trace, TRUE );
1948 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), 1 ); // auto-trace
1949 gtk_widget_set_sensitive( picwin_combo_action, TRUE );
1950 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_action), 0 ); // zoom
1951 old_best_match_i = -1;
1952
1953 picbild.mousedown_func = picwin_mousedown;
1954 }
1955 catch(error_obj error)
1956 {
1957 GtkWidget *dialog;
1958 utf8_string str;
1959 char tkn[2];
1960 tkn[1] = '\0';
1961
1962 switch( Im_here )
1963 {
1964 case IM_HERE_picture:
1965 str = "When creating plot-picture: ";
1966 break;
1967 case IM_HERE_funcion:
1968 str = "When plotting y";
1969 tkn[0] = char(i)+'0';
1970 str.append( tkn );
1971 str.append( ": " );
1972 break;
1973 case IM_HERE_polar:
1974 str = "When plotting r";
1975 tkn[0] = char(i)+'0';
1976 str.append( tkn );
1977 str.append( ": " );
1978 break;
1979 case IM_HERE_par:
1980 str = "When plotting xf";
1981 tkn[0] = char(i)+'0';
1982 str.append( tkn );
1983 str.append( " yf" );
1984 str.append( tkn );
1985 str.append( ": " );
1986 break;
1987 }
1988
1989 str.append( error.msg );
1990 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin),
1991 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
1992 GTK_BUTTONS_CLOSE, str.c_str() );
1993 gtk_dialog_run(GTK_DIALOG(dialog));
1994 gtk_widget_destroy(dialog);
1995 }
1996 catch(...)
1997 {
1998 try{ THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1999 catch(error_obj error)
2000 {
2001 GtkWidget *dialog;
2002
2003 dialog = gtk_message_dialog_new( GTK_WINDOW(picturewin),
2004 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
2005 GTK_BUTTONS_CLOSE, error.msg );
2006 gtk_dialog_run( GTK_DIALOG(dialog) );
2007 gtk_widget_destroy(dialog);
2008 }
2009 }
2010 }
2011
picwin_combo_action_changed(GtkComboBox * widget,gpointer user_data)2012 void picwin_combo_action_changed( GtkComboBox *widget, gpointer user_data )
2013 {
2014 gettimeofday( &action_combo_changed, 0 );
2015
2016 switch( gtk_combo_box_get_active( widget ) )
2017 {
2018 case LeftClickAction_Zoom:
2019 gtk_label_set_text( GTK_LABEL(picwin_status), PRG_NAME );
2020 break;
2021
2022 case LeftClickAction_FindRoot:
2023 case LeftClickAction_FindMaximumMinimum:
2024 case LeftClickAction_FindIntersection:
2025 gtk_label_set_text( GTK_LABEL(picwin_status), _("Make a guess") );
2026 break;
2027
2028 case LeftClickAction_CalcDerivate:
2029 gtk_label_set_text( GTK_LABEL(picwin_status), _("Select point") );
2030 break;
2031 case LeftClickAction_CalcIntegral:
2032 case LeftClickAction_CalcLength:
2033 gtk_label_set_text( GTK_LABEL(picwin_status), _("Select start point") );
2034 break;
2035 }
2036 picwin_first_click_done = false;
2037 }
2038
picturewin_build_menu(void)2039 GtkWidget* picturewin_build_menu(void)
2040 {
2041 GtkActionGroup *actions;
2042 GtkUIManager *ui_manager;
2043 GError *error = NULL;
2044
2045 static const gchar *menu =
2046 "<ui>"
2047 " <menubar name='MenuBar'>"
2048 " <menu action='FileMenu'>"
2049 " <menuitem action='SaveAs'/>"
2050 " <separator/>"
2051 " <menuitem action='Close'/>"
2052 " <separator/>"
2053 " <menuitem action='Quit'/>"
2054 " </menu>"
2055 " </menubar>"
2056 "</ui>";
2057 GtkActionEntry entries[] = {
2058 { "FileMenu", NULL, menu_file },
2059 { "SaveAs", GTK_STOCK_SAVE_AS, menu_file_save_as, "<shift><ctrl>S", NULL, G_CALLBACK(picturewin_save_as) },
2060 { "Close", GTK_STOCK_CLOSE, menu_file_close, "<ctrl>W", NULL, G_CALLBACK(picturewin_close) },
2061 { "Quit", GTK_STOCK_QUIT, menu_file_quit, "<ctrl>Q", NULL, G_CALLBACK(UMP_gtk_quit) }
2062 };
2063 guint n_entries = G_N_ELEMENTS(entries);
2064
2065 actions = gtk_action_group_new("Actions");
2066 gtk_action_group_add_actions(actions, entries, n_entries, NULL);
2067 ui_manager = gtk_ui_manager_new();
2068 gtk_ui_manager_insert_action_group(ui_manager, actions, 0);
2069 gtk_window_add_accel_group( GTK_WINDOW(picturewin), gtk_ui_manager_get_accel_group(ui_manager) );
2070 if (!gtk_ui_manager_add_ui_from_string(ui_manager, menu, -1, &error))
2071 {
2072 g_message("building menus failed: %s", error->message);
2073 g_error_free(error);
2074 return 0;
2075 }
2076 gtk_ui_manager_ensure_update(ui_manager);
2077
2078
2079 return gtk_ui_manager_get_widget(ui_manager, "/MenuBar");
2080 }
2081
picturewin_show(const char * title,const math::Picture & src)2082 void picturewin_show( const char *title, const math::Picture &src )
2083 {
2084 static int combobox_trace_last_nrofentries;
2085 GtkWidget *drawarea,*scrolled;
2086
2087 old_best_match_i = -1;
2088
2089 if(picturewin == 0)
2090 {
2091 picturewin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2092 gtk_window_set_title(GTK_WINDOW(picturewin), title);
2093 g_signal_connect_swapped( GTK_OBJECT(picturewin), "delete-event",
2094 G_CALLBACK(picturewin_close), NULL);
2095
2096 picturewin_vbox = gtk_vbox_new(FALSE,0);
2097
2098 if((picturewin_menu = picturewin_build_menu()) == 0)
2099 {
2100 gtk_widget_destroy( picturewin );
2101 picturewin = 0;
2102 return;
2103 }
2104 gtk_box_pack_start(GTK_BOX(picturewin_vbox), picturewin_menu, FALSE, FALSE, 0);
2105
2106 {
2107 GtkWidget *tbox;
2108 utf8_string str;
2109
2110 tbox = gtk_hbox_new(FALSE,2);
2111
2112 picwin_label_trace = gtk_label_new( _("Trace action") );
2113 gtk_box_pack_start(GTK_BOX(tbox), picwin_label_trace, FALSE, FALSE, 2 );
2114
2115 picwin_combo_trace = gtk_combo_box_new_text();
2116 gtk_box_pack_start(GTK_BOX(tbox), picwin_combo_trace, FALSE, FALSE, 2 );
2117 gtk_label_set_mnemonic_widget( GTK_LABEL(picwin_label_trace), picwin_combo_trace );
2118
2119 gtk_widget_set_sensitive(picwin_combo_trace, FALSE);
2120
2121
2122 picwin_combo_action = gtk_combo_box_new_text();
2123 gtk_box_pack_end(GTK_BOX(tbox), picwin_combo_action, FALSE, FALSE, 2 );
2124
2125 combobox_trace_last_nrofentries = picwin_reload_combos( 0 );
2126
2127 gtk_widget_set_sensitive(picwin_combo_action, FALSE);
2128 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_action), -1 );
2129 g_signal_connect( GTK_OBJECT(picwin_combo_action), "changed",
2130 G_CALLBACK(picwin_combo_action_changed), gpointer(NULL) );
2131
2132 gtk_box_pack_start(GTK_BOX(picturewin_vbox), tbox, FALSE, FALSE, 2 );
2133 }
2134
2135 drawarea = gtk_drawing_area_new();
2136 picbild.connect_to_drawing_area( drawarea );
2137
2138 scrolled = gtk_scrolled_window_new( NULL, NULL );
2139 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC,
2140 GTK_POLICY_AUTOMATIC );
2141
2142 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled), drawarea );
2143
2144 gtk_box_pack_start( GTK_BOX(picturewin_vbox), scrolled, TRUE, TRUE, 0 );
2145
2146 {
2147 GtkWidget *tbox, *tbar;
2148 tbox = gtk_hbox_new( FALSE, 0 );
2149
2150 picwin_status = gtk_label_new( PRG_NAME );
2151 gtk_misc_set_alignment( GTK_MISC(picwin_status), 0.0f, 0.5f );
2152 gtk_box_pack_start( GTK_BOX(tbox), picwin_status, FALSE, FALSE, 0 );
2153
2154 tbar = gtk_statusbar_new();
2155 gtk_box_pack_start( GTK_BOX(tbox), tbar, TRUE, TRUE, 0 );
2156
2157 gtk_box_pack_start( GTK_BOX(picturewin_vbox), tbox, FALSE, FALSE, 0 );
2158 }
2159
2160 gtk_container_add( GTK_CONTAINER(picturewin), picturewin_vbox );
2161
2162 gtk_window_resize( GTK_WINDOW(picturewin), src.pic.get_width() + 10,
2163 src.pic.get_height() + 90 );
2164
2165 gtk_widget_show_all(picturewin);
2166 }
2167 else
2168 {
2169 gtk_window_set_title( GTK_WINDOW(picturewin), title );
2170 gtk_window_resize( GTK_WINDOW(picturewin), src.pic.get_width() + 10,
2171 src.pic.get_height() + 90 );
2172
2173 gtk_window_present( GTK_WINDOW(picturewin) );
2174
2175 gtk_widget_set_sensitive(picwin_combo_trace, FALSE);
2176 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_trace), 0 ); // trace off
2177
2178 gtk_widget_set_sensitive(picwin_combo_action, FALSE);
2179 gtk_combo_box_set_active( GTK_COMBO_BOX(picwin_combo_action), -1 ); // no action
2180
2181 combobox_trace_last_nrofentries = picwin_reload_combos( combobox_trace_last_nrofentries );
2182 }
2183
2184 picbild2 = src;
2185 picbild.update_from( src.pic );
2186
2187 picbild.mousemove_func = picwin_mousemove;
2188 picbild.mousedown_func = picwin_mousenop;
2189 picbild.mouseup_func = picwin_mousenop;
2190 }
2191
2192
picturewin_translate(void)2193 void picturewin_translate(void)
2194 {
2195 if(picturewin != 0)
2196 {
2197 GtkWidget *new_menu;
2198
2199 gtk_label_set( GTK_LABEL(picwin_label_trace), _("Trace action") );
2200
2201
2202 if(( new_menu = picturewin_build_menu()) == 0 )
2203 return;
2204
2205 gtk_widget_destroy( picturewin_menu );
2206 picturewin_menu = new_menu;
2207
2208 gtk_box_pack_start( GTK_BOX(picturewin_vbox), picturewin_menu, FALSE, FALSE, 0 );
2209 gtk_box_reorder_child( GTK_BOX(picturewin_vbox), picturewin_menu, 0 );
2210
2211 picwin_reload_combos( 12 );
2212 }
2213 }
2214
picturewin_close(void)2215 void picturewin_close(void)
2216 {
2217 if(picturewin != 0)
2218 {
2219 gtk_widget_destroy(picturewin);
2220 picturewin = 0;
2221 }
2222 }
2223