1
2 /*
3 * Ump - Unnamed Math Program
4 * Copyright (c) 2005 by Mattias Hultgren <mattias_hultgren@tele2.se>
5 *
6 * See main.cpp
7 */
8
9 #include <math.h>
10 #include "matrix_editor.h"
11 #include "main.h"
12 #include "ump_editor.h"
13 #include "ump_simplewin.h"
14 #include "ump_advancedwin.h"
15 #include "ump_graphwin.h"
16 #include "ump_prefwin.h"
17 #include "ump_aboutwin.h"
18 #include "vector.h"
19
20 const int matrix_editor_max_size = 500;
21
22 struct MatrixEditorPage
23 {
24 Matrix matrix;
25 GtkWidget *rows, *cols, *rows_label, *cols_label;
26 gint notebook_index;
27 };
28
29 struct MatrixEditor
30 {
31 Vector<MatrixEditorPage> pages;
32 GtkWidget *window, *notebook, *vbox, *menu, *bottom_label;
33 Format format;
34 }matrix_editor;
35
36
aboutwin_show_matrix_editor(void)37 void aboutwin_show_matrix_editor(void) { aboutwin_show(GTK_WINDOW(matrix_editor.window)); }
prefwin_show_matrix_editor(void)38 void prefwin_show_matrix_editor(void) { prefwin_show(GTK_WINDOW(matrix_editor.window)); }
39
40
41 void matrix_editor_add_matrix( const char *name, const Matrix &src, gint pos ) throw(error_obj);
42
43 void matrix_element_got_focus( GtkWidget *widget, gpointer user_data );
44 gboolean matrix_size_update( GtkWidget *widget, GdkEventFocus *event, gpointer user_data );
45 void matrix_element_update_insert( GtkEditable *editable, gchar *new_text, gint new_text_length,
46 gint *position, gpointer user_data );
47 void matrix_element_update_delete( GtkEditable *editable, gint start_pos, gint end_pos,
48 gpointer user_data);
49 void matrix_element_update( GtkEditable *editable, gpointer user_data );
50 gboolean matrix_element_focus_out( GtkWidget *widget, GdkEventFocus *event, gpointer user_data );
51
52 void menu_matrix_new(void);
53 void menu_matrix_new_with_name_func(void);
54 void menu_matrix_open(void);
55 void menu_matrix_close(void);
56 void menu_matrix_delete(void);
57 void menu_matrix_calc_inverse(void);
58 void menu_matrix_calc_transpose(void);
59 void menu_matrix_calc_determinant(void);
60 void menu_matrix_calc_adjoint(void);
61 void menu_matrix_calc_identity(void);
62 void menu_matrix_calc_add(void);
63 void menu_matrix_calc_substract(void);
64 void menu_matrix_calc_multiply(void);
65 void menu_matrix_calc_power(void);
66 void menu_matrix_calc_fill_with(void);
67
68
build_menu(void)69 GtkWidget* build_menu(void)
70 {
71 GtkActionGroup *actions;
72 GtkUIManager *ui_manager;
73 GError *error = NULL;
74 static const gchar *menu_str =
75 "<ui>"
76 " <menubar name='MenuBar'>"
77 " <menu action='FileMenu'>"
78 " <menuitem action='Preferences'/>"
79 " <separator/>"
80 " <menuitem action='Close'/>"
81 " <separator/>"
82 " <menuitem action='Quit'/>"
83 " </menu>"
84 " <menu action='MatrixMenu'>"
85 " <menuitem action='New'/>"
86 " <menuitem action='NewName'/>"
87 " <menuitem action='Open'/>"
88 " <menuitem action='CloseMatrix'/>"
89 " <menuitem action='Delete'/>"
90 " </menu>"
91 " <menu action='CalculateMenu'>"
92 " <menuitem action='Add'/>"
93 " <menuitem action='Substract'/>"
94 " <menuitem action='Multiply'/>"
95 " <menuitem action='Power'/>"
96 " <separator/>"
97 " <menuitem action='Adjoint'/>"
98 " <menuitem action='Determinant'/>"
99 " <menuitem action='Inverse'/>"
100 " <menuitem action='Transpose'/>"
101 " <separator/>"
102 " <menuitem action='Identity'/>"
103 " <menuitem action='FillWith'/>"
104 " <separator/>"
105 " </menu>"
106 " <menu action='ToolsMenu'>"
107 " <menuitem action='Simple'/>"
108 " <menuitem action='Advanced'/>"
109 " <menuitem action='Editor'/>"
110 " <menuitem action='Graphtool'/>"
111 " </menu>"
112 " <menuitem action='About'/>"
113 " </menubar>"
114 "</ui>";
115 GtkActionEntry entries[] = {
116 { "FileMenu", NULL, menu_file },
117 { "Preferences", GTK_STOCK_PREFERENCES, menu_pref, NULL, NULL, G_CALLBACK(prefwin_show_matrix_editor) },
118 { "Close", GTK_STOCK_CLOSE, menu_file_close, "<ctrl>W", NULL, G_CALLBACK(matrix_editor_close) },
119 { "Quit", GTK_STOCK_QUIT, menu_file_quit, "<ctrl>Q", NULL, G_CALLBACK(UMP_gtk_quit) },
120 { "MatrixMenu", NULL, _("_Matrix") },
121 { "New", GTK_STOCK_NEW, menu_file_new, "", NULL, G_CALLBACK(menu_matrix_new) },
122 { "NewName", GTK_STOCK_NEW, _("New with name..."), "<ctrl>N", NULL, G_CALLBACK(menu_matrix_new_with_name_func) },
123 { "Open", GTK_STOCK_OPEN, menu_file_open, "<ctrl>O", NULL, G_CALLBACK(menu_matrix_open) },
124 { "CloseMatrix", GTK_STOCK_CLOSE, menu_file_close, "", NULL, G_CALLBACK(menu_matrix_close) },
125 { "Delete", NULL, edit_edit_delete, "", NULL, G_CALLBACK(menu_matrix_delete) },
126 { "CalculateMenu", NULL, _("_Calculate") },
127 { "Inverse", NULL, _("Inverse"), NULL, NULL, G_CALLBACK(menu_matrix_calc_inverse) },
128 { "Transpose", NULL, _("Transpose"), NULL, NULL, G_CALLBACK(menu_matrix_calc_transpose) },
129 { "Determinant", NULL, _("Determinant"), NULL, NULL, G_CALLBACK(menu_matrix_calc_determinant) },
130 { "Adjoint", NULL, _("Adjoint"), NULL, NULL, G_CALLBACK(menu_matrix_calc_adjoint) },
131 { "Identity", NULL, _("Identity"), NULL, NULL, G_CALLBACK(menu_matrix_calc_identity) },
132 { "Power", NULL, _("Power..."), NULL, NULL, G_CALLBACK(menu_matrix_calc_power) },
133 { "FillWith", NULL, _("Fill with..."), NULL, NULL, G_CALLBACK(menu_matrix_calc_fill_with) },
134 { "Add", NULL, _("Add..."), NULL, NULL, G_CALLBACK(menu_matrix_calc_add) },
135 { "Substract", NULL, _("Substract..."), NULL, NULL, G_CALLBACK(menu_matrix_calc_substract) },
136 { "Multiply", NULL, _("Multiply..."), NULL, NULL, G_CALLBACK(menu_matrix_calc_multiply) },
137 { "ToolsMenu", NULL, menu_tools },
138 { "Simple", NULL, menu_tools_simple, NULL, NULL, G_CALLBACK(simplewin_show) },
139 { "Advanced", NULL, menu_tools_advanced, NULL, NULL, G_CALLBACK(advancedwin_show) },
140 { "Editor", NULL, menu_tools_editor, NULL, NULL, G_CALLBACK(editor_showwin) },
141 { "Graphtool", NULL, menu_tools_graphtool, NULL, NULL, G_CALLBACK(graphwin_show) },
142 { "About", NULL, menu_about, NULL, NULL, G_CALLBACK(aboutwin_show_matrix_editor) }
143 };
144 guint n_entries = G_N_ELEMENTS(entries);
145
146
147 actions = gtk_action_group_new("Actions");
148 gtk_action_group_add_actions(actions, entries, n_entries, NULL);
149 ui_manager = gtk_ui_manager_new();
150 gtk_ui_manager_insert_action_group(ui_manager, actions, 0);
151 gtk_window_add_accel_group( GTK_WINDOW(matrix_editor.window), gtk_ui_manager_get_accel_group(ui_manager) );
152 if(!gtk_ui_manager_add_ui_from_string(ui_manager, menu_str, -1, &error))
153 {
154 g_message("building menus failed: %s", error->message);
155 g_error_free(error);
156 return 0;
157 }
158 gtk_ui_manager_ensure_update(ui_manager);
159
160 return gtk_ui_manager_get_widget(ui_manager, "/MenuBar");
161 }
162
163
matrix_editor_show(void)164 GtkWindow* matrix_editor_show(void)
165 {
166 matrix_editor.format.set_max_decimals( 20 );
167 if( matrix_editor.window == 0 )
168 {
169 GtkWidget *tmp, *tmp2;
170
171 matrix_editor.window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
172
173 gtk_window_set_title( GTK_WINDOW(matrix_editor.window), _("Ump - Matrix editor") );
174 g_signal_connect_swapped( G_OBJECT(matrix_editor.window), "delete-event",
175 G_CALLBACK(matrix_editor_close), NULL );
176
177 matrix_editor.vbox = gtk_vbox_new(FALSE,0);
178 gtk_container_add( GTK_CONTAINER(matrix_editor.window), matrix_editor.vbox );
179
180
181 if( (matrix_editor.menu = build_menu()) == 0 )
182 {
183 gtk_widget_destroy( matrix_editor.window );
184 matrix_editor.window = 0;
185 return 0;
186 }
187 gtk_box_pack_start( GTK_BOX(matrix_editor.vbox), matrix_editor.menu, FALSE, FALSE, 0 );
188
189 matrix_editor.notebook = gtk_notebook_new();
190 gtk_box_pack_start( GTK_BOX(matrix_editor.vbox), matrix_editor.notebook, TRUE, TRUE, 3 );
191
192 gtk_notebook_set_scrollable( GTK_NOTEBOOK(matrix_editor.notebook), TRUE );
193
194 tmp = gtk_hbox_new( FALSE, 0 );
195 gtk_box_pack_start( GTK_BOX(matrix_editor.vbox), tmp, FALSE, TRUE, 0 );
196
197 matrix_editor.bottom_label = gtk_label_new( PRG_NAME );
198 gtk_misc_set_alignment(GTK_MISC(matrix_editor.bottom_label), 0.0f, 0.5f);
199 gtk_misc_set_padding(GTK_MISC(matrix_editor.bottom_label), 2, 2);
200 gtk_box_pack_start( GTK_BOX(tmp), matrix_editor.bottom_label, FALSE, TRUE, 0 );
201
202 tmp2 = gtk_statusbar_new();
203 gtk_box_pack_start( GTK_BOX(tmp), tmp2, TRUE, TRUE, 0 );
204
205
206 gtk_window_resize( GTK_WINDOW(matrix_editor.window), 500, 400 );
207 open_windows |= MATRIX_EDITOR_WIN;
208
209 menu_matrix_new();
210 }
211 else
212 gtk_window_present( GTK_WINDOW( matrix_editor.window ) );
213
214 return GTK_WINDOW(matrix_editor.window);
215 }
216
matrix_editor_close(void)217 void matrix_editor_close(void)
218 {
219 if( matrix_editor.window != 0 )
220 {
221 while( gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) != 0 )
222 menu_matrix_close();
223
224 gtk_widget_destroy( matrix_editor.window );
225 matrix_editor.window = 0;
226
227 matrix_editor.pages.clear();
228
229 open_windows &= ~MATRIX_EDITOR_WIN;
230 if(open_windows == 0)
231 UMP_gtk_quit();
232 }
233 }
234
matrix_editor_translate(void)235 void matrix_editor_translate(void)
236 {
237 if( matrix_editor.window != 0 )
238 {
239 GtkWidget *new_menu;
240
241 gtk_window_set_title( GTK_WINDOW( matrix_editor.window ), _("Ump - Matrix editor") );
242
243
244 if(( new_menu = build_menu()) == 0 )
245 return;
246
247 gtk_widget_destroy( matrix_editor.menu );
248 matrix_editor.menu = new_menu;
249
250 gtk_box_pack_start(GTK_BOX(matrix_editor.vbox), matrix_editor.menu, FALSE, FALSE, 0);
251 gtk_box_reorder_child( GTK_BOX(matrix_editor.vbox), matrix_editor.menu, 0 );
252
253 for( uint32 i=0; i<matrix_editor.pages.get_size(); i++ )
254 {
255 gtk_label_set_label( GTK_LABEL(matrix_editor.pages[i]->rows_label), _("_Rows: ") );
256
257 gtk_label_set_label( GTK_LABEL(matrix_editor.pages[i]->cols_label), _("_Columns: ") );
258 }
259 }
260 }
261
262
matrix_editor_add_matrix(const char * name,const Matrix & src,gint pos)263 void matrix_editor_add_matrix( const char *name, const Matrix &src, gint pos ) throw(error_obj)
264 {
265 MatrixEditorPage *page=0;
266 GtkAdjustment *tmp_adj;
267 GtkWidget *tmp, *vbox, *table;
268 utf8_string str;
269
270 try
271 {
272 page = new MatrixEditorPage;
273 page->matrix = src;
274 matrix_editor.pages.insert_this( page, pos );
275 }
276 catch( error_obj error )
277 {
278 delete page;
279 throw;
280 }
281 catch( ... ) { delete page; THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
282
283 if( pos == -1 )
284 pos = matrix_editor.pages.get_size() -1;
285
286 matrix_editor.pages[pos]->notebook_index = 0;
287 for( gint i=pos-1; i >= 0; i-- )
288 {
289 if( matrix_editor.pages[i]->notebook_index >= 0 )
290 {
291 matrix_editor.pages[pos]->notebook_index = matrix_editor.pages[i]->notebook_index +1;
292 break;
293 }
294 }
295
296 vbox = gtk_vbox_new(FALSE,0);
297 gtk_notebook_insert_page( GTK_NOTEBOOK(matrix_editor.notebook), vbox,
298 gtk_label_new( name ), matrix_editor.pages[pos]->notebook_index );
299
300 tmp = gtk_hbox_new(FALSE, 3);
301 gtk_box_pack_start( GTK_BOX(vbox), tmp, FALSE, TRUE, 3 );
302
303 page->rows_label = gtk_label_new_with_mnemonic( _("_Rows: ") );
304 gtk_box_pack_start( GTK_BOX(tmp), page->rows_label, FALSE, TRUE, 3 );
305
306 tmp_adj = (GtkAdjustment *) gtk_adjustment_new( gdouble(src.get_height()), 1.0, gdouble(matrix_editor_max_size), 1.0, 5.0, 5.0);
307 page->rows = gtk_spin_button_new(tmp_adj, 1.0, 0);
308 gtk_box_pack_start( GTK_BOX(tmp), page->rows, FALSE, TRUE, 3 );
309 gtk_label_set_mnemonic_widget( GTK_LABEL(page->rows_label), page->rows );
310
311
312 page->cols_label = gtk_label_new_with_mnemonic( _("_Columns: ") );
313 gtk_box_pack_start( GTK_BOX(tmp), page->cols_label, FALSE, TRUE, 3 );
314
315 tmp_adj = (GtkAdjustment *) gtk_adjustment_new( gdouble(src.get_width()), 1.0, gdouble(matrix_editor_max_size), 1.0, 5.0, 5.0);
316 page->cols = gtk_spin_button_new(tmp_adj, 1.0, 0);
317 gtk_box_pack_start( GTK_BOX(tmp), page->cols, FALSE, TRUE, 3 );
318 gtk_label_set_mnemonic_widget( GTK_LABEL(page->cols_label), page->cols );
319
320
321 tmp = gtk_scrolled_window_new( NULL, NULL );
322 gtk_box_pack_start( GTK_BOX(vbox), tmp, TRUE, TRUE, 3 );
323 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tmp), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
324
325 table = gtk_table_new( src.get_height(), src.get_width(), TRUE );
326 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(tmp), table );
327
328 for( uint32 row=0; row<src.get_height(); row++ )
329 {
330 for( uint32 col=0; col<src.get_width(); col++ )
331 {
332 tmp = gtk_entry_new();
333
334 gtk_table_attach( GTK_TABLE(table), tmp, col, col+1, row, row+1, GTK_FILL, GTK_FILL, 0, 0 );
335 gtk_widget_set_size_request( tmp, 100, 30 );
336
337 str.clear();
338 src.get_complex( col+1, row+1 ).append_to_string( str, matrix_editor.format );
339
340 gtk_entry_set_text( GTK_ENTRY(tmp), str.c_str() );
341
342 g_signal_connect( GTK_OBJECT(tmp), "grab-focus",
343 G_CALLBACK(matrix_element_got_focus),
344 GUINT_TO_POINTER((guint(col+1)<<9) + guint(row+1)) );
345
346 g_signal_connect_after( GTK_OBJECT(tmp), "focus-in-event",
347 G_CALLBACK(matrix_size_update), GINT_TO_POINTER(pos) );
348
349
350 g_signal_connect_after( GTK_OBJECT(tmp), "focus-out-event",
351 G_CALLBACK(matrix_element_focus_out),
352 GUINT_TO_POINTER( (guint(pos)<<18) + (guint(col+1)<<9) + guint(row+1) ) );
353
354 g_signal_connect_after( GTK_OBJECT(tmp), "insert-text",
355 G_CALLBACK(matrix_element_update_insert),
356 GUINT_TO_POINTER( (guint(pos)<<18) + (guint(col+1)<<9) + guint(row+1) ) );
357 g_signal_connect_after( GTK_OBJECT(tmp), "delete-text",
358 G_CALLBACK(matrix_element_update_delete),
359 GUINT_TO_POINTER( (guint(pos)<<18) + (guint(col+1)<<9) + guint(row+1) ) );
360 }
361 }
362 }
363
364
matrix_close_by_name(const char * name)365 void matrix_close_by_name( const char *name )
366 {
367 gint notebook_index, index;
368
369 for( notebook_index=0; ; notebook_index++ )
370 {
371 if( notebook_index == gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) )
372 return;
373
374 if( strcmp( gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
375 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) ),
376 name ) == 0 )
377 break;
378 }
379
380 for( index=0; index<matrix_editor.pages.get_size(); index++ )
381 {
382 if( notebook_index == matrix_editor.pages[index]->notebook_index )
383 break;
384 }
385 if( index == matrix_editor.pages.get_size() )
386 {
387 printf( "index == matrix_editor.pages.get_size()....this is a bug\n" );
388 return;
389 }
390
391 gtk_notebook_remove_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index );
392
393 if( index == (matrix_editor.pages.get_size() -1) )
394 {
395 matrix_editor.pages.remove( index );
396
397 while( index != 0 )
398 {
399 if( matrix_editor.pages[ index-1 ]->matrix.get_width() == 0 )
400 {
401 index--;
402 matrix_editor.pages.remove( index );
403 }
404 else
405 break;
406 }
407 }
408 else if( index != matrix_editor.pages.get_size() )
409 {
410 matrix_editor.pages[index]->matrix.set_size( 0, 0 );
411 matrix_editor.pages[index]->notebook_index = -1;
412 for( ; index < matrix_editor.pages.get_size(); index++ )
413 matrix_editor.pages[index]->notebook_index--;
414 }
415 }
416
417 /****************************************
418 * Below follows all signal callbacks *
419 ****************************************/
420
matrix_element_got_focus(GtkWidget * widget,gpointer user_data)421 void matrix_element_got_focus( GtkWidget *widget, gpointer user_data )
422 {
423 uint32 row, col;
424 static char str[200];
425
426 col = GPOINTER_TO_UINT(user_data);
427 row = 0x1ff & col;
428 col >>= 9;
429
430 snprintf( str, 200, "%s: %lu %s: %lu", _("Column"), col, _("Row"), row );
431
432 gtk_label_set_label( GTK_LABEL(matrix_editor.bottom_label), str );
433 }
434
matrix_update_page(int index)435 void matrix_update_page( int index ) throw(error_obj)
436 {
437 gint notebook_index = matrix_editor.pages[index]->notebook_index;
438
439 matrix_editor_add_matrix(
440 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
441 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index )),
442 matrix_editor.pages[index]->matrix, index );
443
444 gtk_widget_show_all( matrix_editor.window );
445 gtk_notebook_set_current_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index );
446 gtk_notebook_remove_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index+1 );
447
448 matrix_editor.pages.remove( index+1 );
449 }
450
matrix_size_update(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)451 gboolean matrix_size_update( GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
452 {
453 int index, notebook_index;
454 uint32 new_width, new_height;
455 math::Variable *ptr;
456
457 index = GPOINTER_TO_INT(user_data);
458 notebook_index = matrix_editor.pages[index]->notebook_index;
459
460 new_width = uint32(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matrix_editor.pages[index]->cols)));
461 new_height = uint32(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matrix_editor.pages[index]->rows)));
462
463 try
464 {
465 if( matrix_editor.pages[index]->matrix.get_height() != new_height ||
466 matrix_editor.pages[index]->matrix.get_width() != new_width )
467 {
468 Matrix matr, *src;
469 matr.set_size( new_width, new_height );
470 src = &(matrix_editor.pages[index]->matrix);
471
472 for( int r=1; r<=matr.get_height() && r<=src->get_height(); r++ )
473 {
474 for( int c=1; c<=matr.get_width() && c<=src->get_width(); c++ )
475 matr.set_complex( c, r, src->get_complex( c, r ) );
476 }
477 *src = matr;
478
479 matrix_update_page( index );
480
481 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
482 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
483 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ))));
484
485 *(ptr->get_matrix_rw()) = matr;
486 }
487 }
488 catch( error_obj error )
489 {
490 GtkWidget *dialog;
491 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
492 GTK_DIALOG_DESTROY_WITH_PARENT,
493 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
494 gtk_dialog_run(GTK_DIALOG(dialog));
495 gtk_widget_destroy(dialog);
496 }
497 return FALSE;
498 }
499
matrix_element_focus_out(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)500 gboolean matrix_element_focus_out( GtkWidget *widget, GdkEventFocus *event, gpointer user_data )
501 {
502 math::CodeLine calculater;
503 math::Variable ans;
504 utf8_string outstr;
505 uint32 index, row, col;
506 const gchar *str;
507
508 index = GPOINTER_TO_UINT(user_data);
509 row = 0x1ff & index;
510 index >>= 9;
511 col = 0x1ff & index;
512 index >>= 9;
513
514 str = gtk_entry_get_text( GTK_ENTRY(widget) );
515
516 try
517 {
518 calculater.set_code_line( str, false );
519 calculater.calc( &ans );
520
521 matrix_editor.pages[index]->matrix.get_complex( col, row ).append_to_string( outstr,
522 matrix_editor.format );
523
524 gtk_entry_set_text( GTK_ENTRY(widget), outstr.c_str() );
525 }
526 catch( error_obj error )
527 {
528 GtkWidget *dialog;
529 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
530 GTK_DIALOG_DESTROY_WITH_PARENT,
531 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
532 gtk_dialog_run(GTK_DIALOG(dialog));
533 gtk_widget_destroy(dialog);
534 }
535 }
536
matrix_element_update(GtkEditable * editable,gpointer user_data)537 void matrix_element_update( GtkEditable *editable, gpointer user_data )
538 {
539 math::CodeLine calculater;
540 math::Variable ans, *ptr;
541 uint32 index, row, col;
542 gchar *str;
543
544 index = GPOINTER_TO_UINT(user_data);
545 row = 0x1ff & index;
546 index >>= 9;
547 col = 0x1ff & index;
548 index >>= 9;
549
550 str = gtk_editable_get_chars( editable, 0, -1 );
551
552 try
553 {
554 calculater.set_code_line( str, false );
555 calculater.calc( &ans );
556
557 matrix_editor.pages[index]->matrix.set_complex( col, row, *ans.get_complex() );
558
559 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
560 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
561 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook),
562 matrix_editor.pages[index]->notebook_index ))));
563
564 *(ptr->get_matrix_rw()) = matrix_editor.pages[index]->matrix;
565 }
566 catch( ... ) { }
567
568 g_free( str );
569 }
570
matrix_element_update_insert(GtkEditable * editable,gchar * new_text,gint new_text_length,gint * position,gpointer user_data)571 void matrix_element_update_insert( GtkEditable *editable, gchar *new_text, gint new_text_length,
572 gint *position, gpointer user_data )
573 {
574 matrix_element_update( editable, user_data );
575 }
576
matrix_element_update_delete(GtkEditable * editable,gint start_pos,gint end_pos,gpointer user_data)577 void matrix_element_update_delete( GtkEditable *editable, gint start_pos, gint end_pos,
578 gpointer user_data )
579 {
580 matrix_element_update( editable, user_data );
581 }
582
matrix_changed(math::Variable * ptr)583 void matrix_changed( math::Variable *ptr )
584 {
585 gint notebook_index, index;
586 const char *name = ptr->get_name()->c_str();
587
588 if( ptr->get_type() != math::VariableType_Matrix )
589 {
590 matrix_close_by_name( ptr->get_name()->c_str() );
591 return;
592 }
593
594 if( ptr->get_matrix()->get_width() > matrix_editor_max_size ||
595 ptr->get_matrix()->get_width() == 0 ||
596 ptr->get_matrix()->get_height() > matrix_editor_max_size ||
597 ptr->get_matrix()->get_height() == 0 )
598 {
599 matrix_close_by_name( ptr->get_name()->c_str() );
600 return;
601 }
602
603 for( notebook_index=0; ; notebook_index++ )
604 {
605 if( notebook_index == gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) )
606 return;
607
608 if( strcmp( gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
609 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) ),
610 name ) == 0 )
611 break;
612 }
613
614 for( index=0; index<matrix_editor.pages.get_size(); index++ )
615 {
616 if( notebook_index == matrix_editor.pages[index]->notebook_index )
617 break;
618 }
619
620 if( index != matrix_editor.pages.get_size() )
621 {
622 try{
623 matrix_editor.pages[index]->matrix = *(ptr->get_matrix());
624
625 matrix_update_page( index );
626 }
627 catch( error_obj error )
628 {
629 GtkWidget *dialog;
630 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
631 GTK_DIALOG_DESTROY_WITH_PARENT,
632 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
633 gtk_dialog_run(GTK_DIALOG(dialog));
634 gtk_widget_destroy(dialog);
635 }
636 }
637 }
638
matrix_deleted(math::Variable * ptr)639 void matrix_deleted( math::Variable *ptr )
640 {
641 matrix_close_by_name( ptr->get_name()->c_str() );
642 }
643
644 /***************************************
645 * Below follows only menu callbacks *
646 ***************************************/
647
create_new_matrix_page(const char * name)648 void create_new_matrix_page( const char *name )
649 {
650 Matrix tmp_matr;
651 math::Variable var, *ptr;
652 Complex value(0);
653
654 try
655 {
656 tmp_matr.set_size( 3, 3 );
657 for( int i=1; i<=3; i++ )
658 for( int i2=1; i2<=3; i2++ )
659 tmp_matr.set_complex( i, i2, value );
660
661 matrix_editor_add_matrix( name, tmp_matr, -1 );
662
663 var.set_matrix( &tmp_matr );
664 var.set_name( name );
665
666 math::global_varlist.create( var, false, true, true );
667
668 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( name ) );
669
670 ptr->set_change_func( matrix_changed );
671 ptr->set_delete_func( matrix_deleted );
672 }
673 catch( error_obj error )
674 {
675 GtkWidget *dialog;
676 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
677 GTK_DIALOG_DESTROY_WITH_PARENT,
678 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
679 gtk_dialog_run(GTK_DIALOG(dialog));
680 gtk_widget_destroy(dialog);
681 }
682
683 gtk_widget_show_all( matrix_editor.window );
684
685 gtk_notebook_set_current_page( GTK_NOTEBOOK(matrix_editor.notebook),
686 gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) )-1 );
687 }
688
menu_matrix_new(void)689 void menu_matrix_new(void)
690 {
691 char str[100];
692 int i;
693
694 for( i=1; ; i++ )
695 {
696 snprintf( str, 100, "m%ld", i );
697
698 try{ math::global_varlist.get_id( str ); }
699 catch( ... ) { break; } // only throw "Variable not found"
700 }
701
702 create_new_matrix_page( str );
703 }
704
menu_matrix_new_with_name_func(void)705 void menu_matrix_new_with_name_func(void)
706 {
707 GtkWidget *align, *dialog, *entry, *hbox, *label;
708 const char *str;
709
710 dialog = gtk_dialog_new_with_buttons( _("New with name..."), GTK_WINDOW(matrix_editor.window),
711 GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
712
713 align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
714 gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
715 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
716
717 hbox = gtk_hbox_new( FALSE, 3 );
718 gtk_container_add( GTK_CONTAINER(align), hbox );
719
720 label = gtk_label_new( _("Name: ") );
721 gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 );
722
723 entry = gtk_entry_new();
724 gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 0 );
725
726 gtk_widget_show_all( dialog );
727
728 while( true )
729 {
730 if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_OK )
731 str = gtk_entry_get_text( GTK_ENTRY(entry) );
732 else
733 break;
734
735 if( str[0] == '\0' )
736 break;
737 try
738 {
739 math::check_name_against_reserved( str );
740
741 try{ math::global_varlist.get_id( str ); }
742 catch( ... )
743 {
744 create_new_matrix_page( str );
745 break;
746 }
747 char tmp_err[ERROR_OBJ_MSG_LEN];
748 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("\"%s\" is not a unique name."), str );
749 THROW_ERROR( ErrorType_General, tmp_err );
750 }
751 catch( error_obj error )
752 {
753 GtkWidget *dialog2;
754 dialog2 = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
755 GTK_DIALOG_DESTROY_WITH_PARENT,
756 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
757 gtk_dialog_run(GTK_DIALOG(dialog2));
758 gtk_widget_destroy(dialog2);
759 }
760 }
761 gtk_widget_destroy( dialog );
762 }
763
menu_matrix_open(void)764 void menu_matrix_open(void)
765 {
766 GtkWidget *dialog, *treeview;
767 GtkListStore *list_store;
768 GtkTreeIter iter;
769 gint i, i2;
770 GtkCellRenderer *renderer;
771 GtkTreeViewColumn *column;
772 bool empty_list = true;
773 char tmp_str[30];
774
775 enum { COLUMN_NAME, COLUMN_SIZE, N_COLUMNS };
776
777 list_store = gtk_list_store_new( N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING );
778
779 for( i=1; i<=math::global_varlist.get_highest_idnr(); i++ )
780 {
781 const math::Variable *ptr;
782 const char *name;
783
784 try{ ptr = math::global_varlist.get_pointer( i ); }
785 catch( ... ) { continue; } // only throw "Variable not found"
786
787 if( ptr->get_type() == math::VariableType_Matrix )
788 {
789 if( ptr->get_matrix()->get_width() == 0 || // don't add matrices of zero size
790 ptr->get_matrix()->get_height() == 0 )
791 continue;
792
793 if( ptr->get_matrix()->get_width() > matrix_editor_max_size || // don't add matrices of zero size
794 ptr->get_matrix()->get_height() > matrix_editor_max_size )
795 continue;
796
797 name = ptr->get_name()->c_str();
798
799 for( i2=0; i2<gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ); i2++ )
800 {
801 if( strcmp( name, gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
802 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), i2 ))) == 0 )
803 break;
804 }
805
806 if( i2 != gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) ) )
807 continue; // this matrix is already open
808
809 snprintf( tmp_str, 30, "%lux%lu", ptr->get_matrix()->get_height(), ptr->get_matrix()->get_width() );
810 gtk_list_store_append( list_store, &iter );
811 gtk_list_store_set( list_store, &iter, COLUMN_NAME, name, COLUMN_SIZE, tmp_str, -1);
812 empty_list = false;
813 }
814 }
815
816 if( empty_list )
817 {
818 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
819 GTK_DIALOG_DESTROY_WITH_PARENT,
820 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
821 _("There is no matrix variable to open.") );
822 gtk_dialog_run(GTK_DIALOG(dialog));
823 gtk_widget_destroy(dialog);
824
825 return;
826 }
827
828 gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(list_store), COLUMN_NAME,
829 GTK_SORT_ASCENDING );
830
831 dialog = gtk_dialog_new_with_buttons ( _("Open a matrix variable"),
832 GTK_WINDOW(matrix_editor.window),
833 GTK_DIALOG_DESTROY_WITH_PARENT,
834 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
835 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
836 NULL );
837
838 treeview = gtk_tree_view_new_with_model( GTK_TREE_MODEL(list_store) );
839 gtk_box_pack_start( GTK_BOX( GTK_DIALOG(dialog)->vbox ), treeview, TRUE, TRUE, 3 );
840
841 renderer = gtk_cell_renderer_text_new();
842 column = gtk_tree_view_column_new_with_attributes( _("Name"), renderer, "text", COLUMN_NAME, NULL);
843 gtk_tree_view_append_column( GTK_TREE_VIEW(treeview), column );
844
845 renderer = gtk_cell_renderer_text_new();
846 column = gtk_tree_view_column_new_with_attributes( _("Size"), renderer, "text", COLUMN_SIZE, NULL);
847 gtk_tree_view_append_column( GTK_TREE_VIEW(treeview), column );
848
849 gtk_widget_show( treeview );
850
851 switch( gtk_dialog_run( GTK_DIALOG(dialog) ) )
852 {
853 case GTK_RESPONSE_ACCEPT:
854 {
855 GtkTreeSelection *sel;
856 GtkTreeModel *model;
857 gchar *name;
858 math::Variable *ptr;
859
860 sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(treeview) );
861
862 if( gtk_tree_selection_get_selected( sel, &model, &iter ) )
863 {
864 gtk_tree_model_get( model, &iter, COLUMN_NAME, &name, -1 );
865
866 try
867 {
868 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( name ) );
869
870 matrix_editor_add_matrix( name, *ptr->get_matrix(), -1 );
871
872 ptr->set_change_func( matrix_changed );
873 ptr->set_delete_func( matrix_deleted );
874 }
875 catch( error_obj error )
876 {
877 GtkWidget *dialog;
878 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
879 GTK_DIALOG_DESTROY_WITH_PARENT,
880 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
881 gtk_dialog_run(GTK_DIALOG(dialog));
882 gtk_widget_destroy(dialog);
883 }
884 gtk_widget_show_all( matrix_editor.window );
885 gtk_notebook_set_current_page( GTK_NOTEBOOK(matrix_editor.notebook),
886 gtk_notebook_get_n_pages( GTK_NOTEBOOK(matrix_editor.notebook) )-1 );
887 g_free( name );
888 }
889 }
890 break;
891
892 case GTK_RESPONSE_REJECT:
893 break;
894 }
895 gtk_widget_destroy( dialog );
896 }
897
menu_matrix_close(void)898 void menu_matrix_close(void)
899 {
900 gint notebook_index;
901 math::Variable *ptr;
902
903 notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
904
905 if( notebook_index == -1 )
906 return;
907
908 try
909 {
910 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
911 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
912 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ))));
913
914 ptr->set_change_func( 0 );
915 ptr->set_delete_func( 0 );
916
917 matrix_close_by_name(
918 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
919 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) ) );
920 }
921 catch( ... ){}
922 }
923
menu_matrix_delete(void)924 void menu_matrix_delete(void)
925 {
926 gint notebook_index;
927
928 notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
929
930 if( notebook_index == -1 )
931 return;
932
933 try
934 {
935 math::global_varlist.remove( math::global_varlist.get_id(
936 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
937 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) )
938 ) );
939 }
940 catch( error_obj error )
941 {
942 GtkWidget *dialog;
943 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
944 GTK_DIALOG_DESTROY_WITH_PARENT,
945 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg);
946 gtk_dialog_run(GTK_DIALOG(dialog));
947 gtk_widget_destroy(dialog);
948 }
949 }
950
menu_matrix_calc_inv_trans_adj(int which)951 void menu_matrix_calc_inv_trans_adj( int which ) //_identity
952 {
953 gint notebook_index;
954 math::Variable *ptr;
955
956 notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
957
958 if( notebook_index == -1 )
959 return;
960
961 try
962 {
963 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(
964 gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
965 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) )
966 ) );
967 if( which == 0 )
968 ptr->get_matrix_rw()->inverse();
969 else if( which == 1 )
970 ptr->get_matrix_rw()->trans();
971 else if( which == 2 )
972 ptr->get_matrix_rw()->adjoint();
973 else
974 ptr->get_matrix_rw()->identity();
975 ptr->signal_changed();
976 }
977 catch( error_obj error )
978 {
979 GtkWidget *dialog;
980 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
981 GTK_DIALOG_DESTROY_WITH_PARENT,
982 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
983 gtk_dialog_run(GTK_DIALOG(dialog));
984 gtk_widget_destroy(dialog);
985 }
986 }
987
menu_matrix_calc_inverse(void)988 void menu_matrix_calc_inverse(void)
989 {
990 menu_matrix_calc_inv_trans_adj( 0 );
991 }
menu_matrix_calc_transpose(void)992 void menu_matrix_calc_transpose(void)
993 {
994 menu_matrix_calc_inv_trans_adj( 1 );
995 }
menu_matrix_calc_adjoint(void)996 void menu_matrix_calc_adjoint(void)
997 {
998 menu_matrix_calc_inv_trans_adj( 2 );
999 }
menu_matrix_calc_identity(void)1000 void menu_matrix_calc_identity(void)
1001 {
1002 menu_matrix_calc_inv_trans_adj( 3 );
1003 }
1004
menu_matrix_calc_determinant(void)1005 void menu_matrix_calc_determinant(void)
1006 {
1007 gint notebook_index;
1008 Complex det;
1009 const char *name;
1010
1011 notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
1012
1013 if( notebook_index == -1 )
1014 return;
1015
1016 try
1017 {
1018 name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1019 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) );
1020 det = math::global_varlist.get_pointer( math::global_varlist.get_id(name) )
1021 ->get_matrix()->det();
1022
1023 try
1024 {
1025 GtkWidget *dialog;
1026 utf8_string ostr, tmp_str;
1027
1028 ostr = "det ";
1029 tmp_str = name;
1030 ostr.append( tmp_str );
1031 tmp_str = " = ";
1032 ostr.append( tmp_str );
1033
1034 det.append_to_string( ostr, matrix_editor.format );
1035 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1036 GTK_DIALOG_DESTROY_WITH_PARENT,
1037 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, ostr.c_str() );
1038 gtk_dialog_run(GTK_DIALOG(dialog));
1039 gtk_widget_destroy(dialog);
1040 }
1041 catch( error_obj error ) { throw; }
1042 catch( ... ) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1043 }
1044 catch( error_obj error )
1045 {
1046 GtkWidget *dialog;
1047 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1048 GTK_DIALOG_DESTROY_WITH_PARENT,
1049 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
1050 gtk_dialog_run(GTK_DIALOG(dialog));
1051 gtk_widget_destroy(dialog);
1052 }
1053 }
1054
menu_matrix_calc_add_sub_mul(int which)1055 void menu_matrix_calc_add_sub_mul( int which )
1056 {
1057 utf8_string base, str;
1058 GtkWidget *dialog, *align, *vbox;
1059 const char *name;
1060 math::Variable *ptr;
1061 const math::Variable *ptr2;
1062 Vector<GtkWidget *> radios;
1063 int i,nr;
1064 bool valid;
1065
1066 try{
1067 try{
1068 if( which == 0 )
1069 name = _("Add...");
1070 else if( which == 1 )
1071 name = _("Substract...");
1072 else
1073 name = _("Multiply...");
1074 dialog = gtk_dialog_new_with_buttons( name, GTK_WINDOW(matrix_editor.window),
1075 GTK_DIALOG_MODAL, GTK_STOCK_OK,
1076 GTK_RESPONSE_OK, NULL );
1077
1078 base = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1079 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook),
1080 gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) ) ) );
1081 ptr = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(base.c_str()) );
1082 if( which == 0 )
1083 base.append( " += " );
1084 else if( which == 1 )
1085 base.append( " -= " );
1086 else
1087 base.append( " *= " );
1088
1089 align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
1090 gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
1091 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
1092
1093 vbox = gtk_vbox_new( FALSE, 3 );
1094 gtk_container_add( GTK_CONTAINER(align), vbox );
1095
1096 for( i=0,nr=0; i<gtk_notebook_get_n_pages(GTK_NOTEBOOK(matrix_editor.notebook)); i++ )
1097 {
1098 name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1099 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), i ) );
1100 ptr2 = math::global_varlist.get_pointer( math::global_varlist.get_id(name) );
1101 if( which == 0 || which == 1 ) // add or substract
1102 valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_width() &&
1103 ptr->get_matrix()->get_height() == ptr2->get_matrix()->get_height() );
1104 else // multiply
1105 valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_height() );
1106 if( valid )
1107 {
1108 str = base;
1109
1110 str.append( *ptr2->get_name() );
1111
1112 if(nr == 0)
1113 {
1114 radios.append( gtk_radio_button_new_with_label( NULL, str.c_str() ) );
1115 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(*radios[0]), TRUE );
1116 }
1117 else
1118 radios.append( gtk_radio_button_new_with_label_from_widget(
1119 GTK_RADIO_BUTTON(*radios[0]), str.c_str() ) );
1120
1121 gtk_box_pack_start(GTK_BOX(vbox), *radios[nr], FALSE, FALSE, 0);
1122 nr++;
1123 }
1124 }
1125
1126 if( nr == 0 )
1127 THROW_ERROR( ErrorType_General, _("No matching matrix found") );
1128
1129 gtk_widget_show_all(dialog);
1130
1131 switch(gtk_dialog_run( GTK_DIALOG(dialog) ))
1132 {
1133 case GTK_RESPONSE_OK:
1134 for( i=0,nr=0; i<gtk_notebook_get_n_pages(GTK_NOTEBOOK(matrix_editor.notebook)); i++ )
1135 {
1136 name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1137 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), i ) );
1138 ptr2 = math::global_varlist.get_pointer( math::global_varlist.get_id(name) );
1139 if( which == 0 || which == 1 ) // add or substract
1140 valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_width() &&
1141 ptr->get_matrix()->get_height() == ptr2->get_matrix()->get_height() );
1142 else // multiply
1143 valid = ( ptr->get_matrix()->get_width() == ptr2->get_matrix()->get_height() );
1144 if( valid )
1145 {
1146 if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(*radios[nr]) ) == TRUE )
1147 {
1148 Matrix matr;
1149
1150 if( which == 0) // add
1151 matrix_add( &matr, ptr->get_matrix(), ptr2->get_matrix() );
1152 else if( which == 1 ) // substract
1153 matrix_sub( &matr, ptr->get_matrix(), ptr2->get_matrix() );
1154 else // multiply
1155 matrix_mul( &matr, ptr->get_matrix(), ptr2->get_matrix() );
1156 ptr->set_matrix( &matr );
1157 ptr->signal_changed();
1158 break;
1159 }
1160 nr++;
1161 }
1162 }
1163 break;
1164
1165 default:
1166 break;
1167 }
1168 }
1169 catch( error_obj error ) { gtk_widget_destroy(dialog); throw error; }
1170 catch( ... ) { gtk_widget_destroy(dialog); THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
1171 gtk_widget_destroy(dialog);
1172 }
1173 catch( error_obj error )
1174 {
1175 GtkWidget *dialog;
1176 dialog = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1177 GTK_DIALOG_DESTROY_WITH_PARENT,
1178 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
1179 gtk_dialog_run(GTK_DIALOG(dialog));
1180 gtk_widget_destroy(dialog);
1181 }
1182 }
1183
menu_matrix_calc_add(void)1184 void menu_matrix_calc_add(void)
1185 {
1186 menu_matrix_calc_add_sub_mul( 0 );
1187 }
menu_matrix_calc_substract(void)1188 void menu_matrix_calc_substract(void)
1189 {
1190 menu_matrix_calc_add_sub_mul( 1 );
1191 }
menu_matrix_calc_multiply(void)1192 void menu_matrix_calc_multiply(void)
1193 {
1194 menu_matrix_calc_add_sub_mul( 2 );
1195 }
1196
menu_matrix_calc_power_fill(int val)1197 void menu_matrix_calc_power_fill( int val )
1198 {
1199 GtkWidget *align, *dialog, *entry, *hbox, *label;
1200 const char *str, *name;
1201 gint notebook_index;
1202
1203
1204 notebook_index = gtk_notebook_get_current_page( GTK_NOTEBOOK(matrix_editor.notebook) );
1205 if( notebook_index == -1 )
1206 return;
1207
1208 if( val == 0 ) // power
1209 dialog = gtk_dialog_new_with_buttons( _("Power..."), GTK_WINDOW(matrix_editor.window),
1210 GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
1211 else // if( val == 1 ) // fill with
1212 dialog = gtk_dialog_new_with_buttons( _("Fill with..."), GTK_WINDOW(matrix_editor.window),
1213 GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL );
1214
1215 align = gtk_alignment_new( 0.0, 0.0, 1.0, 1.0 );
1216 gtk_container_set_border_width( GTK_CONTAINER(align), 5 );
1217 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
1218
1219 hbox = gtk_hbox_new( FALSE, 3 );
1220 gtk_container_add( GTK_CONTAINER(align), hbox );
1221
1222 {
1223 const char *trans;
1224 if( val == 0 )
1225 trans = _("Power: ");
1226 else
1227 trans = _("Fill with: ");
1228 label = gtk_label_new( trans );
1229 }
1230 gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 );
1231
1232 entry = gtk_entry_new();
1233 gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 0 );
1234
1235 gtk_widget_show_all( dialog );
1236
1237 if( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_OK )
1238 str = gtk_entry_get_text( GTK_ENTRY(entry) );
1239 else
1240 {
1241 gtk_widget_destroy( dialog );
1242 return;
1243 }
1244
1245 try
1246 {
1247 math::CodeLine code;
1248 math::Variable *var, ans;
1249 Matrix matr_ans;
1250
1251 code.set_code_line( str );
1252
1253 code.calc( &ans );
1254
1255 name = gtk_notebook_get_tab_label_text( GTK_NOTEBOOK(matrix_editor.notebook),
1256 gtk_notebook_get_nth_page( GTK_NOTEBOOK(matrix_editor.notebook), notebook_index ) );
1257 var = math::global_varlist.get_pointer_rw( math::global_varlist.get_id(name) );
1258
1259 if( val == 0 )
1260 {
1261 Integer power;
1262
1263 if( ans.get_complex()->imaginary != Real(0.0) )
1264 THROW_ERROR( ErrorType_Domain, _("Domain error: Imaginary part must be zero.") );
1265 if( !ans.get_complex()->real.isInteger() )
1266 THROW_ERROR( ErrorType_Domain, _("Domain error: Can't raise a matrix to a non integer number.") );
1267 ans.get_complex()->real.get_top( &power );
1268 matrix_pow( &matr_ans, var->get_matrix(), power );
1269 var->set_matrix( &matr_ans );
1270 }
1271 else //if( val == 1 )
1272 {
1273 var->get_matrix_rw()->fill( *ans.get_complex() );
1274 var->signal_changed();
1275 }
1276 }
1277 catch( error_obj error )
1278 {
1279 GtkWidget *dialog2;
1280 dialog2 = gtk_message_dialog_new( GTK_WINDOW(matrix_editor.window),
1281 GTK_DIALOG_DESTROY_WITH_PARENT,
1282 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error.msg );
1283 gtk_dialog_run( GTK_DIALOG(dialog2) );
1284 gtk_widget_destroy( dialog2 );
1285 }
1286 gtk_widget_destroy( dialog );
1287 }
1288
menu_matrix_calc_power(void)1289 void menu_matrix_calc_power(void)
1290 {
1291 menu_matrix_calc_power_fill( 0 );
1292 }
menu_matrix_calc_fill_with(void)1293 void menu_matrix_calc_fill_with(void)
1294 {
1295 menu_matrix_calc_power_fill( 1 );
1296 }
1297