1 /*
2 * xnec2c - GTK2-based version of nec2c, the C translation of NEC2
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /* geom_edit.c
20 *
21 * Structure/Geometry editor functions for xnec2c
22 */
23
24 #include "geom_edit.h"
25 #include "shared.h"
26
27 /*------------------------------------------------------------------------*/
28
29 /* Wire_Editor()
30 *
31 * Handles all actions of the wire editor window
32 */
33 void
Wire_Editor(int action)34 Wire_Editor( int action )
35 {
36 /* For looking up spinbuttons */
37 GtkSpinButton *spin;
38
39 /* Frame of tapered wire data */
40 GtkWidget *frame;
41
42 /* For reading/writing to GW & GC rows */
43 static GtkTreeIter
44 iter_gw,
45 iter_gc;
46
47 int idx, idi;
48
49 static gboolean
50 load = FALSE, /* Enable wire loading (conductivity specified) */
51 taper = FALSE, /* Editing a tapered wire */
52 save = FALSE, /* Enable saving of editor data */
53 busy = FALSE, /* Block callbacks. Must be a better way to do this? */
54 newpcl = TRUE, /* New percent-of-lambda value */
55 newrdm = TRUE, /* New diameter ratio value */
56 newwln = TRUE; /* New wire length value */
57
58 /* Float type data, wire conductivity */
59 static gdouble fv[14], s = 0.0;
60
61 /* Integer type data */
62 static gint iv[4];
63
64 /* Wire's projection on xyz axes */
65 gdouble dx, dy, dz;
66
67 /* Card (row) name */
68 gchar name[3];
69
70 /* Spin button names, int & float data */
71 gchar *ispin[2] =
72 {
73 "wire_tagnum_spinbutton",
74 "wire_numseg_spinbutton"
75 };
76
77 gchar *fspin[14] =
78 {
79 "wire_x1_spinbutton",
80 "wire_y1_spinbutton",
81 "wire_z1_spinbutton",
82 "wire_x2_spinbutton",
83 "wire_y2_spinbutton",
84 "wire_z2_spinbutton",
85 "wire_dia_spinbutton",
86 "wire_rlen_spinbutton",
87 "wire_dia1_spinbutton",
88 "wire_dian_spinbutton",
89 "wire_rdia_spinbutton",
90 "wire_pcl_spinbutton",
91 "wire_len_spinbutton",
92 "wire_res_spinbutton"
93 };
94
95
96 /* Block callbacks. (Should be a better way to do this) */
97 if( Give_Up( &busy, wire_editor) ) return;
98
99 /* Save data to nec2 editor if appropriate */
100 if( (action & EDITOR_SAVE) && save )
101 {
102 /* Clear data not used in GC card */
103 iv[SPIN_COL_I3] = iv[SPIN_COL_I4] = 0;
104 for( idx = WIRE_RDIA; idx <= WIRE_RES; idx++ )
105 fv[idx] = 0.0;
106
107 /* Set GW data to treeview */
108 Set_Geometry_Data( geom_store, &iter_gw, iv, fv );
109
110 /* Set GC card data to treeview if taper */
111 if( taper )
112 Set_Geometry_Data( geom_store, &iter_gc,
113 &iv[SPIN_COL_I3], &fv[WIRE_RLEN] );
114
115 /* Set wire conductivity (loading card) */
116 if( load )
117 Set_Wire_Conductivity( iv[SPIN_COL_I1], s, cmnd_store );
118
119 save = load = FALSE;
120 } /* if( (action & EDITOR_SAVE) && save ) */
121
122 /* Read int data from the wire editor */
123 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
124 {
125 spin = GTK_SPIN_BUTTON( lookup_widget(wire_editor, ispin[idi]) );
126 iv[idi] = gtk_spin_button_get_value_as_int( spin );
127 }
128
129 /* Read float data from the wire editor */
130 for( idx = WIRE_X1; idx <= WIRE_RES; idx++ )
131 {
132 spin = GTK_SPIN_BUTTON( lookup_widget(wire_editor, fspin[idx]) );
133 fv[idx] = gtk_spin_button_get_value( spin );
134 }
135 fv[WIRE_DIA] /= 2.0;
136 fv[WIRE_DIA1] /= 2.0;
137 fv[WIRE_DIAN] /= 2.0;
138
139 /* Respond to user action */
140 switch( action )
141 {
142 case EDITOR_NEW: /* New wire row(s) to create */
143 /* Insert a default GE card if list is empty */
144 Insert_GE_Card( geom_store, &iter_gw );
145
146 /* Insert a new blank GW row after a selected row,
147 * if any, otherwise before the last (GE) row */
148 Insert_Blank_Geometry_Row(
149 geom_treeview, geom_store, &iter_gw, "GW" );
150
151 /* Some default values */
152 iv[SPIN_COL_I1] = ++gbl_tag_num;
153 iv[SPIN_COL_I3] = iv[SPIN_COL_I4] = 0;
154
155 if( taper )
156 {
157 /* Insert a new blank GC row if tapered wire */
158 Insert_Blank_Geometry_Row(
159 geom_treeview, geom_store, &iter_gc, "GC" );
160 fv[WIRE_DIA] = 0.0;
161 }
162
163 /* Scroll tree view to bottom */
164 gtk_adjustment_set_value(
165 geom_adjustment, geom_adjustment->upper );
166 break;
167
168 case EDITOR_EDIT: /* Edit a wire row (GW/GC) */
169 /* Get selected row */
170 Get_Selected_Row(
171 geom_treeview, geom_store, &iter_gw, name );
172 iter_gc = iter_gw;
173
174 /*** Editing a GC card ***/
175 if( strcmp(name, "GC") == 0 )
176 {
177 taper = TRUE;
178
179 /* Get tapered wire data from tree view */
180 Get_Geometry_Data( geom_store, &iter_gc,
181 &iv[SPIN_COL_I3], &fv[WIRE_RLEN] );
182 fv[WIRE_RDIA] = fv[WIRE_RLEN];
183
184 /* Check for a preceding GW card.
185 * If card is GW, get wire data */
186 if( Check_Card_Name(geom_store, &iter_gw, PREVIOUS, "GW") )
187 {
188 Get_Geometry_Data( geom_store, &iter_gw, iv, fv );
189
190 /* Warn user if wire radius not 0 */
191 if( fv[WIRE_DIA] != 0.0 )
192 stop( _("GC card preceded by GW card\n"\
193 "with non-zero wire radius"), ERR_OK );
194
195 } /* if( strcmp(name, "GC") == 0 ) */
196 else stop( _("No GW card before GC card"), ERR_OK );
197 }
198 else /*** Editing a GW card ***/
199 {
200 taper = FALSE;
201
202 /* Get wire data from tree view */
203 Get_Geometry_Data( geom_store, &iter_gw, iv, fv );
204
205 /* Get wire conductivity if specified in LD card */
206 Get_Wire_Conductivity(iv[SPIN_COL_I1], &s, cmnd_store);
207 fv[WIRE_RES] = s;
208
209 /*** Get tapered wire data if dia = 0 ***/
210 if( fv[WIRE_DIA] == 0.0 )
211 {
212 /* If next card is GC, get data */
213 if( Check_Card_Name(geom_store, &iter_gc, NEXT, "GC") )
214 {
215 taper = TRUE;
216
217 /* Get wire taper data from tree view */
218 Get_Geometry_Data( geom_store, &iter_gc,
219 &iv[SPIN_COL_I3], &fv[WIRE_RLEN] );
220 fv[WIRE_RDIA] = fv[WIRE_RLEN];
221 }
222 else stop( _("No GC card after a GW card\n"\
223 "with a zero wire radius"), ERR_OK );
224
225 } /* if( fv[WIRE_DIA] == 0.0 ) */
226 /* If radius != 0, next card should not be GC */
227 else if( Check_Card_Name(geom_store, &iter_gc, NEXT, "GC") )
228 stop( _("GC card follows a GW card\n"\
229 "with non-zero wire radius"), ERR_OK );
230
231 } /* if( strcmp(name, "GC") == 0 ) */
232 break;
233
234 case WIRE_EDITOR_TAPR: /* Show taper wire data if button checked */
235 {
236 /* Wire diameter */
237 static double diam;
238
239 /* Read tapered wire checkbutton */
240 taper = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(
241 lookup_widget(wire_editor, "wire_taper_checkbutton")) );
242 if( taper )
243 {
244 /* Set wire dia to 0 */
245 diam = fv[WIRE_DIA];
246 fv[WIRE_DIA] = 0.0;
247
248 /* Insert GC card if valid GW iteration */
249 if( gtk_list_store_iter_is_valid(geom_store, &iter_gw) )
250 Insert_Blank_Geometry_Row(
251 geom_treeview, geom_store, &iter_gc, "GC");
252 }
253 else
254 {
255 /* Restore wire diam */
256 fv[WIRE_DIA] = diam;
257
258 /* Remove GC card if valid */
259 Remove_Row( geom_store, &iter_gc );
260 } /* if( taper ) */
261 }
262 save = TRUE;
263 break;
264
265 case EDITOR_CANCEL: /* Cancel wire editor */
266 /* Remove cards */
267 Remove_Row( geom_store, &iter_gw );
268 if( taper )
269 Remove_Row( geom_store, &iter_gc );
270 save = busy = FALSE;
271 return;
272
273 case EDITOR_DATA: /* Some data changed in editor window */
274 save = TRUE;
275 break;
276
277 case EDITOR_LOAD: /* Wire conductivity specified */
278 spin = GTK_SPIN_BUTTON( lookup_widget(
279 wire_editor, fspin[WIRE_RES]) );
280 s = gtk_spin_button_get_value( spin );
281 if( s > 0.0 )
282 {
283 save = TRUE;
284 load = TRUE;
285 }
286 else load = FALSE;
287 break;
288
289 case EDITOR_TAGNUM: /* Tag number edited by user */
290 gbl_tag_num = iv[SPIN_COL_I1];
291 save = TRUE;
292 if( s > 0.0 ) load = TRUE;
293 break;
294
295 case EDITOR_SEGPC: /* Segment length as % of smallest wavelength */
296 /* Calculate num of segs for given % of lambda */
297 if( calc_data.mxfrq != 0.0 )
298 {
299 if( taper && ( fv[WIRE_RLEN] != 1.0) ) /* Taper ratio < 1 */
300 {
301 double cnt = 1.0 / (fv[WIRE_PCL]/100.0) * (1.0-fv[WIRE_RLEN]);
302 if( cnt < 1.0 )
303 {
304 double i = ceil( log(1.0-cnt) / log(fv[WIRE_RLEN]) );
305 iv[SPIN_COL_I2] = (gint)i;
306 }
307 }
308 else
309 {
310 double i = ceil( 100.0 * (fv[WIRE_LEN]/fv[WIRE_PCL]) /
311 ((double)CVEL/calc_data.mxfrq) );
312 iv[SPIN_COL_I2] = (gint)i;
313 }
314 }
315 newpcl = FALSE;
316 save = TRUE;
317 break;
318
319 /* Calculate new wire end points on length change */
320 case WIRE_EDITOR_WLEN:
321 {
322 double l, dl;
323
324 /* Length of wire's projection on axes */
325 dx = fv[WIRE_X2]-fv[WIRE_X1];
326 dy = fv[WIRE_Y2]-fv[WIRE_Y1];
327 dz = fv[WIRE_Z2]-fv[WIRE_Z1];
328
329 /* Wire's length */
330 l = (gdouble)sqrt( dx*dx + dy*dy + dz*dz );
331
332 /* 1/2 of change in wire's length / length */
333 dl = fv[WIRE_LEN] - l; dl /= 2.0 * l;
334
335 /* Corresponding change in wire end co-ordinates */
336 dx *= dl; dy *= dl; dz *= dl;
337 fv[WIRE_X1] -= dx; fv[WIRE_X2] += dx;
338 fv[WIRE_Y1] -= dy; fv[WIRE_Y2] += dy;
339 fv[WIRE_Z1] -= dz; fv[WIRE_Z2] += dz;
340 }
341 newwln = FALSE;
342 save = TRUE;
343 break;
344
345 case WIRE_EDITOR_RLEN: /* Length taper ratio changed */
346 fv[WIRE_DIAN] = fv[WIRE_DIA1] *
347 pow(fv[WIRE_RLEN], (double)(iv[SPIN_COL_I2]-1)); /* Nth seg dia */
348 break;
349
350 case WIRE_EDITOR_RDIA: /* New diameter taper ratio */
351 fv[WIRE_DIAN] = fv[WIRE_DIA1] *
352 pow(fv[WIRE_RDIA], (double)(iv[SPIN_COL_I2]-1)); /* Nth seg dia */
353 newrdm = FALSE;
354 save = TRUE;
355
356 } /* switch( action ) */
357
358 /* Frame of tapered wire data */
359 frame = lookup_widget(wire_editor, "wire_taperframe");
360 /* Show taper data if appropriate */
361 if( taper )
362 {
363 gtk_widget_show( frame );
364 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(
365 lookup_widget(wire_editor,
366 "wire_taper_checkbutton")), TRUE );
367 }
368 else
369 {
370 gtk_widget_hide( frame );
371 gtk_window_resize( GTK_WINDOW(wire_editor), 10, 10 );
372 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(
373 lookup_widget(wire_editor,
374 "wire_taper_checkbutton")), FALSE );
375 }
376
377 /*** Calculate wire length ***/
378 if( newwln )
379 {
380 /* Length of wire's projection on axes */
381 dx = fv[WIRE_X2]-fv[WIRE_X1];
382 dy = fv[WIRE_Y2]-fv[WIRE_Y1];
383 dz = fv[WIRE_Z2]-fv[WIRE_Z1];
384 /* Wire's length */
385 fv[WIRE_LEN] = (gdouble)sqrt( dx*dx + dy*dy + dz*dz );
386 }
387 else newwln = TRUE;
388
389 /*** Calculate seg length as % of smallest wavelength ***/
390 if( (calc_data.mxfrq != 0.0) && newpcl )
391 {
392 if( taper && (fv[WIRE_RLEN] != 1.0) )
393 fv[WIRE_PCL] =
394 100.0 * fv[WIRE_LEN] * (1.0-fv[WIRE_RLEN]) /
395 (1.0-(gdouble)pow(fv[WIRE_RLEN], (gdouble)iv[SPIN_COL_I2])) /
396 ((gdouble)CVEL/calc_data.mxfrq);
397 else
398 fv[WIRE_PCL] = 100.0 * (fv[WIRE_LEN] /
399 (gdouble)iv[SPIN_COL_I2]) / ((gdouble)CVEL/calc_data.mxfrq);
400 }
401 else newpcl = TRUE;
402
403 /*** Calculate radius taper ratio ***/
404 if( (iv[SPIN_COL_I2] > 1) && newrdm )
405 fv[WIRE_RDIA] = pow( fv[WIRE_DIAN]/fv[WIRE_DIA1],
406 1.0/(double)(iv[SPIN_COL_I2]-1) );
407 else newrdm = TRUE;
408
409 /* Write int data to the wire editor */
410 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
411 {
412 spin = GTK_SPIN_BUTTON(
413 lookup_widget(wire_editor, ispin[idi]) );
414 gtk_spin_button_set_value( spin, iv[idi] );
415 }
416
417 /* Write float data to the wire editor (F1 to F7 and taper) */
418 fv[WIRE_DIA] *= 2.0; fv[WIRE_DIA1] *= 2.0; fv[WIRE_DIAN] *= 2.0;
419 for( idx = WIRE_X1; idx <= WIRE_RES; idx++ )
420 {
421 spin = GTK_SPIN_BUTTON(
422 lookup_widget(wire_editor, fspin[idx]) );
423 gtk_spin_button_set_value( spin, fv[idx] );
424 }
425 fv[WIRE_DIA] /= 2.0; fv[WIRE_DIA1] /= 2.0; fv[WIRE_DIAN] /= 2.0;
426
427 /* Wait for GTK to complete its tasks */
428 while( g_main_context_iteration(NULL, FALSE) );
429 busy = FALSE;
430
431 } /* Wire_Editor() */
432
433 /*------------------------------------------------------------------------*/
434
435 /* Patch_Editor()
436 *
437 * Handles all actions of the patch editor window
438 */
439 void
Patch_Editor(int action)440 Patch_Editor( int action )
441 {
442 /* For looking up spinbuttons */
443 GtkSpinButton *spin;
444
445 /* For reading/writing to SP/SM & SC rows */
446 static GtkTreeIter
447 iter_sp,
448 iter_sc;
449
450 int idx, idi;
451
452 /* Patch type */
453 static int ptype = PATCH_ARBT;
454
455 /* Integer type data */
456 static gint iv[4];
457
458 /* Float type data */
459 static gdouble fv[14];
460
461 /* Card (row) name */
462 static gchar name[3] = "SP";
463
464 /* Spin button names, int data */
465 gchar *ispin[2] =
466 {
467 "patch_nx_spinbutton",
468 "patch_ny_spinbutton",
469 };
470
471 /* Spin button names, float data */
472 gchar *fspin[12] =
473 {
474 "patch_x1_spinbutton",
475 "patch_y1_spinbutton",
476 "patch_z1_spinbutton",
477 "patch_x2_spinbutton",
478 "patch_y2_spinbutton",
479 "patch_z2_spinbutton",
480 "patch_x3_spinbutton",
481 "patch_y3_spinbutton",
482 "patch_z3_spinbutton",
483 "patch_x4_spinbutton",
484 "patch_y4_spinbutton",
485 "patch_z4_spinbutton",
486 };
487
488 gchar *rbutton[5] =
489 {
490 "patch_arbitrary_radiobutton",
491 "patch_rectangular_radiobutton",
492 "patch_triangular_radiobutton",
493 "patch_quadrilateral_radiobutton",
494 "patch_surface_radiobutton"
495 };
496
497 static gboolean
498 save = FALSE, /* Enable saving of editor data */
499 busy = FALSE, /* Block callbacks. Must be a better way to do this? */
500 ptset = FALSE; /* Set patch type radio buttons */
501
502
503 /* Block callbacks. (Should be a better way to do this) */
504 if( Give_Up( &busy, patch_editor) ) return;
505
506 /* Save data to nec2 editor if appropriate */
507 if( (action & EDITOR_SAVE) && save )
508 {
509 /* Clear data not used in SC card */
510 iv[SPIN_COL_I3] = iv[SPIN_COL_I4] = 0;
511 fv[UNUSED_F1] = fv[UNUSED_F2] = 0.0;
512
513 /* Set SP data to treeview */
514 Set_Geometry_Data( geom_store, &iter_sp, iv, fv );
515
516 /* Set SC card data to treeview if non arbitrary */
517 if( ptype != PATCH_ARBT )
518 Set_Geometry_Data(geom_store,
519 &iter_sc, &iv[SPIN_COL_I3], &fv[PATCH_X3]);
520
521 save = FALSE;
522 } /* if( (action & EDITOR_SAVE) && save ) */
523
524 /* Set int data from the patch editor (SP card) */
525 if( ptype != PATCH_SURF )
526 {
527 iv[SPIN_COL_I1] = 0; /* Not used in SP */
528 iv[SPIN_COL_I2] = ptype; /* Patch type */
529 }
530 /* Read int data from the patch editor (SM card) */
531 else for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
532 {
533 spin = GTK_SPIN_BUTTON(
534 lookup_widget(patch_editor, ispin[idi]) );
535 double i = gtk_spin_button_get_value( spin );
536 iv[idi] = (gint)i;
537 }
538
539 /* Read float data from the patch editor */
540 for( idx = PATCH_X1; idx <= PATCH_Z2; idx++ )
541 {
542 spin = GTK_SPIN_BUTTON(
543 lookup_widget(patch_editor, fspin[idx]) );
544 fv[idx] = gtk_spin_button_get_value( spin );
545 }
546 for( idx = PATCH_X3; idx <= PATCH_Z4; idx++ )
547 {
548 spin = GTK_SPIN_BUTTON(
549 lookup_widget(patch_editor, fspin[idx-1]) );
550 fv[idx] = gtk_spin_button_get_value( spin );
551 }
552
553 /* Respond to user action */
554 switch( action )
555 {
556 case EDITOR_NEW: /* New patch to edit, enter some default data */
557 /* Insert a default GE card if list is empty */
558 Insert_GE_Card( geom_store, &iter_sp );
559
560 /* Insert a new blank SP row after a selected row,
561 * if any, otherwise before the last (GE) row */
562 Insert_Blank_Geometry_Row(
563 geom_treeview, geom_store, &iter_sp, name );
564
565 /* Insert an SC card for non-arbitrary patch */
566 if( ptype != PATCH_ARBT )
567 Insert_Blank_Geometry_Row(
568 geom_treeview, geom_store, &iter_sc, "SC" );
569
570 /* Scroll tree view to bottom */
571 gtk_adjustment_set_value(
572 geom_adjustment, geom_adjustment->upper );
573 ptset = TRUE;
574 break;
575
576 case EDITOR_EDIT: /* Edit a selected geometry row */
577 /* Get selected row */
578 Get_Selected_Row(
579 geom_treeview, geom_store, &iter_sp, name );
580 iter_sc = iter_sp;
581
582 /*** Editing an SC card ***/
583 if( strcmp(name, "SC") == 0 )
584 {
585 /* Get patch data from SC row in tree view */
586 Get_Geometry_Data( geom_store, &iter_sc,
587 &iv[SPIN_COL_I3], &fv[PATCH_X3] );
588
589 /* Check for a preceding SP | SM card.
590 * If card is SP, get patch data */
591 if( Check_Card_Name(geom_store, &iter_sp, PREVIOUS, "SP") )
592 {
593 Get_Geometry_Data( geom_store, &iter_sp, iv, fv );
594 ptype = iv[SPIN_COL_I2];
595
596 /* Warn user if SP card with arbitrary
597 * patch is followed by an SC card */
598 if( ptype == PATCH_ARBT )
599 stop( _("SC card preceded by SP card\n"\
600 "with arbitrary patch type"), ERR_OK );
601
602 } /* if( Check_Card_Name(geom_store, &iter_sp, PREVIOUS, "SP") ) */
603 else /* Look for a previous SM card */
604 {
605 iter_sp = iter_sc;
606 if( Check_Card_Name(geom_store, &iter_sp, PREVIOUS, "SM") )
607 {
608 Get_Geometry_Data( geom_store, &iter_sp, iv, fv );
609 ptype = PATCH_SURF;
610 }
611 else stop( _("No SP or SM card before SC card"), ERR_OK );
612 }
613 } /* if( strcmp(name, "SC") == 0 ) */
614 /*** Editing an SP|SM card ***/
615 else if( strcmp(name, "SP") == 0 )
616 {
617 /* Get patch data from treeview */
618 Get_Geometry_Data( geom_store, &iter_sp, iv, fv );
619 ptype = iv[SPIN_COL_I2];
620
621 /*** Get SC card data if patch type non-arbitrary ***/
622 if( ptype != PATCH_ARBT )
623 {
624 /* If next card is SC, get data */
625 if( Check_Card_Name(geom_store, &iter_sc, NEXT, "SC") )
626 Get_Geometry_Data( geom_store, &iter_sc,
627 &iv[SPIN_COL_I3], &fv[PATCH_X3] );
628 else
629 {
630 ptype = PATCH_ARBT;
631 stop( _("No SC card after an SP card\n"\
632 "with non-arbitrary patch type"), ERR_OK );
633 }
634
635 } /* if( ptype != PATCH_ARBT ) */
636 /* If patch type arbitrary, no SC card should follow */
637 else if( Check_Card_Name(geom_store, &iter_sc, NEXT, "SC") )
638 stop( _("SC card follows an SP card\n"\
639 "with arbitrary patch type"), ERR_OK );
640 } /* if( strcmp(name, "SP") == 0 ) */
641 else /* SM card */
642 {
643 /* Get patch data from treeview */
644 Get_Geometry_Data( geom_store, &iter_sp, iv, fv );
645 ptype = PATCH_SURF;
646
647 /* If next card is SC, get data */
648 if( Check_Card_Name(geom_store, &iter_sc, NEXT, "SC") )
649 Get_Geometry_Data( geom_store, &iter_sc,
650 &iv[SPIN_COL_I3], &fv[PATCH_X3] );
651 else stop( _("No SC card after an SM card"), ERR_OK );
652
653 } /* if( strcmp(name, "SP") == 0 ) */
654
655 ptset = TRUE;
656 break;
657
658 case EDITOR_CANCEL: /* Cancel patch editor */
659 /* Remove cards */
660 Remove_Row( geom_store, &iter_sp );
661 if( ptype != PATCH_ARBT )
662 Remove_Row( geom_store, &iter_sc );
663 save = busy = FALSE;
664 return;
665
666 case EDITOR_DATA: /* Some editor data changed */
667 save = TRUE;
668 break;
669
670 case PATCH_EDITOR_ARBT: /* Arbitary-shaped patch */
671 ptype = PATCH_ARBT;
672 ptset = FALSE;
673 save = TRUE;
674 for( idx = PATCH_X3; idx <= UNUSED_F2; idx++ )
675 fv[idx] = 0.0;
676
677 /* Remove SC card */
678 Remove_Row( geom_store, &iter_sc );
679 break;
680
681 case PATCH_EDITOR_RECT: /* Rectangular patch */
682 ptype = PATCH_RECT;
683 ptset = FALSE;
684 save = TRUE;
685 for( idx = PATCH_X4; idx <= UNUSED_F2; idx++ )
686 fv[idx] = 0.0;
687 break;
688
689 case PATCH_EDITOR_TRIA: /* Triangular patch */
690 ptype = PATCH_TRIA;
691 ptset = FALSE;
692 save = TRUE;
693 for( idx = PATCH_X4; idx <= UNUSED_F2; idx++ )
694 fv[idx] = 0.0;
695 break;
696
697 case PATCH_EDITOR_QUAD: /* Quadrilateral patch */
698 ptype = PATCH_QUAD;
699 ptset = FALSE;
700 save = TRUE;
701 break;
702
703 case PATCH_EDITOR_SURF: /* Multi-patch surface */
704 iv[SPIN_COL_I1] = iv[SPIN_COL_I2] = 8;
705 ptype = PATCH_SURF;
706 ptset = FALSE;
707 save = TRUE;
708 break;
709
710 case PATCH_EDITOR_SCCD: /* Insert SC card (non-arbitrary patch case) */
711 if( gtk_list_store_iter_is_valid( geom_store, &iter_sp) )
712 Insert_Blank_Geometry_Row(
713 geom_treeview, geom_store, &iter_sc, "SC");
714
715 } /* switch( action ) */
716
717 /* Change labels as needed */
718 if( ptype == PATCH_ARBT )
719 {
720 gtk_label_set_text( GTK_LABEL(
721 lookup_widget(patch_editor, "patch_x1_label")), _("Center - X") );
722 gtk_label_set_text( GTK_LABEL(
723 lookup_widget(patch_editor, "patch_y1_label")), _("Center - Y") );
724 gtk_label_set_text( GTK_LABEL(
725 lookup_widget(patch_editor, "patch_z1_label")), _("Center - Z") );
726 gtk_label_set_text( GTK_LABEL(
727 lookup_widget(patch_editor, "patch_x2_label")), _("Normal - Elev.") );
728 gtk_label_set_text( GTK_LABEL(
729 lookup_widget(patch_editor, "patch_y2_label")), _("Normal - Azim.") );
730 gtk_label_set_text( GTK_LABEL(
731 lookup_widget(patch_editor, "patch_z2_label")), _("Patch Area") );
732 }
733 else
734 {
735 gtk_label_set_text( GTK_LABEL(
736 lookup_widget(patch_editor, "patch_x1_label")), _("Corner 1 - X") );
737 gtk_label_set_text( GTK_LABEL(
738 lookup_widget(patch_editor, "patch_y1_label")), _("Corner 1 - Y") );
739 gtk_label_set_text( GTK_LABEL(
740 lookup_widget(patch_editor, "patch_z1_label")), _("Corner 1 - Z") );
741 gtk_label_set_text( GTK_LABEL(
742 lookup_widget(patch_editor, "patch_x2_label")), _("Corner 2 - X") );
743 gtk_label_set_text( GTK_LABEL(
744 lookup_widget(patch_editor, "patch_y2_label")), _("Corner 2 - Y") );
745 gtk_label_set_text( GTK_LABEL(
746 lookup_widget(patch_editor, "patch_z2_label")), _("Corner 2 - Z") );
747 }
748
749 /* Hide/Show parts of window as needed */
750 switch( ptype )
751 {
752 case PATCH_ARBT: /* Arbitary shaped patch */
753 gtk_widget_hide( lookup_widget(patch_editor, "patch_sc_frame") );
754 gtk_widget_hide( lookup_widget(patch_editor, "patch_sm_frame") );
755 gtk_window_resize( GTK_WINDOW(patch_editor), 10, 10 );
756 break;
757
758 case PATCH_RECT: /* Rectangular patch */
759 gtk_widget_show( lookup_widget(patch_editor, "patch_sc_frame") );
760 gtk_widget_hide( lookup_widget(patch_editor, "patch_sc_table") );
761 gtk_widget_hide( lookup_widget(patch_editor, "patch_sm_frame") );
762 gtk_window_resize( GTK_WINDOW(patch_editor), 10, 10 );
763 break;
764
765 case PATCH_TRIA: /* Triangular patch */
766 gtk_widget_show( lookup_widget(patch_editor, "patch_sc_frame") );
767 gtk_widget_hide( lookup_widget(patch_editor, "patch_sc_table") );
768 gtk_widget_hide( lookup_widget(patch_editor, "patch_sm_frame") );
769 gtk_window_resize( GTK_WINDOW(patch_editor), 10, 10 );
770 break;
771
772 case PATCH_QUAD: /* Quadrilateral patch */
773 gtk_widget_show( lookup_widget(patch_editor, "patch_sc_frame") );
774 gtk_widget_show( lookup_widget(patch_editor, "patch_sc_table") );
775 gtk_widget_hide( lookup_widget(patch_editor, "patch_sm_frame") );
776 gtk_window_resize( GTK_WINDOW(patch_editor), 10, 10 );
777 break;
778
779 case PATCH_SURF: /* Multi-patch surface */
780 gtk_widget_show( lookup_widget(patch_editor, "patch_sm_frame") );
781 gtk_widget_show( lookup_widget(patch_editor, "patch_sc_frame") );
782 gtk_widget_hide( lookup_widget(patch_editor, "patch_sc_table") );
783 gtk_window_resize( GTK_WINDOW(patch_editor), 10, 10 );
784
785 } /* switch( ptype ) */
786
787 /* Set patch type radio button */
788 if( ptset )
789 {
790 ptset = FALSE;
791 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(
792 lookup_widget(patch_editor, rbutton[ptype])), TRUE );
793 }
794
795 /* Set card name */
796 Strlcpy( name, (ptype == PATCH_SURF ? "SM" : "SP"), sizeof(name) );
797 if( gtk_list_store_iter_is_valid(geom_store, &iter_sp) && save )
798 gtk_list_store_set( geom_store, &iter_sp, GEOM_COL_NAME, name, -1 );
799
800 /* Write int data for SM card */
801 if( ptype == PATCH_SURF )
802 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
803 {
804 spin = GTK_SPIN_BUTTON( lookup_widget(patch_editor, ispin[idi]) );
805 gtk_spin_button_set_value( spin, iv[idi] );
806 }
807
808 /* Write float data to the patch editor */
809 for( idx = PATCH_X1; idx <= PATCH_Z2; idx++ )
810 {
811 spin = GTK_SPIN_BUTTON( lookup_widget(patch_editor, fspin[idx]) );
812 gtk_spin_button_set_value( spin, fv[idx] );
813 }
814 for( idx = PATCH_X3; idx <= PATCH_Z4; idx++ )
815 {
816 spin = GTK_SPIN_BUTTON( lookup_widget(patch_editor, fspin[idx-1]) );
817 gtk_spin_button_set_value( spin, fv[idx] );
818 }
819
820 /* Wait for GTK to complete its tasks */
821 while( g_main_context_iteration(NULL, FALSE) );
822 busy = FALSE;
823
824 } /* Patch_Editor() */
825
826 /*------------------------------------------------------------------------*/
827
828 /* Arc_Editor()
829 *
830 * Handles all actions of the arc editor window
831 */
832
833 void
Arc_Editor(int action)834 Arc_Editor( int action )
835 {
836 /* For looking up spinbuttons */
837 GtkSpinButton *spin;
838
839 /* For reading/writing to GA rows */
840 static GtkTreeIter iter_ga;
841
842 int idx, idi;
843
844 static gboolean
845 load = FALSE, /* Enable wire loading (conductivity specified) */
846 newpcl = TRUE, /* New percent-of-lambda value */
847 save = FALSE, /* Enable saving of editor data */
848 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
849
850 /* Float type data */
851 static gdouble fv[7] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
852
853 /* Wire conductivity */
854 static gdouble s = 0.0;
855
856 /* Integer type data */
857 static gint iv[2];
858
859 /* Card (row) name */
860 gchar name[3];
861
862 /* Spin button names, int & float data */
863 gchar *ispin[2] =
864 {
865 "arc_tagnum_spinbutton",
866 "arc_numseg_spinbutton"
867 };
868
869 gchar *fspin[6] =
870 {
871 "arc_rad_spinbutton",
872 "arc_end1_spinbutton",
873 "arc_end2_spinbutton",
874 "arc_dia_spinbutton",
875 "arc_pcl_spinbutton",
876 "arc_res_spinbutton"
877 };
878
879
880 /* Block callbacks. (Should be a better way to do this) */
881 if( Give_Up( &busy, arc_editor) ) return;
882
883 /* Save data to nec2 editor if appropriate */
884 if( (action & EDITOR_SAVE) && save )
885 {
886 Set_Geometry_Data( geom_store, &iter_ga, iv, fv );
887
888 /* Set wire conductivity (loading card) */
889 if( load )
890 Set_Wire_Conductivity( iv[SPIN_COL_I1], s, cmnd_store );
891
892 save = load = FALSE;
893 } /* if( (action & EDITOR_SAVE) && save ) */
894
895 /* Read int data from the arc editor */
896 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
897 {
898 spin = GTK_SPIN_BUTTON( lookup_widget(arc_editor, ispin[idi]) );
899 iv[idi] = gtk_spin_button_get_value_as_int( spin );
900 }
901
902 /* Read float data from the arc editor */
903 for( idx = ARC_RAD; idx <= ARC_PCL; idx++ )
904 {
905 spin = GTK_SPIN_BUTTON( lookup_widget(arc_editor, fspin[idx]) );
906 fv[idx] = gtk_spin_button_get_value( spin );
907 }
908 fv[ARC_DIA] /= 2.0;
909
910 /* Get wire conductivity */
911 spin = GTK_SPIN_BUTTON( lookup_widget(arc_editor, fspin[idx]) );
912 s = gtk_spin_button_get_value( spin );
913
914 /* Respond to user action */
915 switch( action )
916 {
917 case EDITOR_NEW: /* New arc row to create */
918 /* Insert a default GE card if list is empty */
919 Insert_GE_Card( geom_store, &iter_ga );
920
921 /* Insert a new blank GA row after a selected row,
922 * if any, otherwise before the last (GE) row */
923 Insert_Blank_Geometry_Row(
924 geom_treeview, geom_store, &iter_ga, "GA");
925
926 /* Some default values */
927 iv[SPIN_COL_I1] = ++gbl_tag_num;
928 spin = GTK_SPIN_BUTTON(
929 lookup_widget(arc_editor, ispin[SPIN_COL_I1]));
930 gtk_spin_button_set_value( spin, iv[SPIN_COL_I1] );
931
932 /* Scroll tree view to bottom */
933 gtk_adjustment_set_value(
934 geom_adjustment, geom_adjustment->upper);
935 break;
936
937 case EDITOR_EDIT: /* Edit an arc row (GA) selected in treeview */
938 /* Get selected row */
939 Get_Selected_Row(
940 geom_treeview, geom_store, &iter_ga, name );
941
942 /* Get arc data from tree view */
943 Get_Geometry_Data(
944 geom_store, &iter_ga, iv, fv );
945
946 /* Get wire conductivity if specified in LD card */
947 Get_Wire_Conductivity(iv[SPIN_COL_I1], &s, cmnd_store);
948 break;
949
950 case EDITOR_CANCEL: /* Cancel arc editor */
951 /* Remove cards */
952 Remove_Row( geom_store, &iter_ga );
953 save = busy = FALSE;
954 return;
955
956 case EDITOR_DATA: /* Some data changed in editor window */
957 save = TRUE;
958 break;
959
960 case EDITOR_LOAD: /* Wire conductivity specified */
961 spin = GTK_SPIN_BUTTON( lookup_widget(
962 arc_editor, fspin[SPIN_COL_F6]) );
963 s = gtk_spin_button_get_value( spin );
964 if( s > 0.0 )
965 {
966 save = TRUE;
967 load = TRUE;
968 }
969 else load = FALSE;
970 break;
971
972 case EDITOR_TAGNUM: /* Tag number edited by user */
973 gbl_tag_num = iv[SPIN_COL_I1];
974 save = TRUE;
975 if( s > 0.0 ) load = TRUE;
976 break;
977
978 case EDITOR_SEGPC: /* Segment length as % of smallest wavelength */
979 /* Calculate num of segs for given % of lambda */
980 if( calc_data.mxfrq != 0.0 )
981 {
982 gdouble len = fv[ARC_RAD] *
983 (gdouble)fabs( fv[ARC_END1]-fv[ARC_END2] )/(gdouble)TD;
984 double i = ceil(100.0 / fv[ARC_PCL] *
985 len /((gdouble)CVEL/(gdouble)calc_data.mxfrq));
986 iv[SPIN_COL_I2] = (gint)i;
987 }
988 newpcl = FALSE;
989 save = TRUE;
990
991 } /* switch( action ) */
992
993 /*** Calculate seg length as % of smallest wavelength ***/
994 if( (calc_data.mxfrq != 0.0) && newpcl )
995 {
996 gdouble len = fv[ARC_RAD] *
997 (gdouble)fabs( fv[ARC_END1]-fv[ARC_END2] )/(gdouble)TD;
998 fv[ARC_PCL] = 100.0 * (len/(gdouble)iv[SPIN_COL_I2]) /
999 ((gdouble)CVEL/(gdouble)calc_data.mxfrq);
1000 }
1001 else newpcl = TRUE;
1002
1003 /* Write int data to the arc editor */
1004 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1005 {
1006 spin = GTK_SPIN_BUTTON(
1007 lookup_widget(arc_editor, ispin[idi]) );
1008 gtk_spin_button_set_value( spin, iv[idi] );
1009 }
1010
1011 /* Write float data to the arc editor (F1 to F4 & pcl/resistance) */
1012 fv[ARC_DIA] *= 2.0;
1013 for( idx = ARC_RAD; idx <= ARC_PCL; idx++ )
1014 {
1015 spin = GTK_SPIN_BUTTON(
1016 lookup_widget(arc_editor, fspin[idx]) );
1017 gtk_spin_button_set_value( spin, fv[idx] );
1018 }
1019 fv[ARC_DIA] /= 2.0;
1020
1021 spin = GTK_SPIN_BUTTON(
1022 lookup_widget(arc_editor, fspin[idx]) );
1023 gtk_spin_button_set_value( spin, s );
1024
1025 /* Wait for GTK to complete its tasks */
1026 while( g_main_context_iteration(NULL, FALSE) );
1027 busy = FALSE;
1028
1029 } /* Arc_Editor() */
1030
1031 /*------------------------------------------------------------------------*/
1032
1033 /* Helix_Editor()
1034 *
1035 * Handles all actions of the helix editor window
1036 */
1037
1038 void
Helix_Editor(int action)1039 Helix_Editor( int action )
1040 {
1041 /* For looking up spinbuttons */
1042 GtkSpinButton *spin;
1043
1044 /* For reading/writing to GH rows */
1045 static GtkTreeIter iter_gh;
1046
1047 gint idx, idi;
1048 gdouble ftmp;
1049
1050 static gboolean
1051 load = FALSE, /* Enable wire loading (conductivity specified) */
1052 linkall = TRUE, /* Link all radius spinbuttons */
1053 linkzo = FALSE, /* Link X, Y @ Z=0 spinbuttons */
1054 linkzhl = FALSE, /* Link X, Y @ Z=HL spinbuttons */
1055 helixlh = FALSE, /* Specify a left hand helix */
1056 newpcl = TRUE, /* New percent-of-lambda value */
1057 newspc = TRUE, /* New percent-of-lambda value */
1058 save = FALSE, /* Enable saving of editor data */
1059 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
1060
1061 /* Float type data, wire conductivity */
1062 static gdouble fv[10], s = 0.0;
1063
1064 /* Integer type data */
1065 static gint iv[2];
1066
1067 /* Card (row) name */
1068 gchar name[3];
1069
1070 /* Spin button names, int & float data */
1071 gchar *ispin[2] =
1072 {
1073 "helix_tagnum_spinbutton",
1074 "helix_numseg_spinbutton"
1075 };
1076
1077 gchar *fspin[10] =
1078 {
1079 "helix_tspace_spinbutton",
1080 "helix_len_spinbutton",
1081 "helix_radxzo_spinbutton",
1082 "helix_radyzo_spinbutton",
1083 "helix_radxzhl_spinbutton",
1084 "helix_radyzhl_spinbutton",
1085 "helix_dia_spinbutton",
1086 "helix_pcl_spinbutton",
1087 "helix_nturns_spinbutton",
1088 "helix_res_spinbutton"
1089 };
1090
1091
1092 /* Block callbacks. (Should be a better way to do this) */
1093 if( Give_Up( &busy, helix_editor) ) return;
1094
1095 /* Save data to nec2 editor if appropriate */
1096 if( (action & EDITOR_SAVE) && save )
1097 {
1098 /* Change seg/turn to total number of segs */
1099 gint tmp = iv[SPIN_COL_I2];
1100 double i = ceil( (gdouble)iv[SPIN_COL_I2] * fv[HELIX_NTURN] );
1101 iv[SPIN_COL_I2] = (gint)i;
1102
1103 /* Change to left hand helix */
1104 if( helixlh )
1105 fv[HELIX_LEN] = -fv[HELIX_LEN];
1106
1107 Set_Geometry_Data( geom_store, &iter_gh, iv, fv );
1108
1109 /* Change back */
1110 iv[SPIN_COL_I2] = tmp;
1111 fv[HELIX_LEN] = fabs( fv[HELIX_LEN] );
1112
1113 /* Set wire conductivity (loading card) */
1114 if( load )
1115 Set_Wire_Conductivity( iv[SPIN_COL_I1], s, cmnd_store );
1116
1117 save = load = FALSE;
1118 } /* if( (action & EDITOR_SAVE) && save ) */
1119
1120 /* Read int data from the helix editor */
1121 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1122 {
1123 spin = GTK_SPIN_BUTTON(
1124 lookup_widget(helix_editor, ispin[idi]) );
1125 iv[idi] = gtk_spin_button_get_value_as_int( spin );
1126 }
1127 /* Read float data from the helix editor */
1128 for( idx = HELIX_TSPACE; idx <= HELIX_RES; idx++ )
1129 {
1130 spin = GTK_SPIN_BUTTON(
1131 lookup_widget(helix_editor, fspin[idx]) );
1132 fv[idx] = gtk_spin_button_get_value( spin );
1133 }
1134 fv[HELIX_DIA] /= 2.0;
1135
1136 /* Link all radius spinbuttons to X @ Z=0 */
1137 if( linkall )
1138 fv[HELIX_RYZO] = fv[HELIX_RXZHL] = fv[HELIX_RYZHL] = fv[HELIX_RXZO];
1139
1140 /* Link X, Y @ Z=0 spinbuttons */
1141 if( linkzo )
1142 fv[HELIX_RYZO] = fv[HELIX_RXZO];
1143
1144 /* Link X, Y @ Z=0 spinbuttons */
1145 if( linkzhl )
1146 fv[HELIX_RYZHL] = fv[HELIX_RXZHL];
1147
1148 /* Respond to user action */
1149 switch( action )
1150 {
1151 case EDITOR_NEW: /* New helix row to create */
1152 /* Insert a default GE card if list is empty */
1153 Insert_GE_Card( geom_store, &iter_gh );
1154
1155 /* Insert a new blank GH row after a selected row,
1156 * if any, otherwise before the last (GE) row */
1157 Insert_Blank_Geometry_Row(
1158 geom_treeview, geom_store, &iter_gh, "GH");
1159
1160 /* Some default values */
1161 iv[SPIN_COL_I1] = ++gbl_tag_num;
1162 spin = GTK_SPIN_BUTTON( lookup_widget(
1163 helix_editor, ispin[SPIN_COL_I1]) );
1164 gtk_spin_button_set_value( spin, iv[SPIN_COL_I1] );
1165
1166 /* Scroll tree view to bottom */
1167 gtk_adjustment_set_value(
1168 geom_adjustment, geom_adjustment->upper);
1169 break;
1170
1171 case EDITOR_EDIT: /* Edit a helix row (GH) */
1172 /* Get selected row */
1173 Get_Selected_Row( geom_treeview, geom_store, &iter_gh, name );
1174
1175 /* Get helix data from tree view */
1176 Get_Geometry_Data( geom_store, &iter_gh, iv, fv );
1177
1178 /* Get wire conductivity if specified in LD card */
1179 Get_Wire_Conductivity(iv[SPIN_COL_I1], &s, cmnd_store);
1180 fv[HELIX_RES] = s;
1181
1182 /* Set LH/RH helix check button */
1183 {
1184 GtkToggleButton *toggle =
1185 GTK_TOGGLE_BUTTON( lookup_widget(
1186 helix_editor, "helix_lh_checkbutton") );
1187 if( fv[HELIX_LEN] < 0.0 )
1188 gtk_toggle_button_set_active( toggle, TRUE );
1189 else
1190 gtk_toggle_button_set_active( toggle, FALSE );
1191 }
1192
1193 /* If left hand helix */
1194 fv[HELIX_LEN] = fabs( fv[HELIX_LEN] );
1195
1196 /* Change to number of segs/turn */
1197 fv[HELIX_NTURN] = fv[HELIX_LEN] / fv[HELIX_TSPACE];
1198 iv[SPIN_COL_I2] =
1199 (gint)((gdouble)iv[SPIN_COL_I2] / fv[HELIX_NTURN]);
1200 break;
1201
1202 case EDITOR_CANCEL: /* Cancel helix editor */
1203 /* Remove cards */
1204 Remove_Row( geom_store, &iter_gh );
1205 save = busy = FALSE;
1206 return;
1207
1208 case EDITOR_DATA: /* Some data changed in editor window */
1209 save = TRUE;
1210 break;
1211
1212 case EDITOR_LOAD: /* Wire conductivity specified */
1213 spin = GTK_SPIN_BUTTON(lookup_widget(
1214 helix_editor, fspin[HELIX_RES]));
1215 s = gtk_spin_button_get_value( spin );
1216 if( s > 0.0 )
1217 {
1218 save = TRUE;
1219 load = TRUE;
1220 }
1221 else load = FALSE;
1222 break;
1223
1224 case EDITOR_TAGNUM: /* Tag number edited by user */
1225 gbl_tag_num = iv[SPIN_COL_I1];
1226 save = TRUE;
1227 if( s > 0.0 ) load = TRUE;
1228 break;
1229
1230 case HELIX_EDITOR_LH: /* Left hand helix */
1231 helixlh = TRUE;
1232 save = TRUE;
1233 break;
1234
1235 case HELIX_EDITOR_RH: /* Right hand helix */
1236 helixlh = FALSE;
1237 save = TRUE;
1238 break;
1239
1240 case HELIX_EDITOR_LINKALL: /* Link all radius spinbuttons */
1241 linkall = TRUE;
1242 linkzo = linkzhl = FALSE;
1243 break;
1244
1245 case HELIX_EDITOR_LINKZO: /* Link X, Y @ Z=0 spinbuttons */
1246 linkzo = TRUE;
1247 linkall = linkzhl = FALSE;
1248 break;
1249
1250 case HELIX_EDITOR_LINKZHL: /* Link X, Y @ Z=HL spinbuttons */
1251 linkzhl = TRUE;
1252 linkzo = linkall = FALSE;
1253 break;
1254
1255 case HELIX_EDITOR_NTURN: /* New number of turns */
1256 fv[HELIX_TSPACE] = fv[HELIX_LEN] / fv[HELIX_NTURN];
1257 newspc = FALSE;
1258 save = TRUE;
1259 break;
1260
1261 case EDITOR_SEGPC: /* Segment length as % of smallest wavelength */
1262 /* Calculate num of segs for given % of lambda */
1263 if( calc_data.mxfrq != 0.0 )
1264 {
1265 gdouble len, f;
1266
1267 /* Pitch angle of helix, assumes untapered helix */
1268 f = asin( fv[HELIX_TSPACE] / (gdouble)TP / fv[HELIX_RXZO] );
1269
1270 /* Helix turn length */
1271 len = (gdouble)TP * fv[HELIX_RXZO] / (gdouble)cos( f );
1272
1273 /* New number of segments */
1274 double i = ceil(100.0 / fv[HELIX_PCL]*len /
1275 ((gdouble)CVEL / (gdouble)calc_data.mxfrq) );
1276 iv[SPIN_COL_I2] = (gint)i;
1277 }
1278 newpcl = FALSE;
1279 save = TRUE;
1280
1281 } /* switch( action ) */
1282
1283 /*** Calculate seg length as % of smallest wavelength ***/
1284 if( (calc_data.mxfrq != 0.0) && newpcl )
1285 {
1286 gdouble len, f;
1287
1288 /* Pitch angle of helix, assumes untapered helix */
1289 f = asin( fv[HELIX_TSPACE]/(gdouble)TP/fv[HELIX_RXZO] );
1290
1291 /* Helix turn length */
1292 len = (gdouble)TP * fv[HELIX_RXZO] / (gdouble)cos( f );
1293
1294 fv[HELIX_PCL] = 100.0 * (len/(gdouble)iv[SPIN_COL_I2]) /
1295 ((gdouble)CVEL / (gdouble)calc_data.mxfrq);
1296 }
1297 else newpcl = TRUE;
1298
1299 /* Calculate new turn spacing */
1300 if( newspc )
1301 fv[HELIX_NTURN] = fv[HELIX_LEN] / fv[HELIX_TSPACE];
1302 else
1303 newspc = TRUE;
1304
1305 /* Write int data to the helix editor */
1306 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1307 {
1308 spin = GTK_SPIN_BUTTON( lookup_widget(
1309 helix_editor, ispin[idi]) );
1310 gtk_spin_button_set_value( spin, iv[idi] );
1311 }
1312
1313 /* Write float data to the helix editor */
1314 ftmp = fv[HELIX_DIA];
1315 fv[HELIX_DIA] *= 2.0;
1316 for( idx = HELIX_TSPACE; idx <= HELIX_RES; idx++ )
1317 {
1318 spin = GTK_SPIN_BUTTON( lookup_widget(
1319 helix_editor, fspin[idx]) );
1320 gtk_spin_button_set_value( spin, fv[idx] );
1321 }
1322 fv[HELIX_DIA] = ftmp;
1323
1324 /* Wait for GTK to complete its tasks */
1325 while( g_main_context_iteration(NULL, FALSE) );
1326 busy = FALSE;
1327
1328 } /* Helix_Editor() */
1329
1330 /*------------------------------------------------------------------------*/
1331
1332 /* Reflect_Editor()
1333 *
1334 * Handles all actions of the reflect editor window
1335 */
1336 void
Reflect_Editor(int action)1337 Reflect_Editor( int action )
1338 {
1339 /* For looking up spinbuttons/checkbuttons */
1340 GtkSpinButton *spin;
1341 GtkToggleButton *toggle;
1342
1343 /* For reading/writing to GX row */
1344 static GtkTreeIter iter_gx;
1345
1346 int idx, ck;
1347
1348 /* Integer type data */
1349 static gint iv[2];
1350
1351 /* Check button names */
1352 gchar *ckbutton[3] =
1353 {
1354 "reflect_z_checkbutton",
1355 "reflect_y_checkbutton",
1356 "reflect_x_checkbutton"
1357 };
1358
1359 /* Card (row) name */
1360 gchar name[3];
1361
1362 static gboolean
1363 save = FALSE, /* Enable saving of editor data */
1364 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
1365
1366
1367 /* Block callbacks. (Should be a better way to do this) */
1368 if( Give_Up( &busy, reflect_editor) ) return;
1369
1370 /* Save data to nec2 editor if appropriate */
1371 if( (action & EDITOR_SAVE) && save )
1372 {
1373 Set_Geometry_Int_Data( geom_store, &iter_gx, iv );
1374 save = FALSE;
1375 } /* if( (action & EDITOR_SAVE) && save ) */
1376
1377 /* Respond to user action */
1378 switch( action )
1379 {
1380 case EDITOR_NEW: /* New reflect row to create */
1381 /* Insert a default GE card if list is empty */
1382 Insert_GE_Card( geom_store, &iter_gx );
1383
1384 /* Insert a new blank GX row after a selected row,
1385 * if any, otherwise before the last (GE) row */
1386 Insert_Blank_Geometry_Row(
1387 geom_treeview, geom_store, &iter_gx, "GX");
1388
1389 /* Scroll tree view to bottom */
1390 gtk_adjustment_set_value(
1391 geom_adjustment, geom_adjustment->upper);
1392 break;
1393
1394 case EDITOR_EDIT: /* Edit a reflect row (GX) selected in treeview */
1395 /* Get selected row */
1396 Get_Selected_Row(
1397 geom_treeview, geom_store, &iter_gx, name );
1398
1399 /* Get reflect data from tree view */
1400 Get_Geometry_Int_Data( geom_store, &iter_gx, iv );
1401
1402 /* Set reflection axes check buttons */
1403 {
1404 ck = iv[SPIN_COL_I2];
1405
1406 for( idx = 0; idx < 3; idx++ )
1407 {
1408 toggle = GTK_TOGGLE_BUTTON(
1409 lookup_widget(reflect_editor, ckbutton[idx]) );
1410 if( ck & 1 )
1411 gtk_toggle_button_set_active( toggle, TRUE );
1412 else
1413 gtk_toggle_button_set_active( toggle, FALSE );
1414 ck /= 10;
1415 }
1416 }
1417
1418 /* Set tag num increment */
1419 spin = GTK_SPIN_BUTTON(
1420 lookup_widget(reflect_editor, "reflect_taginc_spinbutton") );
1421 gtk_spin_button_set_value( spin, iv[SPIN_COL_I1] );
1422 break;
1423
1424 case EDITOR_CANCEL: /* Cancel reflect editor */
1425 /* Remove cards */
1426 Remove_Row( geom_store, &iter_gx );
1427 save = busy = FALSE;
1428 return;
1429
1430 case REFLECT_EDITOR_TOGGLE: /* Reflect button toggled */
1431 save = TRUE;
1432 break;
1433
1434 case EDITOR_DATA: /* Some data changed in editor window */
1435 save = TRUE;
1436
1437 } /* switch( action ) */
1438
1439 /* Work out the I2 value needed by GX card */
1440 ck = 1; iv[SPIN_COL_I2] = 0;
1441 for( idx = 0; idx < 3; idx++ )
1442 {
1443 toggle = GTK_TOGGLE_BUTTON(
1444 lookup_widget(reflect_editor, ckbutton[idx]) );
1445 if( gtk_toggle_button_get_active(toggle) )
1446 iv[SPIN_COL_I2] += ck;
1447 ck *= 10;
1448 }
1449
1450 /* Read tag inc from the reflect editor */
1451 spin = GTK_SPIN_BUTTON(
1452 lookup_widget(reflect_editor,
1453 "reflect_taginc_spinbutton") );
1454 iv[SPIN_COL_I1] = gtk_spin_button_get_value_as_int( spin );
1455
1456 /* Wait for GTK to complete its tasks */
1457 while( g_main_context_iteration(NULL, FALSE) );
1458 busy = FALSE;
1459
1460 } /* Reflection_Editor() */
1461
1462 /*------------------------------------------------------------------------*/
1463
1464 /* Scale_Editor()
1465 *
1466 * Handles all actions of the scale editor window
1467 */
1468 void
Scale_Editor(int action)1469 Scale_Editor( int action )
1470 {
1471 /* For looking up spinbuttons */
1472 GtkSpinButton *spin;
1473
1474 /* For reading/writing to GS row */
1475 static GtkTreeIter iter_gs;
1476
1477 /* Integer type data */
1478 static gint iv[2];
1479
1480 /* Spin button names, int data */
1481 gchar *ispin[2] =
1482 {
1483 "scale_from_spinbutton",
1484 "scale_to_spinbutton"
1485 };
1486
1487 int idx, idi;
1488
1489 /* Scale factor */
1490 static gdouble scale = 1.0;
1491
1492 /* Card (row) name, strings for convertions */
1493 gchar name[3], sf[13], *str;
1494
1495 static gboolean
1496 save = FALSE, /* Enable saving of editor data */
1497 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
1498
1499
1500 /* Block callbacks. (Should be a better way to do this) */
1501 if( Give_Up( &busy, scale_editor) ) return;
1502
1503 /* Save data to nec2 editor if appropriate */
1504 if( (action & EDITOR_SAVE) && save )
1505 {
1506 /* Clear all GS columns */
1507 for( idx = GEOM_COL_I1; idx <= GEOM_COL_F7; idx++ )
1508 gtk_list_store_set( geom_store, &iter_gs, idx, "0", -1 );
1509
1510 /* Enter tag from-to data */
1511 Set_Geometry_Int_Data( geom_store, &iter_gs, iv );
1512
1513 /* Enter scale factor */
1514 snprintf( sf, sizeof(sf), "%12.5E", scale );
1515 gtk_list_store_set(
1516 geom_store, &iter_gs, GEOM_COL_F1, sf, -1 );
1517
1518 save = FALSE;
1519 } /* if( (action & EDITOR_SAVE) && save ) */
1520
1521 /* Respond to user action */
1522 switch( action )
1523 {
1524 case EDITOR_NEW: /* New scale row to create */
1525 /* Insert a default GE card if list is empty */
1526 Insert_GE_Card( geom_store, &iter_gs );
1527
1528 /* Insert a new blank GS row after a selected row,
1529 * if any, otherwise before the last (GE) row */
1530 Insert_Blank_Geometry_Row(
1531 geom_treeview, geom_store, &iter_gs, "GS");
1532
1533 /* Scroll tree view to bottom */
1534 gtk_adjustment_set_value(
1535 geom_adjustment, geom_adjustment->upper);
1536 save = FALSE;
1537 break;
1538
1539 case EDITOR_EDIT: /* Edit a scale row (GS) selected in treeview */
1540 /* Get selected row */
1541 Get_Selected_Row(
1542 geom_treeview, geom_store, &iter_gs, name );
1543
1544 /* Get tag from-to data from tree view */
1545 Get_Geometry_Int_Data( geom_store, &iter_gs, iv );
1546
1547 /* Get scale data from tree view */
1548 if( gtk_list_store_iter_is_valid(geom_store, &iter_gs) )
1549 {
1550 gtk_tree_model_get( GTK_TREE_MODEL(geom_store),
1551 &iter_gs, GEOM_COL_F1, &str, -1);
1552 scale = Strtod( str, NULL );
1553 g_free( str );
1554 }
1555 else
1556 stop( _("Error reading row data\n"\
1557 "Invalid list iterator"), ERR_OK );
1558
1559 /* Enter tag from-to data to scale editor */
1560 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1561 {
1562 spin = GTK_SPIN_BUTTON(
1563 lookup_widget(scale_editor, ispin[idi]) );
1564 gtk_spin_button_set_value( spin, iv[idi] );
1565 }
1566
1567 /* Set scale factor to scale editor */
1568 spin = GTK_SPIN_BUTTON(
1569 lookup_widget(scale_editor, "scale_factor_spinbutton") );
1570 gtk_spin_button_set_value( spin, scale );
1571 break;
1572
1573 case EDITOR_CANCEL: /* Cancel scale editor */
1574 /* Remove cards */
1575 Remove_Row( geom_store, &iter_gs );
1576 save = busy = FALSE;
1577 return;
1578
1579 case EDITOR_DATA: /* Some data changed in editor window */
1580 /* Read int data from the scale editor */
1581 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1582 {
1583 spin = GTK_SPIN_BUTTON(
1584 lookup_widget(scale_editor, ispin[idi]) );
1585 iv[idi] = gtk_spin_button_get_value_as_int( spin );
1586 }
1587
1588 /* Read scale from the scale editor */
1589 spin = GTK_SPIN_BUTTON(
1590 lookup_widget(scale_editor, "scale_factor_spinbutton") );
1591 scale = gtk_spin_button_get_value( spin );
1592 save = TRUE;
1593
1594 } /* switch( action ) */
1595
1596 /* Wait for GTK to complete its tasks */
1597 while( g_main_context_iteration(NULL, FALSE) );
1598 busy = FALSE;
1599
1600 } /* Scale_Editor() */
1601
1602 /*------------------------------------------------------------------------*/
1603
1604 /* Cylinder_Editor()
1605 *
1606 * Handles all actions of the cylinder editor window
1607 */
1608 void
Cylinder_Editor(int action)1609 Cylinder_Editor( int action )
1610 {
1611 /* For looking up spinbuttons */
1612 GtkSpinButton *spin;
1613
1614 /* For reading/writing to GR row */
1615 static GtkTreeIter iter_gr;
1616
1617 int idi;
1618
1619 /* Integer data (I1 & I2) */
1620 static gint iv[2];
1621
1622 /* Cylinder data spinbuttons */
1623 static gchar *ispin[2] =
1624 {
1625 "cylinder_taginc_spinbutton",
1626 "cylinder_total_spinbutton"
1627 };
1628
1629 /* Card (row) name, strings for convertions */
1630 gchar name[3];
1631
1632 static gboolean
1633 save = FALSE, /* Enable saving of editor data */
1634 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
1635
1636
1637 /* Block callbacks. (Should be a better way to do this) */
1638 if( Give_Up( &busy, cylinder_editor) ) return;
1639
1640 /* Save data to nec2 editor if appropriate */
1641 if( (action & EDITOR_SAVE) && save )
1642 {
1643 Set_Geometry_Int_Data( geom_store, &iter_gr, iv );
1644 save = FALSE;
1645 } /* if( (action & EDITOR_SAVE) && save ) */
1646
1647 /* Respond to user action */
1648 switch( action )
1649 {
1650 case EDITOR_NEW: /* New cylinder row to create */
1651 /* Insert a default GE card if list is empty */
1652 Insert_GE_Card( geom_store, &iter_gr );
1653
1654 /* Insert a new blank GR row after a selected row,
1655 * if any, otherwise before the last (GE) row */
1656 Insert_Blank_Geometry_Row(
1657 geom_treeview, geom_store, &iter_gr, "GR");
1658
1659 /* Scroll tree view to bottom */
1660 gtk_adjustment_set_value(
1661 geom_adjustment, geom_adjustment->upper);
1662 save = TRUE;
1663 break;
1664
1665 case EDITOR_EDIT: /* Edit a cylinder row (GR) selected in treeview */
1666 /* Get selected row */
1667 Get_Selected_Row(
1668 geom_treeview, geom_store, &iter_gr, name);
1669
1670 /* Get integer data from cylinder editor */
1671 Get_Geometry_Int_Data( geom_store, &iter_gr, iv );
1672
1673 /* Write int data to the cylinder editor */
1674 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1675 {
1676 spin = GTK_SPIN_BUTTON(
1677 lookup_widget(cylinder_editor, ispin[idi]));
1678 gtk_spin_button_set_value( spin, iv[idi] );
1679 }
1680 break;
1681
1682 case EDITOR_CANCEL: /* Cancel cylinder editor */
1683 /* Remove cards */
1684 Remove_Row( geom_store, &iter_gr );
1685 save = busy = FALSE;
1686 return;
1687
1688 case EDITOR_DATA: /* Some data changed in editor window */
1689 save = TRUE;
1690
1691 } /* switch( action ) */
1692
1693 /* Read int data from the cylinder editor */
1694 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I2; idi++ )
1695 {
1696 spin = GTK_SPIN_BUTTON(
1697 lookup_widget(cylinder_editor, ispin[idi]));
1698 iv[idi] = gtk_spin_button_get_value_as_int( spin );
1699 }
1700
1701 /* Wait for GTK to complete its tasks */
1702 while( g_main_context_iteration(NULL, FALSE) );
1703 busy = FALSE;
1704
1705 } /* Cylinder_Editor() */
1706
1707 /*------------------------------------------------------------------------*/
1708
1709 /* Transform_Editor()
1710 *
1711 * Handles all actions of the transform editor window
1712 */
1713 void
Transform_Editor(int action)1714 Transform_Editor( int action )
1715 {
1716 /* For looking up spinbuttons */
1717 GtkSpinButton *spin;
1718
1719 /* For reading/writing to GM row */
1720 static GtkTreeIter iter_gm;
1721
1722 int idx, idi, idf;
1723
1724 /* Integer data (I1 to I3) */
1725 static gint iv[3];
1726
1727 /* Float data (F1 to F7) */
1728 static gdouble fv[7];
1729
1730 /* Transform int data spinbuttons */
1731 static gchar *ispin[3] =
1732 {
1733 "transform_taginc_spinbutton",
1734 "transform_new_spinbutton",
1735 "transform_start_spinbutton"
1736 };
1737
1738 /* Transform float data spinbuttons */
1739 static gchar *fspin[6] =
1740 {
1741 "transform_rx_spinbutton",
1742 "transform_ry_spinbutton",
1743 "transform_rz_spinbutton",
1744 "transform_mx_spinbutton",
1745 "transform_my_spinbutton",
1746 "transform_mz_spinbutton"
1747 };
1748
1749 /* Card (row) name, strings for convertions */
1750 gchar name[3];
1751
1752 static gboolean
1753 save = FALSE, /* Enable saving of editor data */
1754 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
1755
1756
1757 /* Block callbacks. (Should be a better way to do this) */
1758 if( Give_Up( &busy, transform_editor) ) return;
1759
1760 /* Save data to nec2 editor if appropriate */
1761 if( (action & EDITOR_SAVE) && save )
1762 {
1763 Set_Geometry_Data( geom_store, &iter_gm, iv, fv );
1764 save = FALSE;
1765 } /* if( (action & EDITOR_SAVE) && save ) */
1766
1767 /* Respond to user action */
1768 switch( action )
1769 {
1770 case EDITOR_NEW: /* New transform row to create */
1771 /* Insert a default GE card if list is empty */
1772 Insert_GE_Card( geom_store, &iter_gm );
1773
1774 /* Insert a new blank GM row after a selected row,
1775 * if any, otherwise before the last (GE) row */
1776 Insert_Blank_Geometry_Row(
1777 geom_treeview, geom_store, &iter_gm, "GM");
1778
1779 /* Scroll tree view to bottom */
1780 gtk_adjustment_set_value(
1781 geom_adjustment, geom_adjustment->upper);
1782 break;
1783
1784 case EDITOR_EDIT: /* Edit transform row (GM) selected in treeview */
1785 /* Get selected row */
1786 Get_Selected_Row(geom_treeview, geom_store, &iter_gm, name);
1787
1788 /* Get integer data from transform editor */
1789 Get_Geometry_Data( geom_store, &iter_gm, iv, fv );
1790
1791 /* Write int data to the transform editor */
1792 iv[SPIN_COL_I3] = (gint)fv[SPIN_COL_F7];
1793 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I3; idi++ )
1794 {
1795 spin = GTK_SPIN_BUTTON(
1796 lookup_widget(transform_editor, ispin[idi]));
1797 gtk_spin_button_set_value( spin, iv[idi] );
1798 }
1799 /* Write float data to the transform editor */
1800 for( idf = SPIN_COL_F1; idf <= SPIN_COL_F6; idf++ )
1801 {
1802 spin = GTK_SPIN_BUTTON(
1803 lookup_widget(transform_editor, fspin[idf]));
1804 gtk_spin_button_set_value( spin, fv[idf] );
1805 }
1806 break;
1807
1808 case EDITOR_CANCEL: /* Cancel transform editor */
1809 /* Remove cards */
1810 Remove_Row( geom_store, &iter_gm );
1811 save = busy = FALSE;
1812 return;
1813
1814 case EDITOR_DATA: /* Some data changed in editor window */
1815 save = TRUE;
1816
1817 } /* switch( action ) */
1818
1819 /* Read int data from the transform editor */
1820 for( idi = SPIN_COL_I1; idi <= SPIN_COL_I3; idi++ )
1821 {
1822 spin = GTK_SPIN_BUTTON(
1823 lookup_widget(transform_editor, ispin[idi]));
1824 iv[idi] = gtk_spin_button_get_value_as_int( spin );
1825 }
1826 /* Read float data from the transform editor */
1827 for( idx = 0; idx < 6; idx++ )
1828 {
1829 spin = GTK_SPIN_BUTTON(
1830 lookup_widget(transform_editor, fspin[idx]));
1831 fv[idx] = gtk_spin_button_get_value( spin );
1832 }
1833 fv[SPIN_COL_F7] = (gdouble)iv[SPIN_COL_I3];
1834
1835 /* Wait for GTK to complete its tasks */
1836 while( g_main_context_iteration(NULL, FALSE) );
1837 busy = FALSE;
1838
1839 } /* Transform_Editor() */
1840
1841 /*------------------------------------------------------------------------*/
1842
1843 /* Gend_Editor()
1844 *
1845 * Edits the GE card
1846 */
1847
1848 void
Gend_Editor(int action)1849 Gend_Editor( int action )
1850 {
1851 /* For reading/writing to GE row */
1852 static GtkTreeIter iter_ge;
1853
1854 /* For checking radio buttons */
1855 GtkToggleButton *toggle;
1856
1857 /* Ground type radio buttons */
1858 #define GE_RDBTN 3
1859 static gchar *rdbutton[GE_RDBTN] =
1860 {
1861 "gend_noimg_radiobutton",
1862 "gend_nognd_radiobutton",
1863 "gend_img_radiobutton"
1864 };
1865
1866 /* Card (row) name, strings for convertions */
1867 gchar name[3], *sv;
1868 static gchar si[6];
1869
1870 int idx;
1871
1872 static gboolean
1873 save = FALSE, /* Enable saving of editor data */
1874 busy = FALSE; /* Block callbacks. Must be a better way to do this? */
1875
1876
1877 /* Block callbacks. (Should be a better way to do this) */
1878 if( Give_Up( &busy, gend_editor) ) return;
1879
1880 /* Save data to nec2 editor if appropriate */
1881 if( (action & EDITOR_SAVE) && save &&
1882 gtk_list_store_iter_is_valid(geom_store, &iter_ge))
1883 {
1884 gtk_list_store_set(
1885 geom_store, &iter_ge, GEOM_COL_I1, si, -1 );
1886 save = FALSE;
1887 } /* if( (action & EDITOR_SAVE) && save ) */
1888
1889 /* Respond to user action */
1890 switch( action )
1891 {
1892 case EDITOR_EDIT: /* Edit geom end row (GE) */
1893 /* Open GE Editor */
1894 if( gend_editor == NULL )
1895 {
1896 gend_editor = create_gend_editor();
1897 gtk_widget_show( gend_editor );
1898 }
1899
1900 /* Get selected row */
1901 Get_Selected_Row( geom_treeview, geom_store, &iter_ge, name );
1902
1903 /* Get integer data from transform editor */
1904 if( gtk_list_store_iter_is_valid(geom_store, &iter_ge) )
1905 {
1906 gtk_tree_model_get( GTK_TREE_MODEL(geom_store),
1907 &iter_ge, GEOM_COL_I1, &sv, -1 );
1908 idx = atoi(sv) + 1;
1909 g_free(sv);
1910 toggle = GTK_TOGGLE_BUTTON( lookup_widget(
1911 gend_editor, rdbutton[idx]) );
1912 gtk_toggle_button_set_active( toggle, TRUE );
1913 }
1914 else stop( _("Error reading row data\n"\
1915 "Invalid list iterator"), ERR_OK );
1916 break;
1917
1918 case EDITOR_CANCEL: /* Cancel transform editor */
1919 /* Remove card */
1920 Remove_Row( geom_store, &iter_ge );
1921 save = busy = FALSE;
1922 return;
1923
1924 case EDITOR_RDBUTTON: /* Radio button toggled in editor window */
1925 /* Test radio buttons */
1926 for( idx = 0; idx < GE_RDBTN; idx++ )
1927 {
1928 toggle = GTK_TOGGLE_BUTTON( lookup_widget(
1929 gend_editor, rdbutton[idx]) );
1930 if( gtk_toggle_button_get_active(toggle) )
1931 break;
1932 }
1933 snprintf( si, sizeof(si), "%5d", idx-1 );
1934 save = TRUE;
1935
1936 } /* switch( action ) */
1937
1938 /* Wait for GTK to complete its tasks */
1939 while( g_main_context_iteration(NULL, FALSE) );
1940 busy = FALSE;
1941
1942 } /* Gend_Editor() */
1943
1944 /*------------------------------------------------------------------------*/
1945
1946 /* Insert_GE_Card()
1947 *
1948 * Inserts a default GE card if missing
1949 */
1950
1951 void
Insert_GE_Card(GtkListStore * store,GtkTreeIter * iter)1952 Insert_GE_Card( GtkListStore *store, GtkTreeIter *iter )
1953 {
1954 gint idx, idi;
1955
1956 /* Insert default GE card if list is clear */
1957 idx = gtk_tree_model_iter_n_children(
1958 GTK_TREE_MODEL(store), NULL );
1959 if( !idx )
1960 {
1961 gtk_list_store_append( store, iter );
1962 gtk_list_store_set( store, iter, GEOM_COL_NAME, "GE", -1 );
1963 for( idi = GEOM_COL_I1; idi < GEOM_NUM_COLS; idi++ )
1964 gtk_list_store_set( store, iter, idi, "0", -1 );
1965 }
1966
1967 } /* Insert_GE_Card() */
1968
1969 /*------------------------------------------------------------------------*/
1970
1971 /* Get_Geometry_Data()
1972 *
1973 * Gets geometry data from a treeview row
1974 */
1975
1976 void
Get_Geometry_Data(GtkListStore * store,GtkTreeIter * iter,int * iv,double * fv)1977 Get_Geometry_Data(
1978 GtkListStore *store,
1979 GtkTreeIter *iter,
1980 int *iv, double *fv )
1981 {
1982 gint idi, idf;
1983 gchar *sv;
1984
1985 /* Get data from tree view (I1,I2, F1-F7)*/
1986 if( gtk_list_store_iter_is_valid(store, iter) )
1987 {
1988 for( idi = GEOM_COL_I1; idi <= GEOM_COL_I2; idi++ )
1989 {
1990 gtk_tree_model_get(
1991 GTK_TREE_MODEL(store), iter, idi, &sv, -1);
1992 iv[idi-GEOM_COL_I1] = atoi(sv);
1993 g_free(sv);
1994 }
1995 for( idf = GEOM_COL_F1; idf <= GEOM_COL_F7; idf++ )
1996 {
1997 gtk_tree_model_get(
1998 GTK_TREE_MODEL(store), iter, idf, &sv, -1);
1999 fv[idf-GEOM_COL_F1] = Strtod( sv, NULL );
2000 g_free(sv);
2001 }
2002 }
2003 else stop( _("Error reading row data\n"\
2004 "Invalid list iterator"), ERR_OK );
2005
2006 } /* Get_Geometry_Data() */
2007
2008 /*------------------------------------------------------------------------*/
2009
2010 /* Get_Geometry_Int_Data()
2011 *
2012 * Gets integer (I1, I2) geometry data from a treeview row
2013 */
2014
2015 void
Get_Geometry_Int_Data(GtkListStore * store,GtkTreeIter * iter,int * iv)2016 Get_Geometry_Int_Data( GtkListStore *store, GtkTreeIter *iter, int *iv )
2017 {
2018 gint idi;
2019 gchar *sv;
2020
2021 /* Get data from tree view (I1, I2) */
2022 if( gtk_list_store_iter_is_valid(store, iter) )
2023 {
2024 for( idi = GEOM_COL_I1; idi <= GEOM_COL_I2; idi++ )
2025 {
2026 gtk_tree_model_get(
2027 GTK_TREE_MODEL(store), iter, idi, &sv, -1);
2028 iv[idi-GEOM_COL_I1] = atoi(sv);
2029 g_free(sv);
2030 }
2031 }
2032 else stop( _("Error reading row data\n"\
2033 "Invalid list iterator"), ERR_OK );
2034
2035 } /* Get_Geometry_Int_Data() */
2036
2037 /*------------------------------------------------------------------------*/
2038
2039 /* Set_Geometry_Data()
2040 *
2041 * Sets data into a geometry row
2042 */
2043
2044 void
Set_Geometry_Data(GtkListStore * store,GtkTreeIter * iter,int * iv,double * fv)2045 Set_Geometry_Data(
2046 GtkListStore *store,
2047 GtkTreeIter *iter,
2048 int *iv, double *fv )
2049 {
2050 gchar str[13];
2051 gint idi, idf;
2052
2053 /* Format and set editor data to treeview (I1, I2 & F1-F7) */
2054 if( gtk_list_store_iter_is_valid(store, iter) )
2055 {
2056 for( idi = GEOM_COL_I1; idi <= GEOM_COL_I2; idi++ )
2057 {
2058 snprintf( str, 6, "%5d", iv[idi-GEOM_COL_I1] );
2059 gtk_list_store_set( store, iter, idi, str, -1 );
2060 }
2061
2062 for( idf = GEOM_COL_F1; idf <= GEOM_COL_F7; idf++ )
2063 {
2064 snprintf( str, 13, "%12.5E", fv[idf-GEOM_COL_F1] );
2065 gtk_list_store_set( store, iter, idf, str, -1 );
2066 }
2067 }
2068 else stop( _("Error writing row data\n"\
2069 "Please re-select row"), ERR_OK );
2070
2071 SetFlag( NEC2_EDIT_SAVE );
2072
2073 } /* Set_Geometry_Data() */
2074
2075 /*------------------------------------------------------------------------*/
2076
2077 /* Set_Geometry_Int_Data()
2078 *
2079 * Sets integer (I1, I2) data into a geometry row
2080 */
2081
2082 void
Set_Geometry_Int_Data(GtkListStore * store,GtkTreeIter * iter,int * iv)2083 Set_Geometry_Int_Data( GtkListStore *store, GtkTreeIter *iter, int *iv )
2084 {
2085 gchar str[6];
2086 gint idi, idf;
2087
2088 /* Format and set editor data to treeview (I1, I2) */
2089 if( gtk_list_store_iter_is_valid(store, iter) )
2090 {
2091 for( idi = GEOM_COL_I1; idi <= GEOM_COL_I2; idi++ )
2092 {
2093 snprintf( str, sizeof(str), "%5d", iv[idi-GEOM_COL_I1] );
2094 gtk_list_store_set( store, iter, idi, str, -1 );
2095 }
2096
2097 /* Clear unused float columns */
2098 for( idf = GEOM_COL_F1; idf <= GEOM_COL_F7; idf++ )
2099 gtk_list_store_set( store, iter, idf, "0.0", -1 );
2100 }
2101 else stop( _("Error writing row data\n"\
2102 "Please re-select row"), ERR_OK );
2103
2104 SetFlag( NEC2_EDIT_SAVE );
2105
2106 } /* Set_Geometry_Int_Data() */
2107
2108 /*------------------------------------------------------------------------*/
2109
2110 /* Check_Card_Name()
2111 *
2112 * Checks previous or next card's name, returns TRUE on match
2113 */
2114
2115 gboolean
Check_Card_Name(GtkListStore * store,GtkTreeIter * iter,gboolean next,const gchar * name)2116 Check_Card_Name(
2117 GtkListStore *store,
2118 GtkTreeIter *iter,
2119 gboolean next,
2120 const gchar *name )
2121 {
2122 gboolean retv;
2123 char *str;
2124
2125 retv = FALSE;
2126 if( gtk_list_store_iter_is_valid(store, iter) )
2127 {
2128 if( next )
2129 {
2130 if( gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter) )
2131 {
2132 gtk_tree_model_get( GTK_TREE_MODEL(store),
2133 iter, GEOM_COL_NAME, &str, -1);
2134 if( strcmp(name, str) == 0 ) retv = TRUE;
2135 g_free(str);
2136 }
2137 }
2138 else
2139 {
2140 if( gtk_tree_model_iter_previous(GTK_TREE_MODEL(store), iter) )
2141 {
2142 gtk_tree_model_get( GTK_TREE_MODEL(store), iter,
2143 GEOM_COL_NAME, &str, -1);
2144 if( strcmp(name, str) == 0 ) retv = TRUE;
2145 g_free(str);
2146 }
2147 }
2148 }
2149
2150 return( retv );
2151
2152 } /* Check_Card_Name() */
2153
2154 /*------------------------------------------------------------------------*/
2155
2156 /* Give_Up()
2157 *
2158 * Signals functon to abort if busy or no NEC2 editor window
2159 */
2160
2161 gboolean
Give_Up(int * busy,GtkWidget * widget)2162 Give_Up( int *busy, GtkWidget *widget )
2163 {
2164 /* Block callbacks. (Should be a better way to do this) */
2165 if( *busy ) return( TRUE );
2166 *busy = TRUE;
2167
2168 /* Abort if NEC2 editor window is closed */
2169 if( nec2_edit_window == NULL )
2170 {
2171 stop( _("NEC2 editor window not open"), ERR_OK );
2172 gtk_widget_destroy( widget );
2173 *busy = FALSE;
2174 return( TRUE );
2175 }
2176
2177 return( FALSE );
2178
2179 } /* Give_Up() */
2180
2181 /*------------------------------------------------------------------------*/
2182
2183 /* Insert_Blank_Geometry_Row()
2184 *
2185 * Inserts a blank row in a tree view with only its name (GW ... )
2186 */
2187
2188 void
Insert_Blank_Geometry_Row(GtkTreeView * view,GtkListStore * store,GtkTreeIter * iter,const gchar * name)2189 Insert_Blank_Geometry_Row(
2190 GtkTreeView *view, GtkListStore *store,
2191 GtkTreeIter *iter, const gchar *name )
2192 {
2193 GtkTreeSelection *selection;
2194 gboolean retv;
2195 gint n;
2196 gchar *str;
2197
2198 if( nec2_edit_window == NULL )
2199 return;
2200
2201 /* Get selected row, if any */
2202 selection = gtk_tree_view_get_selection( view );
2203 retv = gtk_tree_selection_get_selected(
2204 selection, NULL, iter );
2205
2206 /* If no selected row, insert new row into list
2207 * store before last row, else after the selected row,
2208 * but if this is a GE row, then insert before it */
2209 if( !retv )
2210 {
2211 n = gtk_tree_model_iter_n_children(
2212 GTK_TREE_MODEL(store), NULL );
2213 gtk_tree_model_iter_nth_child(
2214 GTK_TREE_MODEL(store), iter, NULL, n-1 );
2215 gtk_list_store_insert_before( store, iter, iter );
2216 }
2217 else
2218 {
2219 gtk_tree_model_get( GTK_TREE_MODEL(store),
2220 iter, GEOM_COL_NAME, &str, -1 );
2221 if( strcmp(str, "GE") == 0 )
2222 gtk_list_store_insert_before( store, iter, iter );
2223 else
2224 gtk_list_store_insert_after( store, iter, iter );
2225 g_free(str);
2226 }
2227
2228 gtk_list_store_set( store, iter, GEOM_COL_NAME, name, -1 );
2229 for( n = GEOM_COL_I1; n < GEOM_NUM_COLS; n++ )
2230 gtk_list_store_set( store, iter, n, "--", -1 );
2231 gtk_tree_selection_select_iter( selection, iter );
2232
2233 } /* Insert_Blank_Geometry_Row() */
2234
2235 /*------------------------------------------------------------------------*/
2236
2237 /* Remove_Row()
2238 *
2239 * Removes a row and selects previous or next row
2240 */
2241
2242 void
Remove_Row(GtkListStore * store,GtkTreeIter * iter)2243 Remove_Row( GtkListStore *store, GtkTreeIter *iter )
2244 {
2245 if( gtk_list_store_iter_is_valid(store, iter) )
2246 gtk_list_store_remove( store, iter );
2247
2248 } /* Remove_Row() */
2249
2250 /*------------------------------------------------------------------------*/
2251
2252 /* Get_Selected_Row()
2253 *
2254 * Gets the selected row in a tree view
2255 */
2256
2257 gboolean
Get_Selected_Row(GtkTreeView * view,GtkListStore * store,GtkTreeIter * iter,gchar * name)2258 Get_Selected_Row(
2259 GtkTreeView *view,
2260 GtkListStore *store,
2261 GtkTreeIter *iter,
2262 gchar *name )
2263 {
2264 gchar *str;
2265 GtkTreeSelection *selection;
2266
2267 /* Get selected row, if any */
2268 selection = gtk_tree_view_get_selection( view );
2269 if( !gtk_tree_selection_get_selected(selection, NULL, iter) )
2270 return( FALSE );
2271
2272 /* Get row name */
2273 gtk_tree_model_get(
2274 GTK_TREE_MODEL(store), iter, GEOM_COL_NAME, &str, -1);
2275 Strlcpy( name, str, 3 );
2276 g_free( str );
2277
2278 return( TRUE );
2279
2280 } /* Get_Selected_Row() */
2281
2282 /*------------------------------------------------------------------------*/
2283
2284 /* Set_Wire_Conductivity()
2285 *
2286 * Sets the wire conductivity specified in a geometry editor
2287 * (wire, arc, helix) to a loading card (LD row) in commands treview
2288 */
2289
2290 void
Set_Wire_Conductivity(int tag,double s,GtkListStore * store)2291 Set_Wire_Conductivity( int tag, double s, GtkListStore *store )
2292 {
2293 int idx, idi, nchld;
2294 GtkTreeIter iter_ld;
2295 gchar *str, sv[13];
2296
2297 /* Find num of rows and first iter, abort if tree empty */
2298 nchld = gtk_tree_model_iter_n_children(
2299 GTK_TREE_MODEL(store), NULL);
2300 if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter_ld))
2301 return;
2302
2303 /* Look for an LD card with tag number = tag */
2304 for( idx = 0; idx < nchld; )
2305 {
2306 gtk_tree_model_get( GTK_TREE_MODEL(store),
2307 &iter_ld, GEOM_COL_NAME, &str, -1 );
2308
2309 if( strcmp(str, "LD") == 0 )
2310 {
2311 g_free( str );
2312 gtk_tree_model_get( GTK_TREE_MODEL(store),
2313 &iter_ld, GEOM_COL_I2, &str, -1 );
2314 if( atoi( str ) == tag )
2315 {
2316 g_free( str );
2317 break;
2318 }
2319 else g_free( str );
2320 }
2321 else g_free( str );
2322
2323 idx++;
2324 if( !gtk_tree_model_iter_next(
2325 GTK_TREE_MODEL(store), &iter_ld) )
2326 break;
2327
2328 } /* for( idx = 0; idx < nchld; idx++ ) */
2329
2330 /* If not found LD card with tagnum = tag, insert new */
2331 if( idx >= nchld )
2332 {
2333 gtk_tree_model_iter_nth_child(
2334 GTK_TREE_MODEL(store), &iter_ld, NULL, nchld-1 );
2335 gtk_list_store_insert_before( store, &iter_ld, &iter_ld );
2336 gtk_list_store_set(
2337 store, &iter_ld, CMND_COL_NAME, "LD", -1 );
2338
2339 /* Clear rest of LD row */
2340 for( idi = CMND_COL_I1; idi <= CMND_COL_F6; idi++ )
2341 gtk_list_store_set( store, &iter_ld, idi, "0", -1 );
2342 }
2343
2344 /* Set LD card parameters */
2345 gtk_list_store_set( store, &iter_ld, CMND_COL_I1, "5", -1 );
2346 snprintf( sv, 6, "%5d", tag );
2347 gtk_list_store_set( store, &iter_ld, CMND_COL_I2, sv, -1 );
2348 snprintf( sv, 13, "%12.5E", s );
2349 gtk_list_store_set( store, &iter_ld, CMND_COL_F1, sv, -1 );
2350
2351 /* Scroll tree view to bottom */
2352 gtk_adjustment_set_value(
2353 cmnd_adjustment, cmnd_adjustment->upper );
2354
2355 } /* Set_Wire_Conductivity() */
2356
2357 /*------------------------------------------------------------------------*/
2358
2359 /* Get_Wire_Conductivity()
2360 *
2361 * Gets the wire conductivity specified in a loading
2362 * card (LD row) in commands treview for a given tag #
2363 */
2364
2365 gboolean
Get_Wire_Conductivity(int tag,double * s,GtkListStore * store)2366 Get_Wire_Conductivity( int tag, double *s, GtkListStore *store )
2367 {
2368 int idx, type, nchld;
2369 GtkTreeIter iter_ld;
2370 gchar *str;
2371 static int t = -1;
2372
2373 /* Find num of rows and first iter, abort if tree empty */
2374 nchld = gtk_tree_model_iter_n_children(
2375 GTK_TREE_MODEL(store), NULL );
2376 if( !gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter_ld) )
2377 return( FALSE );
2378
2379 /* Look for an LD card with tag number = tag */
2380 for( idx = 0; idx < nchld; )
2381 {
2382 gtk_tree_model_get( GTK_TREE_MODEL(store),
2383 &iter_ld, GEOM_COL_NAME, &str, -1 );
2384
2385 if( strcmp(str, "LD") == 0 )
2386 {
2387 g_free( str );
2388 gtk_tree_model_get( GTK_TREE_MODEL(store),
2389 &iter_ld, GEOM_COL_I2, &str, -1 );
2390 if( atoi(str) == tag )
2391 {
2392 g_free( str );
2393 break;
2394 }
2395 else g_free( str );
2396 }
2397 else g_free( str );
2398
2399 idx++;
2400 if( !gtk_tree_model_iter_next(
2401 GTK_TREE_MODEL(store), &iter_ld) )
2402 break;
2403
2404 } /* for( idx = 0; idx < nchld; idx++ ) */
2405
2406 /* If not found LD card with tagnum = tag, return s=0 */
2407 if( idx >= nchld )
2408 {
2409 *s = 0.0;
2410 t = tag;
2411 return( FALSE );
2412 }
2413
2414 /* If LD card for given tag is already read, abort */
2415 if( t == tag ) return( FALSE );
2416 else t = tag;
2417
2418 /* Get the loading type (we want LDTYP 5) */
2419 gtk_tree_model_get( GTK_TREE_MODEL(store),
2420 &iter_ld, GEOM_COL_I1, &str, -1 );
2421 type = atoi( str );
2422 g_free( str );
2423 if( type != 5 ) return( FALSE );
2424
2425 /* Get the wire conductivity S/m */
2426 gtk_tree_model_get( GTK_TREE_MODEL(store),
2427 &iter_ld, CMND_COL_F1, &str, -1 );
2428 *s = Strtod( str, NULL );
2429 g_free( str );
2430
2431 return( TRUE );
2432 } /* Get_Wire_Conductivity() */
2433
2434 /*------------------------------------------------------------------------*/
2435
2436