1 /* object.c
2 * functions that do operations to DenemoObjects
3 *
4 * for Denemo, a gtk+ frontend to GNU Lilypond
5 * (c) 1999-2005 Matthew Hiller
6 */
7
8 #include <denemo/denemo.h>
9 #include "command/chord.h"
10 #include "core/utils.h"
11 #include "command/commandfuncs.h"
12 #include "command/object.h"
13 #include "command/staff.h"
14 #include "command/tuplet.h"
15 #include "command/select.h"
16 #include "audio/pitchentry.h"
17 #include "core/utils.h"
18 #include "core/view.h"
19 #include "command/lilydirectives.h"
20 #include <string.h>
21 static void edit_staff_and_voice_properties (gboolean show_staff);
22 void initkeyaccs (gint * accs, gint number);
23
24 DenemoObject *
get_object(void)25 get_object (void)
26 {
27 DenemoProject *gui = Denemo.project;
28 DenemoMovement *si = gui->movement;
29 return (DenemoObject *) si->currentobject ? (DenemoObject *) si->currentobject->data : NULL;
30 }
31
32 /**
33 * Free the given object
34 * @param mudobj the DenemoObject to free
35 FIXME is this failing to free the object field???
36 */
37 void
freeobject(DenemoObject * mudobj)38 freeobject (DenemoObject * mudobj)
39 {
40 if (mudobj == NULL)
41 return;
42 if (mudobj->lilypond)
43 g_free (mudobj->lilypond);
44 switch (mudobj->type)
45 {
46 case CHORD:
47 freechord (mudobj); /* Which also frees mudobj itself */
48 break;
49 case CLEF:
50 free_directives (((clef *) mudobj->object)->directives);
51 g_free (mudobj->object);
52 g_free (mudobj);
53 break;
54 case KEYSIG:
55 free_directives (((keysig *) mudobj->object)->directives);
56 g_free (mudobj->object);
57 g_free (mudobj);
58 break;
59 case TIMESIG:
60 free_directives (((timesig *) mudobj->object)->directives);
61 g_free (mudobj->object);
62 g_free (mudobj);
63 break;
64
65 case TUPOPEN:
66 case TUPCLOSE:
67 free_directives (((tuplet *) mudobj->object)->directives);
68 g_free (mudobj->object);
69 g_free (mudobj);
70 break;
71 default:
72 g_free (mudobj);
73 break;
74 }
75 }
76 /* drop display full information about the object at the cursor */
77 static GtkWidget *ObjectInfo = NULL;
78 static gboolean
drop_object_info(void)79 drop_object_info (void)
80 {
81 if (ObjectInfo)
82 gtk_widget_hide (ObjectInfo);
83 return TRUE;
84 }
85 /* display full information about the object at the cursor if Inspector is open*/
86 void
update_object_info(void)87 update_object_info (void)
88 {
89 if (ObjectInfo && gtk_widget_get_visible (ObjectInfo))
90 display_current_object ();
91 }
92 static void
append_directives_information(GString * selection,GList * directives)93 append_directives_information (GString * selection, GList * directives)
94 {
95 gboolean first = TRUE;
96 do
97 {
98 DenemoDirective *directive = directives->data;
99 if(directive->tag==NULL)
100 directive->tag = g_string_new("<Unknown Tag>");//shouldn't happen
101 const gchar *label = get_label_for_command (directive->tag->str);
102 const gchar *menupath = get_menu_path_for_command (directive->tag->str);
103 const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
104 if (tooltip == NULL) tooltip = _("No tooltip");
105
106 if(directive->tag==NULL)
107 directive->tag = g_string_new("<Unknown Tag>");//shouldn't happen
108 gchar *label_e = label? g_markup_escape_text(label, -1): g_markup_escape_text(directive->tag->str, -1);
109 if(!first)
110 g_string_append (selection, "\n<span foreground=\"blue\"weight=\"bold\">---------------------------------------------------------</span>\n");
111 else
112 g_string_append (selection, "\n<span foreground=\"green\"weight=\"bold\">---------------------------------------------------------</span>\n");
113 first = FALSE;
114 if(label)
115 g_string_append_printf (selection, _("Directive for command: <span weight=\"bold\">\"%s\"</span>\n"), label_e);
116 else
117 g_string_append_printf (selection, _("Directive tagged: <span foreground=\"red\"weight=\"bold\">\"%s\"</span>\n"), label_e);
118 g_free (label_e);
119 if(menupath)
120 {
121 gchar *menupath_e = g_markup_escape_text(menupath, -1);
122 g_string_append_printf (selection, _("Menu location for this command: <span style=\"italic\" weight=\"bold\">\"%s\"</span>\n"), menupath_e);
123 g_free (menupath_e);
124 }
125 if(tooltip)
126 {
127 gchar * tooltip_e = g_markup_escape_text(tooltip, -1);
128 g_string_append_printf (selection, _("The help for the command that created this directive is:\n<big>\"%s\"</big>\n"), tooltip_e);
129 g_free (tooltip_e);
130 }
131 if(directive->prefix)
132 {
133 gchar *lily = g_markup_escape_text(directive->prefix->str, -1);
134 g_string_append_printf (selection, _("LilyPond inserted in prefix to this object is <tt>\"%s\"</tt>\n"), lily);
135 g_free (lily);
136 }
137 if(directive->postfix)
138 {
139 gchar *lily = g_markup_escape_text(directive->postfix->str, -1);
140 g_string_append_printf (selection, _("LilyPond inserted in postfix to this object is <tt>\"%s\"</tt>\n"), lily);
141 g_free (lily);
142 }
143 if(directive->x || directive->y)
144 g_string_append (selection, _( "<span foreground=\"red\"weight=\"bold\">THIS DIRECTIVE IS CONDITIONAL ON THE LAYOUT\n</span>"));
145 if(!directives->next)
146 g_string_append (selection, "<span foreground=\"blue\"weight=\"bold\">---------------------------------------------------------</span>");
147
148 }
149 while (directives->next && (directives = directives->next));
150 g_string_append (selection, "\n");
151 }
152
append_lilypond(DenemoObject * curObj,GString * selection)153 static void append_lilypond (DenemoObject *curObj, GString *selection)
154 {
155 DenemoProject *gui = Denemo.project;
156 if( gui->lilysync != gui->changecount)
157 refresh_lily_cb (NULL, gui); //if(curObj->lilypond)g_print ("lili |%s|\n", curObj->lilypond);
158 if(curObj->lilypond && *curObj->lilypond)
159 g_string_append_printf (selection, _("The LilyPond syntax generated is: <tt>\"%s\"</tt>\n"), g_markup_escape_text(curObj->lilypond, -1));
160 else
161 g_string_append_printf (selection, _("This object does not affect the music typesetting, (no LilyPond syntax is generated)\n"));
162 }
163
gcd384(gint n)164 static gint gcd384 (gint n)
165 {
166 gint remainder, m = 384;
167 while (n != 0)
168 {
169 remainder = m % n;
170 m = n;
171 n = remainder;
172 }
173 return m;
174 }
reset_cursors(void)175 static void reset_cursors (void)
176 {
177 gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_LEFT_PTR));
178 if(ObjectInfo)
179 gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_LEFT_PTR));
180 if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
181 gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_LEFT_PTR));
182 }
183
move_to_next_note(GtkWidget * editwin)184 static void move_to_next_note (GtkWidget *editwin)
185 {
186 if(!cursor_to_next_note_height())
187 cursor_to_nth_note_height (0);
188 if (editwin)
189 {
190 gtk_widget_destroy (editwin);
191 reset_cursors ();
192 edit_object();
193 }
194 }
195
go_left(GtkWidget * editwin)196 static void go_left(GtkWidget *editwin)
197 {
198 cursor_to_prev_object (FALSE, FALSE);
199 if(Denemo.project->movement->currentobject == NULL)
200 {
201 cursor_to_next_object (FALSE, FALSE);
202 warningdialog (_("Preceding measures are empty"));
203 }
204 if (editwin)
205 {
206 gtk_widget_destroy (editwin);
207 reset_cursors ();
208 edit_object();
209 }
210 }
go_right(GtkWidget * editwin)211 static void go_right(GtkWidget *editwin)
212 {
213 cursor_to_next_object (FALSE, FALSE);
214 if(Denemo.project->movement->currentobject == NULL)
215 {
216 cursor_to_prev_object (FALSE, FALSE);
217 warningdialog (_("Subsequent measures are empty"));
218 }
219 if (editwin)
220 {
221 gtk_widget_destroy (editwin);
222 reset_cursors ();
223 edit_object();
224 }
225 }
226
227 static gint display_timeout_id = 0; //timeout to avoid calling display_current_object() repeatedly during rapid changes/entry of music
228 static gboolean
display_current_object_callback(void)229 display_current_object_callback (void)
230 {
231 DenemoProject *gui = Denemo.project;
232 if(Denemo.project->movement == NULL)
233 return FALSE;
234 gchar *type = "object";
235 if (ObjectInfo == NULL)
236 {
237 ObjectInfo = gtk_window_new (GTK_WINDOW_TOPLEVEL);
238 gtk_window_set_title (GTK_WINDOW (ObjectInfo), _("Denemo Object Inspector"));
239 g_signal_connect (G_OBJECT (ObjectInfo), "delete-event", G_CALLBACK (drop_object_info), NULL);
240 // gtk_window_set_keep_above (GTK_WINDOW (ObjectInfo), TRUE);
241 gtk_window_set_default_size (GTK_WINDOW (ObjectInfo), 400, 400);
242 gtk_window_set_accept_focus (GTK_WINDOW (ObjectInfo), FALSE);
243 }
244 else
245 {
246 gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (ObjectInfo)));
247 }
248
249 GtkWidget *vbox = gtk_vbox_new (FALSE, 8);
250 gtk_container_add (GTK_CONTAINER (ObjectInfo), vbox);
251
252 if (gui->movement->currentobject == NULL)
253 {
254 GtkWidget *label = gtk_label_new ("The cursor is in an empty measure.\n" "As a special case this will be typeset as a non-printing whole measure rest.\n" "Note that if you put anything at all in this measure\n" "you must insert a real whole measure rest if that is what you want.");
255 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
256 }
257 else
258 {
259 DenemoObject *curObj = gui->movement->currentobject->data;
260
261 if (curObj->type==CHORD)
262 {
263 chord *thechord = ((chord *) curObj->object);
264 if (thechord->notes)
265 {
266 note *thenote = findnote (curObj, Denemo.project->movement->cursor_y);
267 GtkWidget *button = gtk_button_new_with_label (
268 thechord->notes->next?_("Inspect next note in chord"):_("Inspect the note"));
269 gtk_widget_set_sensitive (button,
270 ( (!thenote) || thechord->notes->next || (Denemo.project->movement->cursor_y!=thenote->mid_c_offset)));
271
272 g_signal_connect_swapped (button, "clicked", G_CALLBACK (move_to_next_note), NULL);
273 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
274 }
275 }
276 GtkWidget *edit_button = gtk_button_new_with_label (_("Run the Object Editor"));
277 g_signal_connect (edit_button, "clicked", G_CALLBACK (edit_object), NULL);
278 gtk_box_pack_start (GTK_BOX (vbox), edit_button, FALSE, TRUE, 0);
279
280
281 GString *selection = g_string_new (gui->movement->cursor_appending ? _("The cursor is in the appending position after ") : _("The cursor is on "));
282 GString *warning = g_string_new ("");
283 switch (curObj->type)
284 {
285 case CHORD:
286 {
287 chord *thechord = ((chord *) curObj->object);
288 if (thechord->notes)
289 {
290 if (thechord->notes->next)
291 {
292 type = _("chord");
293 selection = g_string_append (selection, _("a chord.\n"));
294 }
295 else
296 {
297 type = _("note");
298 selection = g_string_append (selection, _("a one-note chord.\n"));
299 }
300 if (thechord->slur_begin_p)
301 selection = g_string_append (selection, _("A slur starts from here.\n" "There should be a matching end slur later.\n"));
302 if (thechord->slur_end_p)
303 selection = g_string_append (selection, _("A slur ends here\n" "There should be a matching start slur earlier.\n"));
304 if (thechord->is_tied)
305 selection = g_string_append (selection, _("This is tied to the following note or chord.\n" "The following note or chord should have the same pitch\n"));
306 if (thechord->crescendo_begin_p)
307 selection = g_string_append (selection, _("This note begins a crescendo. Use the Right Click → Dynamics menu to control this.\n"));
308 if (thechord->crescendo_end_p)
309 selection = g_string_append (selection, _("This note ends a crescendo. Use the Right Click → Dynamics menu to control this.\n"));
310 if (thechord->diminuendo_begin_p)
311 selection = g_string_append (selection, _("This note begins a diminuendo. Use the Right Click → Dynamics menu to control this.\n"));
312 if (thechord->diminuendo_end_p)
313 selection = g_string_append (selection, _("This note ends a diminuendo. Use the Right Click → Dynamics menu to control this.\n"));
314
315 if (thechord->is_grace && !(thechord->is_grace & GRACED_NOTE))
316 selection = g_string_append (selection, _("This is an acciaccatura note\n"));
317
318 if (thechord->is_grace & GRACED_NOTE)
319 selection = g_string_append (selection, _("This is an appoggiatura note\n"));
320 if (curObj->isinvisible)
321 selection = g_string_append (selection, _("This note denotes a rhythm - use a MIDI keyboard to add pitches by playing.\n"));
322 if (thechord->fakechord)
323 g_string_append_printf (selection, _("A Chord Symbol \"%s\" is attached to this note.\n"), ((GString *)thechord->fakechord)->str);
324
325 if (thechord->figure)
326 g_string_append_printf (selection, _("A Bass Figure \"%s\" is attached to this note.\n"), ((GString *)thechord->figure)->str);
327
328
329
330 note *thenote = findnote (curObj, gui->movement->cursor_y);
331 if (thenote && gui->movement->cursor_y==thenote->mid_c_offset)
332 {
333
334 g_string_append_printf (selection, _("<b>Within the chord the cursor is on the note %s </b>\n"),
335 pretty_name(mid_c_offsettolily (thenote->mid_c_offset, thenote->enshift)));
336 if (thenote->directives)
337 {
338 selection = g_string_append (selection, _("Attached to this note:"));
339 append_directives_information (selection, thenote->directives);
340 }
341 }
342 if ((thechord->notes->next) && curObj->isinvisible)
343 warning = g_string_append (warning, _("This rhythm has extra notes added to it, delete them and use the foot-pedal or Alt key to enter chords with the MIDI controller.\n"));
344
345 }
346 else
347 {
348 type = _("rest");
349 selection = g_string_append (selection, _("a rest.\n"));
350 if (thechord->slur_begin_p)
351 warning = g_string_append (warning, _("This rest has a slur start on it, use the Right Click → Slurs menu to remove it\n"));
352 if (thechord->slur_end_p)
353 warning = g_string_append (warning, _("This rest has a slur end on it, use the Right Click → Slurs menu to remove it\n"));
354 if (thechord->is_tied)
355 warning = g_string_append (warning, _("This rest has a tie starting on it, use the Right Click → Tied Note to remove it\n"));
356
357
358 if (curObj->isinvisible)
359 selection = g_string_append (selection, _("This rest will not print, just act as a spacer.\n"));
360 if (thechord->is_grace && curObj->isinvisible)
361 warning = g_string_append (warning, _("This rest has the grace attribute set: these objects are usually inserted automatically to match real grace notes in other parts, this helps the music typesetter place the grace note correctly in the Print View.\n"));
362
363 }
364 if (thechord->directives)
365 {
366 selection = g_string_append (selection, _("Attached to the chord:"));
367 append_directives_information (selection, thechord->directives);
368 }
369 gint gcd_s = gcd384 (curObj->starttick);
370 gint gcd_d = gcd384 (curObj->durinticks);
371 if (gcd_s == 384)
372 {
373 if (gcd_d == 384)
374 g_string_append_printf (selection, _("This %s starts %d 's into the measure and lasts %d 's.\n"), type, curObj->starttick/384, curObj->durinticks/384);
375 else
376 g_string_append_printf (selection, _("This %s starts %d 's into the measure and lasts %d/%d 's.\n"), type, curObj->starttick/384, curObj->durinticks/gcd_d, 384/gcd_d);
377 } else
378 {
379 if (gcd_d == 384)
380 g_string_append_printf (selection, _("This %s starts %d/%d 's into the measure and lasts %d 's.\n"), type, curObj->starttick/gcd_s, 384/gcd_s, curObj->durinticks/384);
381 else
382 g_string_append_printf (selection, _("This %s starts %d/%d 's into the measure and lasts %d/%d 's.\n"), type, curObj->starttick/gcd_s, 384/gcd_s, curObj->durinticks/gcd_d, 384/gcd_d);
383 }
384 append_lilypond (curObj, selection);
385 }
386 break;
387 case TUPOPEN:
388 { tuplet *thetup = ((tuplet *) curObj->object);
389 //type = _("start tuplet marker");
390 g_string_append_printf (selection, _(" a Start Tuplet object\n""Meaning %d notes will take the time of %d notes\n" "until an End Tuplet object.\nSee the Notes/Rests → Tuplets for control over how tuplets print\n"), thetup->denominator, thetup->numerator);
391 if (thetup->directives)
392 {
393 selection = g_string_append (selection, _("Attached to the Start Tuplet:"));
394 append_directives_information (selection, thetup->directives);
395 }
396 append_lilypond (curObj, selection);
397 }
398 break;
399 case TUPCLOSE:
400 { tuplet *thetup = ((tuplet *) curObj->object);
401 //type = _("end tuplet marker");
402 g_string_append_printf (selection, _("an End Tuplet object\n" "Note: the Start Tuplet must be in the same measure.\n"));
403 if (thetup->directives)
404 {
405 selection = g_string_append (selection, _("Attached to the End Tuplet:"));
406 append_directives_information (selection, thetup->directives);
407 }
408 append_lilypond (curObj, selection);
409 }
410 break;
411 case CLEF:
412 {
413 clef *theclef = ((clef *) curObj->object);
414 //type = _("clef change object");
415 g_string_append_printf (selection, _("a Clef Change object.\n"));
416 if (theclef->directives)
417 {
418 selection = g_string_append (selection, _("Attached to the Clef Change:"));
419 append_directives_information (selection, theclef->directives);
420 }
421 if (curObj->isinvisible)
422 selection = g_string_append (selection, _("This clef change is non-printing, it just affects the display.\n"));
423 append_lilypond (curObj, selection);
424
425 }
426 break;
427 case TIMESIG:
428 {
429 timesig *thetime = ((timesig *) curObj->object);
430 //type = _("time signature change object");
431 g_string_append_printf (selection, _("a Time Signature Change object.\n"));
432 if (thetime->directives)
433 {
434 selection = g_string_append (selection, _("Attached to the Time Signature Change:"));
435 append_directives_information (selection, thetime->directives);
436 }
437 append_lilypond (curObj, selection);
438 if (gui->movement->currentobject->prev)
439 g_string_append_printf (warning, _("A Time Signature Change should be the first object in a measure\n" "unless you are trying to do something unusual"));
440 }
441 break;
442 case KEYSIG:
443 {
444 keysig *thekey = ((keysig *) curObj->object);
445 //type = _("key signature change object");
446
447 g_string_append_printf (selection, _("a Key Signature Change object.\n"));
448 if (thekey->directives)
449 {
450 selection = g_string_append (selection, _("Attached to the Key Signature Change:"));
451 append_directives_information (selection, thekey->directives);
452 }
453 append_lilypond (curObj, selection);
454 }
455 break;
456 case STEMDIRECTIVE:
457 {
458 stemdirective *thestem = ((stemdirective *) curObj->object);
459 //type = _("stem direction change object");
460 g_string_append_printf (selection, _("a Stem Direction Control Object. The notes after the cursor %s"), ((stemdirective *) curObj->object)->type == DENEMO_STEMDOWN ? _("will have stems downwards.") : ((stemdirective *) curObj->object)->type == DENEMO_STEMUP ? _("will have stems upwards.") : _("will have stems up or down as needed."));
461 if (thestem->directives)
462 {
463 selection = g_string_append (selection, _("\nAttached to the Stemming Change:"));
464 append_directives_information (selection, thestem->directives);
465 }
466 append_lilypond (curObj, selection);
467 }
468 break;
469 case LILYDIRECTIVE:
470 {
471 DenemoDirective *directive = (DenemoDirective *) curObj->object;
472 //type = _("Denemo directive object");
473
474 if(directive->tag==NULL)
475 directive->tag = g_string_new("<Unknown Tag>");//shouldn't happen
476 const gchar *label = get_label_for_command (directive->tag->str);
477 const gchar *menupath = get_menu_path_for_command (directive->tag->str);
478 const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
479 if (tooltip == NULL) tooltip = _("No tooltip");
480 gchar *label_e = label? g_markup_escape_text(label, -1): g_markup_escape_text(directive->tag->str, -1);
481 if(label)
482 g_string_append_printf (selection, _("a Denemo Directive: <span weight=\"bold\">%s</span>\n"), label_e);
483 else
484 g_string_append_printf (selection, _("a Denemo Directive tagged: <span foreground=\"red\"weight=\"bold\">%s</span>\n"), label_e);
485 g_free (label_e);
486 if(tooltip)
487 {
488 gchar *tooltip_e = g_markup_escape_text(tooltip, -1);
489 g_string_append_printf (selection, _("\nThe help for the command that created this directive is\n<big>\"%s\"</big>"), tooltip_e);
490 g_free (tooltip_e);
491 }
492
493 g_string_append_printf (selection, _("%s"), directive->x ? _("\nNot all layouts\n") : directive->y ? _("\nOnly for one Layout\n"): "\n");
494 if(menupath)
495 {
496 gchar *menupath_e = g_markup_escape_text(menupath, -1);
497 g_string_append_printf (selection, _("Menu location for this command: <span style=\"italic\" weight=\"bold\">\"%s\"</span>\n"), menupath_e);
498 g_free (menupath_e);
499 }
500
501 {
502 gchar *text = g_strconcat(directive->prefix?directive->prefix->str:"",
503 directive->postfix?directive->postfix->str:"", NULL);
504 g_strchug (text); //does not allocate memory
505 if (*text)
506 {
507 gchar *lily1 = directive->prefix?g_markup_escape_text(directive->prefix->str, -1):g_strdup("");
508 gchar *lily2 = directive->postfix?g_markup_escape_text(directive->postfix->str, -1):g_strdup("");
509
510 g_string_append_printf (selection, _("The LilyPond text inserted is <tt>%s%s</tt>\n"),
511 lily1,lily2);//puts the whitespace back
512 g_free (lily1);
513 g_free (lily2);
514 }
515 else
516 g_string_append_printf (selection, _("This object does not affect the printed output (no LilyPond syntax is generated for the typesetter)\n"));//well this ignores possible effect of whitespace...
517 g_free (text);
518 if(directive->x || directive->y)
519 g_string_append (selection, _( "<span foreground=\"red\"weight=\"bold\">THIS DIRECTIVE IS CONDITIONAL ON THE LAYOUT\n</span>"));
520 }
521 if (gui->movement->currentobject->next == NULL && (gui->movement->currentmeasure->next == NULL))
522 g_string_assign (warning, _("This Directive is at the end of the music"
523 "\nYou may need a closing double bar line -\n"
524 "see Directives → Markings → Inserting Barlines"));
525 }
526 break;
527 default:
528 {
529 g_string_append (selection, _("The cursor is on an unknown object type. Please report how this happened!"));
530 }
531 break;
532 } //end switch curObj type
533
534 if (gui->movement->smfsync == gui->movement->changecount)
535 {
536
537 gdouble time = curObj->earliest_time;
538 gint minutes = time / 60.0;
539 gdouble seconds = time - 60 * minutes;
540 g_string_append_printf (selection, _("Playback timing: %d minutes %1.2f seconds"), minutes, seconds);
541 }
542
543 if (warning->len)
544 {
545 GtkWidget *label = gtk_label_new ("");
546 warning = g_string_prepend (warning, _("<span font-desc=\"30\">Warning</span> "));
547 gtk_label_set_markup (GTK_LABEL (label), warning->str);
548 gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
549 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
550 }
551 if (selection->len)
552 {
553 GtkWidget *scrolled_window = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
554 gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
555 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
556 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_window), inner_box);
557 GtkWidget *label = gtk_label_new ("");
558 gtk_label_set_selectable (GTK_LABEL(label), TRUE);
559
560 /*
561 making the text selectable unfortunately results in the label text being selected at the start
562 the following code would undo that, but selection-bound cannot be written to, so it does not work.
563 int start, end;
564 gtk_label_get_selection_bounds (GTK_LABEL(label), &start, &end);
565 GValue value = { 0 };
566 g_value_init (&value, G_TYPE_INT);
567 g_value_set_int (&value, end);
568 g_object_set_property (G_OBJECT (label), "selection-bound", &value);
569 *this also does not work:
570 g_signal_emit_by_name (GTK_LABEL(label), "move-cursor", GTK_MOVEMENT_BUFFER_ENDS, -1, FALSE);
571 */
572 gtk_label_set_markup (GTK_LABEL (label), selection->str);
573 gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
574 gtk_box_pack_start (GTK_BOX (inner_box), label, TRUE, TRUE, 0);
575 }
576 g_string_free (warning, TRUE);
577 g_string_free (selection, TRUE);
578 }
579 gtk_widget_show_all (ObjectInfo);
580 #ifdef G_OS_WIN32
581 //on windows, the ObjectInfo window takes the focus regardless of having told it not to, so it is up to the user to bring the inspector to the front.
582 gtk_window_set_transient_for (GTK_WINDOW(ObjectInfo), GTK_WINDOW(Denemo.window));
583 gtk_window_set_keep_above (GTK_WINDOW (ObjectInfo), TRUE);
584
585 #else
586 gtk_window_present (GTK_WINDOW (ObjectInfo));
587 #endif
588 display_timeout_id = 0;
589 return FALSE;
590 }
591 void
display_current_object(void)592 display_current_object (void) {
593 static gint delay = 10;
594 if (display_timeout_id == 0) {
595 display_timeout_id = g_timeout_add (delay, (GSourceFunc)display_current_object_callback, NULL);
596 delay = 10;
597 }
598 else {
599
600 if (delay<1500)
601 delay += 100;
602 }
603 }
show_window(GtkWidget * w)604 static void show_window (GtkWidget *w) {
605 w = gtk_widget_get_toplevel (w);
606 gtk_widget_show (w);
607 gtk_window_present (GTK_WINDOW(w));
608 //g_print ("Window presented");
609 }
610
611 static void
set_false(GtkWidget * button,gboolean * bool)612 set_false (GtkWidget *button, gboolean *bool)
613 {
614 GtkWidget *w = gtk_widget_get_toplevel (button);
615 gtk_widget_destroy (button);
616 show_window (w);
617 if (*bool)
618 score_status(Denemo.project, TRUE);
619 *bool = FALSE;
620 }
621
622 typedef gboolean fn_type (gchar*);
advanced_edit_type_directive(GtkWidget * button,gpointer fn)623 static void advanced_edit_type_directive (GtkWidget *button, gpointer fn)
624 {
625 DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
626 GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
627 gtk_widget_hide (gtk_widget_get_toplevel (button));
628 if (!( ((fn_type *)fn) (directive->tag->str)))
629 {
630 if(directives)
631 *directives = g_list_remove (*directives, directive);
632 else
633 dnm_deleteobject (Denemo.project->movement);
634 gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
635 score_status(Denemo.project, TRUE);
636 }
637 else
638 show_window (button);//gtk_widget_show (gtk_widget_get_toplevel (button));
639
640 }
641
create_palette_button_for_directive(GtkWidget * button,gchar * what)642 static void create_palette_button_for_directive (GtkWidget *button, gchar *what)
643 {
644 DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
645 DenemoPalette *pal = NULL;
646 if(!strcmp (what, "lilycontrol"))
647 what = "score";
648 GString *script = g_string_new (get_script_for_directive (directive, what));
649 gchar *name = choose_palette_by_name (TRUE, FALSE);
650 DenemoObject *curObj = get_object ();
651 if (curObj && curObj->type == CHORD)
652 {
653 chord *thechord = (chord *) curObj->object;
654 if (thechord->chordize)
655 g_string_append (script, "(d-Chordize #t)\n");
656 }
657
658 if (name)
659 pal = create_palette (name, FALSE, TRUE);
660 if(pal) {
661 gchar *button_name = g_strdup_printf (_( "Clone %s"), directive->tag->str);
662 gchar *label = string_dialog_entry (Denemo.project, _("Palette Button Creation"), _("Give a (unique) name for the button"), button_name);
663 if (label)
664 {
665 if (!palette_add_button (pal, label, _("Creates a cloned Denemo Directive"), script->str))
666 warningdialog (_("Could not create a button of that name in that palette"));
667 } else
668 warningdialog (_("Cancelled"));
669 g_free (label);
670 g_free (button_name);
671 gtk_widget_show_all (gtk_widget_get_parent(pal->box));
672 gtk_widget_destroy (gtk_widget_get_toplevel (button));
673 reset_cursors ();
674 }
675 g_string_free (script, TRUE);
676 }
create_palette_button_for_command(GtkWidget * button,gchar * tooltip)677 static void create_palette_button_for_command (GtkWidget *button, gchar *tooltip)
678 {
679 DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
680 DenemoPalette *pal = NULL;
681 gchar *script = g_strdup_printf ("(d-%s)", directive->tag->str);
682 gchar *name = choose_palette_by_name (TRUE, FALSE);
683 if (name)
684 pal = create_palette (name, FALSE, TRUE);
685 if(pal) {
686 gboolean success = palette_add_button (pal, directive->tag->str, tooltip, script);
687 gtk_widget_show_all (gtk_widget_get_parent(pal->box));
688 gtk_widget_destroy (gtk_widget_get_toplevel (button));
689 reset_cursors ();
690 }
691 g_free (script);
692 }
693
delete_directive(GtkWidget * button,gpointer fn)694 static void delete_directive (GtkWidget *button, gpointer fn)
695 {
696 DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
697 GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
698 if(directives)
699 *directives = g_list_remove (*directives, directive);
700 else
701 dnm_deleteobject (Denemo.project->movement);
702 gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
703 score_status(Denemo.project, TRUE);
704 }
705 typedef enum DIRECTIVE_TYPE {DIRECTIVE_OBJECT = 0, DIRECTIVE_SCORE = 1, DIRECTIVE_MOVEMENT = 2, DIRECTIVE_STAFF = 3, DIRECTIVE_VOICE = 4, DIRECTIVE_KEYSIG = 5, DIRECTIVE_TIMESIG = 6} DIRECTIVE_TYPE;
706
707 static void
call_edit_on_action(GtkWidget * button,DIRECTIVE_TYPE score_edit)708 call_edit_on_action (GtkWidget *button, DIRECTIVE_TYPE score_edit)
709 {
710 gtk_widget_destroy (gtk_widget_get_toplevel (button));
711 DenemoScriptParam param;
712 GtkAction *action = (GtkAction*)g_object_get_data (G_OBJECT (button), "action");
713 GList *currentobject = Denemo.project->movement->currentobject;
714 param.string = g_string_new ("edit");
715 g_debug ("Script can look for params \"edit\" - a string to catch this");
716 activate_script (action, ¶m);
717 g_string_free (param.string, TRUE);
718 // gtk_widget_destroy (gtk_widget_get_toplevel (button));
719 if (score_edit)
720 {
721 if (score_edit==DIRECTIVE_SCORE)
722 edit_score_properties ();
723 else
724 if (score_edit==DIRECTIVE_MOVEMENT)
725 edit_movement_properties ();
726 else
727 if (score_edit==DIRECTIVE_VOICE)
728 edit_voice_properties ();
729 else
730 edit_staff_properties ();//also for KEYSIG AND TIMESIG
731
732 } else
733 {
734 if (!score_edit && (currentobject == Denemo.project->movement->currentobject))
735 edit_object();
736 else
737 reset_cursors ();
738 }
739 }
740 static void
call_score_properties_dialog(GtkWidget * button)741 call_score_properties_dialog (GtkWidget *button)
742 {
743 gtk_widget_hide (gtk_widget_get_toplevel (button));
744 score_properties_dialog (NULL, NULL);
745 show_window (button);//gtk_widget_show (gtk_widget_get_toplevel (button));
746 }
execute_editscript(GtkWidget * button,gchar * filename)747 static void execute_editscript (GtkWidget *button, gchar *filename)
748 {
749 gchar *keep = g_strdup (filename);
750 gtk_widget_destroy (gtk_widget_get_toplevel (button));
751 GError *error = (GError *) execute_script_file (keep);
752 g_free (keep);
753 GList *currentobject = Denemo.project->movement->currentobject;
754
755 if (error)
756 g_warning ("%s", error->message);
757
758 if (currentobject == Denemo.project->movement->currentobject)
759 edit_object();
760 else
761 reset_cursors ();
762 }
763
764 /* linked to type_str[] array!!! */
765 typedef enum {
766 EDIT_CHORD = 0,
767 EDIT_NOTE,
768 EDIT_TUPLET_START,
769 EDIT_TUPLET_END,
770 EDIT_CLEF,
771 EDIT_KEY,
772 EDIT_TIMESIG,
773 EDIT_STEMDIR,
774 EDIT_STANDALONE,
775
776 } EditObjectType;
777
778 static gchar *type_str [] =
779 {
780 "chord",
781 "note",
782 "tuplet",
783 "tuplet",
784 "clef",
785 "keysig",
786 "timesig",
787 "stemdirective",
788 "standalone",
789 };
general_edit_popup(GtkWidget * button,EditObjectType type)790 static void general_edit_popup (GtkWidget *button, EditObjectType type)
791 {
792
793 #ifdef G_OS_WIN32
794 //the popup does not work on windows...
795 #else
796 if (type == EDIT_CHORD)
797 popup_menu ("/NoteEditPopup");
798 else
799 #endif
800 infodialog (_("To add or remove built-in attributes right click on the object in the display window"));
801
802 gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
803 reset_cursors ();
804
805 }
display_help(gchar * help)806 static void display_help(gchar *help)
807 {
808 infowarningdialog (help, TRUE);
809 }
810
811
seek_directive(GtkWidget * button,gchar * type,gchar * tag)812 static void seek_directive(GtkWidget *button, gchar *type, gchar *tag)
813 {
814 gtk_widget_destroy (gtk_widget_get_toplevel (button));
815 GList *currentobject = Denemo.project->movement->currentobject;
816 gchar *script = type? g_strconcat ("(define-once EditSimilar::last #f)\n(set! EditSimilar::last (cons ",
817 type, " \"",
818 tag, "\"))\n(d-ResumeEdit)",
819 NULL):
820 g_strdup ("(d-EditSimilar)");
821 call_out_to_guile (script);
822 g_free(script);
823
824 if (currentobject == Denemo.project->movement->currentobject)
825 edit_object();
826 else
827 reset_cursors ();
828 }
seek_note_directive(GtkWidget * button,gchar * tag)829 static void seek_note_directive(GtkWidget *button, gchar *tag)
830 {
831 seek_directive (button, "'note", tag);
832 }
seek_chord_directive(GtkWidget * button,gchar * tag)833 static void seek_chord_directive(GtkWidget *button, gchar *tag)
834 {
835 seek_directive (button, "'chord", tag);
836 }
seek_keysig_directive(GtkWidget * button,gchar * tag)837 static void seek_keysig_directive(GtkWidget *button, gchar *tag)
838 {
839 seek_directive (button, "'keysigdir", tag);
840 }
seek_timesig_directive(GtkWidget * button,gchar * tag)841 static void seek_timesig_directive(GtkWidget *button, gchar *tag)
842 {
843 seek_directive (button, "'timesigdir", tag);
844 }
seek_stemdirective_directive(GtkWidget * button,gchar * tag)845 static void seek_stemdirective_directive(GtkWidget *button, gchar *tag)
846 {
847 seek_directive (button, "'stemdir", tag);
848 }
seek_clef_directive(GtkWidget * button,gchar * tag)849 static void seek_clef_directive(GtkWidget *button, gchar *tag)
850 {
851 seek_directive (button, "'clefdir", tag);
852 }
seek_standalone_directive(GtkWidget * button,gchar * tag)853 static void seek_standalone_directive (GtkWidget *button, gchar *tag)
854 {
855 seek_directive (button, NULL, tag);
856 }
make_chord_directive_conditional(gchar * tag)857 static void make_chord_directive_conditional (gchar *tag)
858 {gchar *script = g_strdup_printf ("(d-ChooseCondition (cons \"%s\" #f))", tag);
859 call_out_to_guile (script);
860 g_free (script);
861 }
make_note_directive_conditional(gchar * tag)862 static void make_note_directive_conditional (gchar *tag)
863 {gchar *script = g_strdup_printf ("(d-ChooseCondition (cons \"%s\" #t))", tag);
864 call_out_to_guile (script);
865 g_free (script);
866 }
867
868
869
870
871
872 #if GTK_MAJOR_VERSION == 2
873 #define GdkRGBA GdkColor
874 #define gtk_widget_override_color gtk_widget_modify_fg
875 #define gtk_widget_override_background_color gtk_widget_modify_bg
876 #define GTK_STATE_FLAG_NORMAL (0)
get_color(GdkColor * color,gdouble r,gdouble g,gdouble b,gdouble a)877 static void get_color (GdkColor *color, gdouble r, gdouble g, gdouble b, gdouble a) {
878 gchar *col = g_strdup_printf ( "#%02x%02x%02x", (gint)(r*254),(gint)(g*254),(gint)(b*254));
879 gdk_color_parse (col, color);
880 g_free(col);
881 }
882 #else
get_color(GdkRGBA * color,gdouble r,gdouble g,gdouble b,gdouble a)883 static void get_color (GdkRGBA *color, gdouble r, gdouble g, gdouble b, gdouble a) {
884 color->red = r; color->green = g;
885 color->blue = b;
886 color->alpha = a;
887 }
888 #endif
889
890 static void
place_directives(GtkWidget * vbox,GList ** pdirectives,EditObjectType type)891 place_directives (GtkWidget *vbox, GList **pdirectives, EditObjectType type)
892 {
893 GList *directives = *pdirectives;
894 for (; directives;directives = directives->next)
895 {
896 DenemoDirective *directive = directives->data;
897 const gchar *label = get_label_for_command (directive->tag->str);
898 GtkAction *action = lookup_action_from_name (directive->tag->str);
899 gchar *name = label?(gchar*)label:directive->tag->str;
900 const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
901
902 gchar *filename = get_editscript_filename (directive->tag->str);
903
904 if (!label)
905 label = directive->tag->str;
906 GtkWidget *expander = gtk_expander_new (label);
907 gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
908 gtk_widget_set_sensitive (expander, TRUE);
909 gtk_container_set_border_width (GTK_CONTAINER (expander), 0);
910 gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, TRUE, 0);
911 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
912 gtk_container_add (GTK_CONTAINER (expander), inner_box);
913
914 if (filename)
915 {
916 gchar *thelabel = g_strconcat (_("Run the Edit Script for "), name, NULL);
917 GtkWidget *button = gtk_button_new_with_label (thelabel);
918 g_signal_connect (button, "clicked", G_CALLBACK (execute_editscript), filename);
919 g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), filename);
920 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
921 g_free(thelabel);
922 }
923 else if (action)
924 {
925 gchar *thelabel = g_strconcat (_("Execute command: "), name, NULL);
926 GtkWidget *button = gtk_button_new_with_label (thelabel);
927 gtk_widget_set_tooltip_text (button, _("Re-run the command to edit the Denemo Directive"));
928 g_object_set_data (G_OBJECT(button), "action", (gpointer)action);
929 g_signal_connect (button, "clicked", G_CALLBACK (call_edit_on_action), NULL);
930 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
931 g_free(thelabel);
932 }
933
934
935 fn_type *func;
936 switch (type) {
937 case EDIT_NOTE:
938 func = text_edit_note_directive;
939 break;
940 case EDIT_CHORD:
941 func = text_edit_chord_directive;
942 break;
943 case EDIT_CLEF:
944 func = text_edit_clef_directive;
945 break;
946 case EDIT_KEY:
947 func = text_edit_keysig_directive;
948 break;
949 case EDIT_TIMESIG:
950 func = text_edit_timesig_directive;
951 break;
952 case EDIT_STEMDIR:
953 func = text_edit_stemdirective_directive;
954 break;
955 default:
956 g_critical ("Unknown type");
957 func = text_edit_standalone_directive;
958 break;
959
960 }
961 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
962 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
963
964 //gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
965 GtkWidget *button = gtk_button_new_with_label (_("Delete"));
966 GtkWidget *labelwidget = (GtkWidget *) gtk_bin_get_child (GTK_BIN (button));
967
968 GdkRGBA color;
969 get_color (&color, 1.0, 0.0, 0.0, 1.0);
970 gtk_widget_override_color (labelwidget, GTK_STATE_FLAG_NORMAL, &color);
971 g_object_set_data (G_OBJECT(button), "directives", (gpointer)pdirectives);
972 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
973 g_signal_connect (button, "clicked", G_CALLBACK (delete_directive), func);
974 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 30);
975
976
977 {
978 fn_type *func;
979 switch (type) {
980 case EDIT_NOTE:
981 func = (fn_type *)seek_note_directive;//seek_directive (note, tag);
982 break;
983 case EDIT_CHORD:
984 func = (fn_type *)seek_chord_directive;
985 break;
986
987 case EDIT_CLEF:
988 func = (fn_type *)seek_clef_directive;
989 break;
990 case EDIT_KEY:
991 func = (fn_type *)seek_keysig_directive;
992 break;
993 case EDIT_TIMESIG:
994 func = (fn_type *)seek_timesig_directive;
995 break;
996 case EDIT_STEMDIR:
997 func = (fn_type *)seek_stemdirective_directive;
998 break;
999 default:
1000 g_critical ("Unknown type");
1001 func = NULL;
1002 break;
1003
1004 }
1005 if(func) {
1006 button = gtk_button_new_with_label (_("Next ➡"));
1007 get_color (&color, 0.0, 0.7, 0.7, 1.0);
1008 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1009 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (func), (gpointer)label);
1010 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1011 }
1012 }
1013 if ((type==EDIT_NOTE) || (type==EDIT_CHORD))
1014 {
1015 button = gtk_button_new_with_label (_("Conditional"));
1016 get_color (&color, 0.0, 0., 0.5, 1.0);
1017 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1018 if (type==EDIT_CHORD)
1019 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (make_chord_directive_conditional), (gpointer)directive->tag->str);
1020 else
1021 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (make_note_directive_conditional), (gpointer)directive->tag->str);
1022
1023
1024
1025 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1026 }
1027
1028 if (tooltip)
1029 {
1030 button = gtk_button_new_with_label (_("Help"));
1031 get_color (&color, 0.0, 0.7, 0.7, 1.0);//color.red = 0.0; color.green = 0.7, color.blue = 0.3; color.alpha = 1.0;
1032 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1033 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (display_help), (gpointer)tooltip);
1034 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1035 }
1036 if (tooltip == NULL) tooltip = _("No tooltip");
1037
1038 if (action) {
1039 button = gtk_button_new_with_label (_("Create Button for Command"));
1040 gtk_widget_set_tooltip_text (button, _( "Make a palette button for running the command that created this attribute."));
1041 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1042 g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_command), (gpointer)tooltip);
1043 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1044 }
1045
1046 button = gtk_button_new_with_label (_("Create Button for Clone"));
1047 gtk_widget_set_tooltip_text (button, _( "Make a palette button for installing this attribute elsewhere."));
1048 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1049 g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_directive), (gpointer)(type_str[type]));
1050 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1051
1052 button = gtk_button_new_with_label (_("Advanced"));
1053 gtk_widget_set_tooltip_text (button, _( "Examine/Edit this directive at a low-level"));
1054 g_object_set_data (G_OBJECT(button), "directives", (gpointer)pdirectives);
1055 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1056 g_signal_connect (button, "clicked", G_CALLBACK (advanced_edit_type_directive), func);
1057 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1058 }
1059 }
1060 static void
place_chord_attributes(GtkWidget * vbox,chord * thechord)1061 place_chord_attributes (GtkWidget *vbox, chord *thechord)
1062 {
1063 GtkWidget *expander = gtk_expander_new (_("Built-in Chord Attributes"));//gtk_expander_new
1064 gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
1065 gtk_widget_set_sensitive (expander, TRUE);
1066 gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1067 GdkRGBA color;
1068 get_color (&color, 0.1, 0.1, 0.8, 1.0);
1069 gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1070 gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, TRUE, 0);
1071 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1072 gtk_container_add (GTK_CONTAINER (expander), inner_box);
1073 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1074 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1075 inner_box = gtk_vbox_new (FALSE, 0);
1076 gtk_box_pack_start (GTK_BOX (hbox), inner_box, FALSE, TRUE, 30);
1077 if (thechord->slur_begin_p)
1078 {
1079 GtkWidget *button = gtk_button_new_with_label (_("Remove slur start"));
1080 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->slur_begin_p);
1081 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1082 }
1083 if (thechord->slur_end_p)
1084 {
1085 GtkWidget *button = gtk_button_new_with_label (_("Remove slur end"));
1086 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->slur_end_p);
1087 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1088 }
1089 if (thechord->is_tied)
1090 {
1091 GtkWidget *button = gtk_button_new_with_label (_("Remove tie"));
1092 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->is_tied);
1093 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1094 }
1095 if (thechord->crescendo_begin_p)
1096 {
1097 GtkWidget *button = gtk_button_new_with_label (_("Remove Start cresc. marking"));
1098 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->crescendo_begin_p);
1099 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1100 }
1101 if (thechord->crescendo_end_p)
1102 {
1103 GtkWidget *button = gtk_button_new_with_label (_("Remove End cresc. marking"));
1104 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->crescendo_end_p);
1105 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1106 }
1107 if (thechord->diminuendo_begin_p)
1108 {
1109 GtkWidget *button = gtk_button_new_with_label (_("Remove Start dim. marking"));
1110 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->diminuendo_begin_p);
1111 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1112 }
1113 if (thechord->diminuendo_end_p)
1114 {
1115 GtkWidget *button = gtk_button_new_with_label (_("Remove End dim. marking"));
1116 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->diminuendo_end_p);
1117 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1118 }
1119
1120 if (thechord->is_grace)
1121 {
1122 GtkWidget *button = gtk_button_new_with_label (_("Un-grace the note"));
1123 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->is_grace);
1124 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1125 }
1126 if(!gtk_container_get_children (GTK_CONTAINER (inner_box)))
1127 gtk_widget_destroy (expander);
1128 }
1129
update_and_close(GtkWidget * editwin)1130 static void update_and_close (GtkWidget *editwin)
1131 {
1132 update_object_info ();
1133 gtk_widget_destroy (editwin);
1134 reset_cursors ();
1135 }
1136
run_script(GtkWidget * button,gchar * script)1137 static void run_script (GtkWidget *button, gchar *script)
1138 {
1139 call_out_to_guile (script);
1140 gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
1141 reset_cursors ();
1142 }
1143
delete_standalone(GtkWidget * button)1144 static void delete_standalone (GtkWidget *button)
1145 {
1146 dnm_deleteobject (Denemo.project->movement);
1147 gtk_widget_destroy (gtk_widget_get_toplevel (button));
1148 score_status(Denemo.project, TRUE);
1149 reset_cursors ();
1150 }
1151 // edit the specific object at the cursor
1152 void
edit_object(void)1153 edit_object (void)
1154 {
1155 DenemoMovement *si = Denemo.project->movement;
1156 DenemoObject *curObj = get_object ();
1157 if (curObj == NULL)
1158 {
1159 warningmessage (_("No object here to edit"));
1160 return;
1161 }
1162 GtkWidget *editwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1163 GdkRGBA color;
1164 get_color (&color, 1.0, 1.0, 1.0, 1.0);//.red = color.green = color.blue = color.alpha = 1.0;
1165 gtk_widget_override_background_color (editwin, GTK_STATE_FLAG_NORMAL, &color);
1166 gtk_window_set_modal (GTK_WINDOW (editwin), TRUE);
1167 gtk_window_set_title (GTK_WINDOW (editwin), _("Denemo Object Editor"));
1168 gtk_window_set_transient_for (GTK_WINDOW(editwin), GTK_WINDOW(Denemo.window));
1169 gtk_window_set_keep_above (GTK_WINDOW (editwin), TRUE);
1170 GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1171 gtk_container_add (GTK_CONTAINER (editwin), vbox);
1172 GtkWidget *close_button = gtk_button_new_with_label (_("Close"));
1173 g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (update_and_close), editwin);
1174
1175 g_signal_connect (G_OBJECT (editwin), "destroy", G_CALLBACK (reset_cursors), NULL);
1176 gtk_box_pack_start (GTK_BOX (vbox), close_button, FALSE, TRUE, 0);
1177 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1178 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1179
1180 GtkWidget *button = gtk_button_new_with_label (_("⬅ Previous Object"));
1181 g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_left), editwin);
1182 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1183
1184 if ((!si->currentobject->prev)&&(!si->currentmeasure->prev))
1185 gtk_widget_set_sensitive (button, FALSE);
1186
1187 GtkWidget *note_up_button = gtk_button_new_with_label (_("Next note in chord"));
1188 g_signal_connect_swapped (note_up_button, "clicked", G_CALLBACK (move_to_next_note), editwin);
1189 gtk_box_pack_start (GTK_BOX (hbox), note_up_button, FALSE, TRUE, 0);
1190
1191 button = gtk_button_new_with_label (_("Next Object ➡"));
1192 g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_right), editwin);
1193 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1194
1195 if ((!si->currentobject->next) && (!si->currentmeasure->next))
1196 gtk_widget_set_sensitive (button, FALSE);
1197
1198 switch (curObj->type)
1199 {
1200 case CHORD:
1201 {
1202 chord *thechord = ((chord *) curObj->object);
1203 if (thechord->directives)
1204 {
1205 GtkWidget *frame = gtk_frame_new (thechord->notes? _("Attached to the chord:"):
1206 _("Attached to the rest:"));
1207 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1208 GdkRGBA color;
1209 get_color (&color, 0.8, 0.1, 0.1, 1.0);//color.red = 0.8;color.green = color.blue = 0.1; color.alpha = 1;
1210 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1211 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1212 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1213 get_color (&color, 0.1, 0.8, 0.1, 1.0);
1214 gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1215 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1216 place_directives (inner_box, &thechord->directives, EDIT_CHORD);
1217 }
1218
1219 if (thechord->notes)
1220 {
1221 place_chord_attributes (vbox, thechord);
1222 note *thenote = findnote (curObj, Denemo.project->movement->cursor_y);
1223 if (!thechord->notes->next)
1224 gtk_button_set_label (GTK_BUTTON (note_up_button), _("Edit the note"));
1225 if ( (!thenote) || thechord->notes->next || (Denemo.project->movement->cursor_y!=thenote->mid_c_offset))
1226 {
1227 note_up_button = NULL; // a tricksy bit of code this: the button is already packed in the vbox, by setting this NULL we stop it being set insensitive as it must be for all other cases.
1228 }
1229 if (thenote && Denemo.project->movement->cursor_y==thenote->mid_c_offset)
1230 {
1231 GString *text = g_string_new ("");
1232
1233 if (thenote->directives)
1234 {
1235 g_string_append_printf (text, _("Attached to Note %s"),
1236 pretty_name (mid_c_offsettolily (thenote->mid_c_offset, thenote->enshift)));
1237 GtkWidget *frame = gtk_frame_new (text->str);
1238 gtk_container_set_border_width (GTK_CONTAINER (frame), 20);
1239 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1240 GdkRGBA color;
1241 get_color (&color, 0.2, 0.7, 0.2, 1.0);/// color.green = 0.7; color.red = color.blue = 0.2; color.alpha = 1;
1242 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1243 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1244 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1245 get_color (&color, 0.1, 0.8, 0.1, 1.0);
1246 gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1247
1248 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1249 place_directives (inner_box, &thenote->directives, EDIT_NOTE);
1250 }
1251 else
1252 {
1253 g_string_append_printf (text, _("Nothing attached to Note %s"),
1254 pretty_name (mid_c_offsettolily (thenote->mid_c_offset, thenote->enshift)));
1255 GtkWidget *frame = gtk_frame_new (text->str);
1256 gtk_container_set_border_width (GTK_CONTAINER (frame), 20);
1257 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1258 GdkRGBA color;
1259 get_color (&color, 0.8, 0.1, 0.1, 1.0);//color.red = 0.8;color.green = color.blue = 0.1; color.alpha = 1;
1260 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1261 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1262 }
1263
1264 g_string_free (text, TRUE);
1265
1266 }
1267 if ((thechord->notes) && curObj->isinvisible)
1268 {
1269 GtkWidget *button = gtk_button_new_with_label (_("Assign Pitch to Rhythm"));
1270 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &curObj->isinvisible);
1271 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1272 }
1273 }
1274 else
1275 {
1276 //type = _("rest");
1277 place_chord_attributes (vbox, thechord);
1278
1279 }
1280 if (thechord->fakechord)
1281 {
1282 GtkWidget *button = gtk_button_new_with_label (_("Edit Chord Symbol"));
1283 g_signal_connect (button, "clicked", G_CALLBACK (run_script), "(d-EditChords)");
1284 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1285 }
1286
1287 if (thechord->figure)
1288 {
1289 GtkWidget *button = gtk_button_new_with_label (_("Edit Bass Figure"));
1290 g_signal_connect (button, "clicked", G_CALLBACK (run_script), "(d-EditFiguredBass)");
1291 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1292 }
1293
1294 {
1295 GtkWidget *separator =
1296 #if GTK_MAJOR_VERSION == 2
1297 gtk_hseparator_new ();
1298 #else
1299 gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
1300 #endif
1301 gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
1302
1303 GtkWidget *button = gtk_button_new_with_label (_("Add/Remove attributes"));
1304 g_signal_connect (button, "clicked", G_CALLBACK (general_edit_popup), EDIT_CHORD);
1305 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1306 }
1307
1308 }
1309 break;
1310 case TUPOPEN:
1311 { tuplet *thetup = ((tuplet *) curObj->object);
1312 //type = _("start tuplet marker");
1313 GtkWidget *button = gtk_button_new_with_label (_("Alter Tuplet Type"));
1314 g_signal_connect_swapped (button, "clicked", G_CALLBACK (call_out_to_guile), "(d-StartTuplet)");
1315 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1316 if (thetup->directives)
1317 {
1318 GtkWidget *frame = gtk_frame_new (_("Attached to the tuplet start:"));
1319 GdkRGBA color;
1320 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1321 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1322 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1323 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1324 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1325 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1326 place_directives (inner_box, &thetup->directives, EDIT_TUPLET_START);
1327 }
1328 }
1329 break;
1330 case TUPCLOSE:
1331 { tuplet *thetup = ((tuplet *) curObj->object);
1332 //type = _("start tuplet marker");
1333 if (thetup->directives)
1334 {
1335 GtkWidget *frame = gtk_frame_new (_("Attached to the tuplet end:"));
1336 GdkRGBA color;
1337 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1338 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1339 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1340 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1341 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1342 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1343 place_directives (inner_box, &thetup->directives, EDIT_TUPLET_END);
1344 }
1345 }
1346 break;
1347
1348 case CLEF:
1349 {
1350 clef *theclef = ((clef *) curObj->object);
1351 //type = _("clef change object");
1352
1353 if (theclef->directives)
1354 {
1355 GtkWidget *frame = gtk_frame_new (_("Attached to the clef change object:"));
1356 GdkRGBA color;
1357 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1358 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1359 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1360 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1361 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1362 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1363 place_directives (inner_box, &theclef->directives, EDIT_CLEF);
1364 }
1365 if (curObj->isinvisible)
1366 {
1367 GtkWidget *button = gtk_button_new_with_label (_("Transform to printing clef"));
1368 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &curObj->isinvisible);
1369 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1370 }
1371 }
1372 break;
1373
1374 case TIMESIG:
1375 {
1376 timesig *thetime = ((timesig *) curObj->object);
1377 //type = _("time signature change object");
1378 if (thetime->directives)
1379 {
1380 GtkWidget *frame = gtk_frame_new (_("Attached to the time signature change object:"));
1381 GdkRGBA color;
1382 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1383 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1384 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1385 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1386 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1387 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1388 place_directives (inner_box, &thetime->directives, EDIT_TIMESIG);
1389 }
1390 }
1391 break;
1392
1393 case KEYSIG:
1394 {
1395 keysig *thekey = ((keysig *) curObj->object);
1396 //type = _("key signature change object");
1397 if (thekey->directives)
1398 {
1399 GtkWidget *frame = gtk_frame_new (_("Attached to the key signature change object:"));
1400 GdkRGBA color;
1401 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1402 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1403 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1404 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1405 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1406 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1407 place_directives (inner_box, &thekey->directives, EDIT_KEY);
1408 }
1409 }
1410 break;
1411
1412
1413 case STEMDIRECTIVE:
1414 {
1415 stemdirective *thestem = ((stemdirective *) curObj->object);
1416 //type = _("stem direction change object");
1417 if (thestem->directives)
1418 {
1419 GtkWidget *frame = gtk_frame_new (_("Attached to the stemming change object:"));
1420 GdkRGBA color;
1421 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1422 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1423 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1424 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1425 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1426 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1427 place_directives (inner_box, &thestem->directives, EDIT_STEMDIR);
1428 }
1429
1430 }
1431 break;
1432
1433 case LILYDIRECTIVE:
1434 {
1435 DenemoDirective *directive = (DenemoDirective *) curObj->object;
1436 const gchar *label = get_label_for_command (directive->tag->str);
1437 GtkAction *action = lookup_action_from_name (directive->tag->str);
1438 gchar *name = label?(gchar*)label:directive->tag->str;
1439 const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
1440 gchar *filename = get_editscript_filename (directive->tag->str);
1441 GtkWidget *frame = gtk_frame_new ( _("Standalone Denemo Directive:"));
1442 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1443 GdkRGBA color;
1444 get_color (&color, 0.5, 0.5, 0.1, 1.0);// .red = 0.5;
1445 //color.green = 0.5; color.blue = 0.1; color.alpha = 1;
1446 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1447 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1448 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1449 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1450 gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1451 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1452
1453 if (filename)
1454 {
1455 gchar *thelabel = g_strconcat ( _("Run the Edit Script for "), name, NULL);
1456 GtkWidget *button = gtk_button_new_with_label (thelabel);
1457 g_signal_connect (button, "clicked", G_CALLBACK (execute_editscript), filename);
1458 g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), filename);
1459 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1460 g_free(thelabel);
1461 }
1462 else if (action)
1463 {
1464 gchar *thelabel = g_strconcat ( _("Execute command: "), name, NULL);
1465 GtkWidget *button = gtk_button_new_with_label (thelabel);
1466 gtk_widget_set_tooltip_text (button, _("Re-run the command to edit the Denemo Directive"));
1467
1468 g_object_set_data (G_OBJECT(button), "action", (gpointer)action);
1469 g_signal_connect (button, "clicked", G_CALLBACK (call_edit_on_action), NULL);
1470 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1471 g_free(thelabel);
1472 }
1473 {
1474 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1475 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1476
1477
1478 button = gtk_button_new_with_label (_("Delete"));
1479 GtkWidget *labelwidget = (GtkWidget *) gtk_bin_get_child (GTK_BIN (button));
1480 get_color (&color, 1.0, 0.0, 0.0, 1.0);
1481 //color.red = 1.0; color.green = color.blue = 0.0; color.alpha = 1.0;
1482 gtk_widget_override_color (labelwidget, GTK_STATE_FLAG_NORMAL, &color);
1483 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1484 g_signal_connect (button, "clicked", G_CALLBACK (delete_standalone), NULL);
1485 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 30);
1486
1487 button = gtk_button_new_with_label (_("Next ➡"));
1488 get_color (&color, 0.0, 0.7, 0.7, 1.0);
1489 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1490 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (seek_standalone_directive), (gpointer)label);
1491 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1492
1493 {
1494 button = gtk_button_new_with_label (_("Conditional"));
1495 get_color (&color, 0.0, 0., 0.5, 1.0);
1496 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1497
1498 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (call_out_to_guile), (gpointer)"(d-ChooseCondition #f)");
1499
1500 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1501 }
1502
1503 if (tooltip)
1504 {
1505 button = gtk_button_new_with_label (_("Help"));
1506 get_color (&color, 0.0, 0.7, 0.3, 1.0);//color.red = 0.0; color.green = 0.7, color.blue = 0.3; color.alpha = 1.0;
1507 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1508 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (display_help), (gpointer)tooltip);
1509 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1510 }
1511 if (tooltip == NULL) tooltip = _("No tooltip");
1512
1513 if (action) {
1514 button = gtk_button_new_with_label (_("Create Button for Command"));
1515 gtk_widget_set_tooltip_text (button, _( "Make a palette button for running the command that created/inserted this object."));
1516 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1517 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (create_palette_button_for_command), (gpointer)tooltip);
1518 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1519 }
1520 button = gtk_button_new_with_label (_("Create Button for Clone"));
1521 gtk_widget_set_tooltip_text (button, _( "Make a palette button for inserting a clone of this object elsewhere."));
1522 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1523 g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_directive), "standalone");
1524 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1525
1526 button = gtk_button_new_with_label (_("Advanced"));
1527 g_object_set_data (G_OBJECT(button), "directives", NULL);
1528 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1529 g_signal_connect (button, "clicked", G_CALLBACK (advanced_edit_type_directive), text_edit_standalone_directive);
1530 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1531 }
1532 }
1533 break;
1534
1535 default:
1536 g_critical ("Type not done");
1537 break;
1538 }
1539 if(g_list_length ( gtk_container_get_children (GTK_CONTAINER(vbox))) == 1)
1540 {//just the close button
1541 warningdialog ("Nothing editable on this object\nYou can add attributes to the object at the cursor by right-clicking on it.");
1542 gtk_widget_destroy (editwin);
1543 }
1544 else
1545 {
1546 if (note_up_button)
1547 gtk_widget_set_sensitive (note_up_button, FALSE);
1548 gtk_widget_show_all (editwin);
1549 gtk_window_present (GTK_WINDOW (editwin));
1550 gdk_window_set_cursor (gtk_widget_get_window (editwin), gdk_cursor_new (GDK_RIGHT_PTR));
1551 gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_X_CURSOR));
1552 if(ObjectInfo)
1553 gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_X_CURSOR));
1554 if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
1555 gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_X_CURSOR));
1556 #ifdef G_OS_WIN32
1557 if(ObjectInfo)
1558 gtk_widget_hide (ObjectInfo);//windows doesn't handle order properly, so this can hide the object editor
1559 #endif
1560 }
1561 }
1562
1563
1564
1565
1566
1567
score_update_and_close(GtkWidget * editwin)1568 static void score_update_and_close (GtkWidget *editwin)
1569 {
1570 gtk_widget_destroy (editwin);
1571 reset_cursors ();
1572 }
go_previous(GtkWidget * editwin)1573 static void go_previous(GtkWidget *editwin)
1574 {
1575 prev_movement (NULL, NULL);//FIXME pass in a DenemoParam * to get status
1576 if (editwin)
1577 {
1578 gtk_widget_destroy (editwin);
1579 reset_cursors ();
1580 edit_movement_properties();
1581 }
1582 }
go_next(GtkWidget * editwin)1583 static void go_next(GtkWidget *editwin)
1584 {
1585 next_movement (NULL, NULL);//FIXME pass in a DenemoParam * to get status
1586 if (editwin)
1587 {
1588 gtk_widget_destroy (editwin);
1589 reset_cursors ();
1590 edit_movement_properties();
1591 }
1592 }
1593 typedef gboolean fn2_type (DenemoDirective*);
low_level_edit_type_directive(GtkWidget * button,gpointer fn)1594 static void low_level_edit_type_directive (GtkWidget *button, gpointer fn)
1595 {
1596 gtk_widget_hide (gtk_widget_get_toplevel (button));
1597 DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
1598 GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
1599 if (!( ((fn2_type *)fn) (directive)))
1600 {
1601 if(directives)
1602 *directives = g_list_remove (*directives, directive);
1603 gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
1604 score_status(Denemo.project, TRUE);
1605 }
1606 else
1607 show_window (button);//gtk_widget_show (gtk_widget_get_toplevel (button));
1608
1609 }
delete_score_directive(GtkWidget * button)1610 static void delete_score_directive (GtkWidget *button)
1611 {
1612 DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
1613 GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
1614 *directives = g_list_remove (*directives, directive);
1615 gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
1616 score_status(Denemo.project, TRUE);
1617 }
1618
place_buttons_for_directives(GList ** pdirectives,GtkWidget * vbox,DIRECTIVE_TYPE score_or_movement,gchar * field)1619 static void place_buttons_for_directives (GList **pdirectives, GtkWidget *vbox, DIRECTIVE_TYPE score_or_movement, gchar *field)
1620 {
1621 GList *g;
1622 gchar *type = "";
1623 if(!strcmp (field, "lilycontrol"))
1624 type = _( "Score ");
1625 else if(!strcmp (field, "movementcontrol"))
1626 type = _( "Movement ");
1627 else if(!strcmp (field, "scoreheader"))
1628 type = _( "Score Header ");
1629 else if(!strcmp (field, "paper"))
1630 type = _( "Paper ");
1631 else if(!strcmp (field, "header"))
1632 type = _( "Movement Header ");
1633 else if(!strcmp (field, "layout"))
1634 type = _( "Movement Layout ");
1635 for (g = *pdirectives; g; g = g->next)
1636 {
1637 DenemoDirective *directive = g->data;
1638 const gchar *label = get_label_for_command (directive->tag->str);
1639 GtkAction *action = lookup_action_from_name (directive->tag->str);
1640 gchar *name = label?(gchar*)label:directive->tag->str;
1641 const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
1642 gchar *filename = get_editscript_filename (directive->tag->str);
1643 GtkWidget *frame;
1644 gchar *text;
1645 if (label == NULL)
1646 text = g_strdup_printf( _("Denemo %s Directive tagged: %s"), type, name);
1647 else
1648 text = g_strdup_printf (_("Denemo %s Directive: %s"), type, label);
1649 frame = gtk_frame_new (text);
1650 g_free(text);
1651 //gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1652 GdkRGBA color;
1653 get_color (&color, 0.5, 0.5, 0.1, 1.0); //color.red = 0.5;
1654 //color.green = 0.5; color.blue = 0.1; color.alpha = 1;
1655 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1656 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1657 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1658 get_color (&color, 0.8, 0.8, 0.1, 1.0);
1659 gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1660 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1661 GtkWidget *button;
1662 if (filename)
1663 {
1664 gchar *thelabel = g_strconcat ( _("Run the Edit Script for "), name, NULL);
1665 button = gtk_button_new_with_label (thelabel);
1666 g_signal_connect (button, "clicked", G_CALLBACK (execute_editscript), filename);
1667 g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), filename);
1668 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1669 g_free(thelabel);
1670 }
1671 else if (action)
1672 {
1673 gchar *thelabel = g_strconcat ( _("Execute command: "), name, NULL);
1674 button = gtk_button_new_with_label (thelabel);
1675 gtk_widget_set_tooltip_text (button, _("Re-run the command to edit the Denemo Directive"));
1676
1677 g_object_set_data (G_OBJECT(button), "action", (gpointer)action);
1678 g_signal_connect (button, "clicked", G_CALLBACK (call_edit_on_action), GINT_TO_POINTER(score_or_movement));
1679 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1680 g_free(thelabel);
1681 }
1682 if (tooltip)
1683 gtk_widget_set_tooltip_text (button, tooltip);
1684
1685 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1686 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1687
1688 button = gtk_button_new_with_label (_("Delete"));
1689 GtkWidget *labelwidget = (GtkWidget *) gtk_bin_get_child (GTK_BIN (button));
1690 get_color (&color, 1.0, 0.0, 0.0, 1.0);
1691 //color.red = 1.0; color.green = color.blue = 0.0; color.alpha = 1.0;
1692 gtk_widget_override_color (labelwidget, GTK_STATE_FLAG_NORMAL, &color);
1693 g_object_set_data (G_OBJECT(button), "directives", (gpointer)pdirectives);
1694 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1695 g_signal_connect (button, "clicked", G_CALLBACK (delete_score_directive), NULL);
1696 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 30);
1697
1698 if (tooltip)
1699 {
1700 button = gtk_button_new_with_label (_("Help"));
1701 get_color (&color, 0.0, 0.7, 0.3, 1.0);
1702 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1703 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (display_help), (gpointer)tooltip);
1704 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1705 }
1706 if (tooltip == NULL) tooltip = _("No tooltip");
1707
1708 if (action) {
1709 button = gtk_button_new_with_label (_("Create Button for Command"));
1710 gtk_widget_set_tooltip_text (button, _( "Make a palette button for running the command that created this attribute."));
1711 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1712 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (create_palette_button_for_command), (gpointer)tooltip);
1713 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1714 }
1715 button = gtk_button_new_with_label (_("Create Button for Clone"));
1716 gtk_widget_set_tooltip_text (button, _( "Make a palette button for installing a clone of this attribute elsewhere."));
1717 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1718 g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_directive), (gpointer)(field));
1719 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1720
1721
1722 button = gtk_button_new_with_label (_("Advanced"));
1723 g_object_set_data (G_OBJECT(button), "directives", pdirectives);
1724 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1725 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (low_level_edit_type_directive), low_level_directive_edit);
1726 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1727
1728
1729
1730
1731
1732 }
1733 }
1734
1735
1736 static void
edit_score_and_movement_properties(gboolean show_score)1737 edit_score_and_movement_properties (gboolean show_score)
1738 {
1739 GtkWidget *editscorewin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1740 GdkRGBA color;
1741 gint window_height = 800;
1742 //color.red = color.green = color.blue = color.alpha = 1.0;
1743 get_color (&color, 1.0, 1.0, 1.0, 1.0);
1744 gtk_widget_override_background_color (editscorewin, GTK_STATE_FLAG_NORMAL, &color);
1745 gtk_window_set_modal (GTK_WINDOW (editscorewin), TRUE);
1746 gtk_window_set_title (GTK_WINDOW (editscorewin), _("Score and Movement Properties Editor"));
1747 gtk_window_set_transient_for (GTK_WINDOW(editscorewin), GTK_WINDOW(Denemo.window));
1748 gtk_window_set_keep_above (GTK_WINDOW (editscorewin), TRUE);
1749 gtk_window_set_default_size (GTK_WINDOW (editscorewin), 600, window_height);
1750
1751
1752 GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1753 gtk_container_add (GTK_CONTAINER (editscorewin), vbox);
1754 GtkWidget *close_button = gtk_button_new_with_label (_("Close"));
1755 g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (score_update_and_close), editscorewin);
1756
1757 g_signal_connect (G_OBJECT (editscorewin), "destroy", G_CALLBACK (reset_cursors), NULL);
1758 gtk_box_pack_start (GTK_BOX (vbox), close_button, FALSE, TRUE, 0);
1759
1760 GtkWidget *button;
1761 GtkWidget *pane;
1762 #if GTK_MAJOR_VERSION == 2
1763 pane = gtk_vpaned_new ();
1764 #else
1765 pane = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
1766 #endif
1767 gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
1768 GtkWidget *expander = gtk_expander_new (_("Score Properties"));
1769 gtk_expander_set_expanded (GTK_EXPANDER(expander), show_score);
1770 gtk_widget_set_sensitive (expander, TRUE);
1771 gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1772 get_color (&color, 0.1, 0.8, 0.1, 1.0);
1773
1774 gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1775 // gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
1776
1777 GtkWidget *frame = gtk_frame_new (NULL);
1778 //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1779
1780
1781
1782 gtk_paned_add1 (GTK_PANED(pane), frame);
1783
1784 gtk_container_add (GTK_CONTAINER (frame), expander);
1785
1786 GtkWidget *scrolled_window = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
1787
1788 gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
1789
1790 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1791 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_window), inner_box);
1792
1793 button = gtk_button_new_with_label (_("Edit Built-in Score Properties"));
1794 g_signal_connect (button, "clicked", G_CALLBACK (call_score_properties_dialog), NULL);
1795 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1796
1797 place_buttons_for_directives ((GList**)&Denemo.project->lilycontrol.directives, inner_box, DIRECTIVE_SCORE, "lilycontrol");
1798 place_buttons_for_directives ((GList**)&Denemo.project->scoreheader, inner_box, DIRECTIVE_SCORE, "scoreheader");
1799 place_buttons_for_directives ((GList**)&Denemo.project->paper, inner_box, DIRECTIVE_SCORE, "paper");
1800
1801
1802
1803 gchar *mnum = g_strdup_printf ("%s %d %s", _("Movement"), Denemo.project->movement->currentmovementnum, _("Properties"));
1804 expander = gtk_expander_new (mnum);
1805 g_free(mnum);
1806 gtk_expander_set_expanded (GTK_EXPANDER(expander), !show_score);
1807 gtk_widget_set_sensitive (expander, TRUE);
1808 gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1809 get_color (&color, 0.1, 0.1, 0.8, 1.0);
1810
1811 gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1812
1813 frame = gtk_frame_new (NULL);
1814 //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1815
1816 gtk_paned_add2 (GTK_PANED(pane), frame);
1817 gtk_container_add (GTK_CONTAINER (frame), expander);
1818
1819 scrolled_window = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
1820 gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
1821 inner_box = gtk_vbox_new (FALSE, 0);
1822 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_window), inner_box);
1823
1824 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1825 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1826
1827 button = gtk_button_new_with_label (_("⬅ Previous Movement"));
1828 g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_previous), editscorewin);
1829 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1830
1831 if ( Denemo.project->movement->currentmovementnum == 1)
1832 gtk_widget_set_sensitive (button, FALSE);
1833
1834 button = gtk_button_new_with_label (_("Next Movement ➡"));
1835 g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_next), editscorewin);
1836 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1837 if (g_list_length(Denemo.project->movements) == Denemo.project->movement->currentmovementnum)
1838 gtk_widget_set_sensitive (button, FALSE);
1839
1840
1841 place_buttons_for_directives ((GList**)&Denemo.project->movement->movementcontrol, inner_box, DIRECTIVE_MOVEMENT, "movementcontrol");
1842 place_buttons_for_directives ((GList**)&Denemo.project->movement->header, inner_box, DIRECTIVE_MOVEMENT, "header");
1843 place_buttons_for_directives ((GList**)&Denemo.project->movement->layout, inner_box, DIRECTIVE_MOVEMENT, "layout");
1844
1845 gtk_paned_set_position (GTK_PANED(pane), show_score? window_height-50 : 50);
1846
1847
1848
1849 if(g_list_length ( gtk_container_get_children (GTK_CONTAINER(vbox))) == 1)
1850 {//just the close button
1851 warningdialog ("No properties have been set on the current score.");
1852 gtk_widget_destroy (editscorewin);
1853 }
1854 else
1855 {
1856 gtk_widget_show_all (editscorewin);
1857 gtk_window_present (GTK_WINDOW (editscorewin));
1858 gdk_window_set_cursor (gtk_widget_get_window (editscorewin), gdk_cursor_new (GDK_RIGHT_PTR));
1859 gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_X_CURSOR));
1860 if(ObjectInfo)
1861 gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_X_CURSOR));
1862 if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
1863 gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_X_CURSOR));
1864
1865 }
1866
1867 }
1868
1869
edit_score_properties(void)1870 void edit_score_properties (void)
1871 {
1872 edit_score_and_movement_properties (TRUE);
1873 }
1874
edit_movement_properties(void)1875 void edit_movement_properties (void)
1876 {
1877 edit_score_and_movement_properties (FALSE);
1878 }
1879
clef_change_initial_cb(GtkWidget * editstaffwin)1880 static void clef_change_initial_cb (GtkWidget *editstaffwin)
1881 {
1882 DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
1883 if(thestaff->voicecontrol != DENEMO_PRIMARY)
1884 warningdialog (_("The clef here only affects the display as this voice is typeset on the staff above.\nNormally you will want it set the same as the staff the notes will appear on.\nDismiss this warning and make any needed changes via the popup dialog coming next."));
1885 clef_change_initial (NULL, NULL);
1886 }
keysig_change_info(void)1887 static void keysig_change_info (void)
1888 {
1889 DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
1890 if(thestaff->voicecontrol != DENEMO_PRIMARY)
1891 {
1892 warningdialog (_("This voice should have the same key signature as the staff it appears on. Use the key signature menu commands to correct it if needed."));// warningdialog (param.string);
1893 }
1894 else
1895 {
1896 warningdialog (_("Change the keysignature by clicking on it, or via the Key Signatures menu (after closing this editor).")); //for some reason the change_key() call does not get the keyboard focus so we can't change the key here.
1897 }
1898 }
1899
timesig_change_initial_cb(GtkWidget * editstaffwin)1900 static void timesig_change_initial_cb (GtkWidget *editstaffwin)
1901 {
1902 DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
1903 if(thestaff->voicecontrol != DENEMO_PRIMARY)
1904 {
1905 warningdialog (_("This voice should have the same time signature as the staff it appears on. Use the time signature menu commands to correct it if needed."));// warningdialog (param.string);
1906 }
1907 else
1908 {
1909 timesig_change (Denemo.project, CHANGEINITIAL);
1910 gtk_widget_destroy (editstaffwin);
1911 edit_staff_and_voice_properties (TRUE);
1912 }
1913 }
staff_above(GtkWidget * editstaffwin)1914 static void staff_above (GtkWidget *editstaffwin)
1915 {
1916 movetostaffup (NULL, NULL);
1917 gtk_widget_destroy (editstaffwin);
1918 edit_staff_and_voice_properties (TRUE);
1919 }
staff_below(GtkWidget * editstaffwin)1920 static void staff_below (GtkWidget *editstaffwin)
1921 {
1922 movetostaffdown (NULL, NULL);
1923 gtk_widget_destroy (editstaffwin);
1924 edit_staff_and_voice_properties (TRUE);
1925 }
1926
change_staff_properties(GtkWidget * editstaffwin)1927 static void change_staff_properties (GtkWidget *editstaffwin)
1928 {
1929 gtk_widget_destroy (editstaffwin);
1930 staff_properties_change_cb (NULL, NULL);
1931 edit_staff_and_voice_properties (TRUE);
1932 }
1933 static void
edit_staff_and_voice_properties(gboolean show_staff)1934 edit_staff_and_voice_properties (gboolean show_staff)
1935 {
1936 GtkWidget *editstaffwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1937 GdkRGBA color;
1938 gint window_height = 800;
1939 get_color (&color, 1.0, 1.0, 1.0, 1.0);
1940 gtk_widget_override_background_color (editstaffwin, GTK_STATE_FLAG_NORMAL, &color);
1941 gtk_window_set_modal (GTK_WINDOW (editstaffwin), TRUE);
1942 gtk_window_set_title (GTK_WINDOW (editstaffwin), _("Staff and Voice Properties Editor"));
1943 gtk_window_set_transient_for (GTK_WINDOW(editstaffwin), GTK_WINDOW(Denemo.window));
1944 gtk_window_set_keep_above (GTK_WINDOW (editstaffwin), TRUE);
1945 gtk_window_set_default_size (GTK_WINDOW (editstaffwin), 600, window_height);
1946
1947
1948 GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1949 gtk_container_add (GTK_CONTAINER (editstaffwin), vbox);
1950 GtkWidget *close_button = gtk_button_new_with_label (_("Close"));
1951 g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (score_update_and_close), editstaffwin);
1952
1953 g_signal_connect (G_OBJECT (editstaffwin), "destroy", G_CALLBACK (reset_cursors), NULL);
1954 gtk_box_pack_start (GTK_BOX (vbox), close_button, FALSE, TRUE, 0);
1955
1956 GtkWidget *button;
1957 GtkWidget *pane;
1958 #if GTK_MAJOR_VERSION == 2
1959 pane = gtk_vpaned_new ();
1960 #else
1961 pane = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
1962 #endif
1963 gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
1964 GtkWidget *expander = gtk_expander_new (_("Staff Properties"));
1965 gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
1966 gtk_widget_set_sensitive (expander, TRUE);
1967 gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1968 get_color (&color, 0.1, 0.1, 0.8, 1.0);
1969 gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1970 // gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
1971
1972 GtkWidget *frame = gtk_frame_new (NULL);
1973 //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1974
1975
1976
1977 gtk_paned_add1 (GTK_PANED(pane), frame);
1978
1979 gtk_container_add (GTK_CONTAINER (frame), expander);
1980
1981 GtkWidget *scrolled_window = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
1982 gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
1983
1984 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1985 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_window), inner_box);
1986 GtkWidget *inner_hbox;
1987 inner_hbox = gtk_hbox_new (FALSE, 0);
1988 gtk_box_pack_start (GTK_BOX (inner_box), inner_hbox, FALSE, TRUE, 0);
1989 button = gtk_button_new_with_label (_("Staff Above"));
1990 g_signal_connect_swapped (button, "clicked", G_CALLBACK (staff_above), editstaffwin);
1991 gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
1992
1993 if ( Denemo.project->movement->currentstaffnum == 1)
1994 gtk_widget_set_sensitive (button, FALSE);
1995
1996 button = gtk_button_new_with_label (_("Staff Below"));
1997 g_signal_connect_swapped (button, "clicked", G_CALLBACK (staff_below), editstaffwin);
1998 gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
1999 if (g_list_length(Denemo.project->movement->thescore) == Denemo.project->movement->currentstaffnum)
2000 gtk_widget_set_sensitive (button, FALSE);
2001 DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
2002 if(thestaff->voicecontrol != DENEMO_PRIMARY)
2003 {
2004 GtkWidget *label = gtk_label_new ("");
2005 gtk_label_set_markup (GTK_LABEL (label), _("<b>This voice will be typeset on the staff above</b>"));
2006 gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
2007 gtk_box_pack_start (GTK_BOX (inner_box), label, FALSE, TRUE, 0);
2008 }
2009 inner_hbox = gtk_hbox_new (FALSE, 0);
2010 gtk_box_pack_start (GTK_BOX (inner_box), inner_hbox, FALSE, TRUE, 0);
2011
2012 button = gtk_button_new_with_label (_("Edit Built-in Staff Properties"));
2013 g_signal_connect_swapped (button, "clicked", G_CALLBACK (change_staff_properties), editstaffwin);
2014 gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2015
2016
2017 const gchar *theclef = get_clef_name (thestaff->clef.type);
2018 gchar *text = g_strconcat (_("Clef: "), theclef, NULL);
2019 button = gtk_button_new_with_label (text);
2020 g_signal_connect_swapped (button, "clicked", G_CALLBACK (clef_change_initial_cb), editstaffwin);
2021 gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2022 g_free (text);
2023
2024 text = g_strdup_printf (_("Time: %d/%d"), thestaff->timesig.time1, thestaff->timesig.time2);
2025 button = gtk_button_new_with_label (text);
2026 g_signal_connect_swapped (button, "clicked", G_CALLBACK (timesig_change_initial_cb), editstaffwin);
2027 gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2028 g_free (text);
2029
2030 text = g_strdup_printf (_("Key: %s"), get_lilypond_for_keysig (&(thestaff->keysig)));
2031 button = gtk_button_new_with_label (text);
2032 g_signal_connect (button, "clicked", G_CALLBACK (keysig_change_info), NULL);
2033 gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2034 g_free (text);
2035
2036
2037 place_buttons_for_directives ((GList**)&thestaff->staff_directives, inner_box, DIRECTIVE_STAFF, "staff");
2038 if(thestaff->keysig.directives)
2039 {
2040 GtkWidget *label = gtk_label_new (_("Key Signature Directives"));
2041 gtk_box_pack_start (GTK_BOX (inner_box), label, FALSE, TRUE, 0);
2042 place_buttons_for_directives ((GList**)&(thestaff->keysig.directives), inner_box, DIRECTIVE_KEYSIG, "keysig");
2043 }
2044 if(thestaff->timesig.directives)
2045 {
2046 GtkWidget *label = gtk_label_new (_("Time Signature Directives"));
2047 gtk_box_pack_start (GTK_BOX (inner_box), label, FALSE, TRUE, 0);
2048 place_buttons_for_directives ((GList**)&(thestaff->timesig.directives), inner_box, DIRECTIVE_TIMESIG, "timesig");
2049 }
2050
2051
2052 expander = gtk_expander_new (_("Voice Properties"));
2053
2054 gtk_expander_set_expanded (GTK_EXPANDER(expander),TRUE);
2055 gtk_widget_set_sensitive (expander, TRUE);
2056 gtk_container_set_border_width (GTK_CONTAINER (expander),10);
2057 get_color (&color, 0.1, 0.1, 0.8, 1.0);
2058 gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
2059
2060 frame = gtk_frame_new (NULL);
2061 //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2062
2063 gtk_paned_add2 (GTK_PANED(pane), frame);
2064 gtk_container_add (GTK_CONTAINER (frame), expander);
2065
2066 scrolled_window = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
2067 gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
2068 inner_box = gtk_vbox_new (FALSE, 0);
2069 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_window), inner_box);
2070
2071 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
2072 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
2073
2074
2075
2076
2077 place_buttons_for_directives ((GList**)&thestaff->voice_directives, inner_box, DIRECTIVE_VOICE, "voice");
2078
2079
2080 gtk_paned_set_position (GTK_PANED(pane), window_height/2);
2081
2082
2083
2084 if(g_list_length ( gtk_container_get_children (GTK_CONTAINER(vbox))) == 1)
2085 {//just the close button
2086 warningdialog ("No properties have been set on the current score.");
2087 gtk_widget_destroy (editstaffwin);
2088 }
2089 else
2090 {
2091 gtk_widget_show_all (editstaffwin);
2092 gtk_window_present (GTK_WINDOW (editstaffwin));
2093 gdk_window_set_cursor (gtk_widget_get_window (editstaffwin), gdk_cursor_new (GDK_RIGHT_PTR));
2094 gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_X_CURSOR));
2095 if(ObjectInfo)
2096 gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_X_CURSOR));
2097 if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
2098 gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_X_CURSOR));
2099
2100 }
2101
2102 }
2103 void
edit_staff_properties(void)2104 edit_staff_properties (void)
2105 {
2106 edit_staff_and_voice_properties (TRUE);
2107 }
2108 void
edit_voice_properties(void)2109 edit_voice_properties (void)
2110 {
2111 edit_staff_and_voice_properties (FALSE);
2112 }
2113
2114
2115
2116
2117 void
set_modeaccs(gint * accs,gint number,gint mode)2118 set_modeaccs (gint * accs, gint number, gint mode)
2119 {
2120
2121 g_debug ("Mode %d : %d \n", number, mode);
2122 if (mode == 0)
2123 {
2124 switch (number)
2125 {
2126 case 11:
2127 number -= 7;
2128 break;
2129 }
2130 initkeyaccs (accs, number);
2131
2132 }
2133 else if (mode == 2)
2134 initkeyaccs (accs, 0);
2135 else if (number == 1 && mode == 1)
2136 initkeyaccs (accs, 0);
2137 }
2138
2139 /**
2140 * This function initializes the accidental-context array associated with
2141 * a key signature or a staff to that appropriate for _number_
2142 */
2143 void
initkeyaccs(gint * accs,gint number)2144 initkeyaccs (gint * accs, gint number)
2145 {
2146 int index;
2147 memset (accs, 0, SEVENGINTS);
2148 if (number > 0)
2149 for (index = 3; number; number--, index = (index + 4) % 7)
2150 accs[index] = 1;
2151 else if (number < 0)
2152 for (index = 6; number; number++, index = (index + 3) % 7)
2153 accs[index] = -1;
2154
2155 }
2156
2157 /**
2158 * Create a new measure break object
2159 * @return the measurebreak
2160 */
2161 DenemoObject *
newmeasurebreakobject()2162 newmeasurebreakobject ()
2163 {
2164 DenemoObject *ret;
2165
2166 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2167 ret->type = MEASUREBREAK;
2168 return ret;
2169 }
2170
2171 /**
2172 * Create a new staff break object
2173 * @return the staffbreak
2174 */
2175 DenemoObject *
newstaffbreakobject()2176 newstaffbreakobject ()
2177 {
2178 DenemoObject *ret;
2179 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2180 ret->type = STAFFBREAK;
2181 return ret;
2182 }
2183
2184 /* clone the directive, excluding the widget */
2185 DenemoDirective *
clone_directive(DenemoDirective * directive)2186 clone_directive (DenemoDirective * directive)
2187 {
2188 DenemoDirective *ret = (DenemoDirective *) g_malloc0 (sizeof (DenemoDirective));
2189 memcpy (ret, directive, sizeof (DenemoDirective)); //BEWARE all pointers in DenemoDirective require code, as follows:
2190 #define CLONE(field) \
2191 if(directive->field && directive->field->len)\
2192 ret->field = g_string_new(directive->field->str);\
2193 else\
2194 ret->field = NULL;
2195 CLONE (tag);
2196 CLONE (prefix);
2197 CLONE (postfix);
2198 CLONE (display);
2199 CLONE (graphic_name);
2200 CLONE (grob);
2201 CLONE (midibytes);
2202 CLONE (data);
2203 #undef CLONE
2204 if (directive->graphic)
2205 {
2206 ret->graphic = directive->graphic; //alternatively could load it via loadGraphicItem, is the same
2207 }
2208 if (directive->widget)
2209 {
2210 // gpointer fn = g_object_get_data(G_OBJECT(directive->widget), "fn");
2211 ret->widget = NULL; //FIXME call widget_for_directive here???
2212 // widget_for_directive(ret, fn);
2213 }
2214 return ret;
2215 }
2216
2217
2218 GList *
clone_directives(GList * directives)2219 clone_directives (GList * directives)
2220 {
2221 GList *ret = NULL;
2222 for (; directives; directives = directives->next)
2223 ret = g_list_append (ret, clone_directive (directives->data));
2224 return ret;
2225 }
2226
2227 void
free_directive_data(DenemoDirective * directive)2228 free_directive_data (DenemoDirective * directive)
2229 {
2230 #define DFREE(field) if(directive->field) g_string_free(directive->field, TRUE);
2231 DFREE (tag);
2232 DFREE (display);
2233 DFREE (prefix);
2234 DFREE (postfix);
2235 DFREE (graphic_name);
2236 DFREE (grob);
2237 #undef DFREE
2238
2239 if (directive->widget && !G_IS_OBJECT (directive->widget))
2240 {
2241 g_debug ("Found non-gobject widget %p\n", directive->widget);
2242 }
2243 if (directive->widget && G_IS_OBJECT (directive->widget))
2244 {
2245 //g_debug("We should destroy the widget now ");
2246 GtkWidget *texteditor = (GtkWidget *) g_object_get_data (G_OBJECT (directive->widget), DENEMO_TEXTEDITOR_TAG);
2247 if (texteditor)
2248 gtk_widget_destroy (texteditor); //FIXME we may need to destroy its parents
2249 gtk_widget_destroy ((GtkWidget *) directive->widget);
2250 }
2251
2252
2253
2254 }
2255
2256 void
free_directive(DenemoDirective * directive)2257 free_directive (DenemoDirective * directive)
2258 {
2259 free_directive_data (directive);
2260 g_free (directive);
2261 }
2262
2263 void
free_directives(GList * directives)2264 free_directives (GList * directives)
2265 {
2266 for (; directives; directives = directives->next)
2267 {
2268 DenemoDirective *directive = directives->data;
2269 free_directive (directive);
2270 }
2271 g_list_free (directives);
2272 }
2273
2274 /**
2275 * Create a clone of the given object
2276 * @param orig the object to clone
2277 * @return the cloned object
2278 */
2279 DenemoObject *
dnm_clone_object(DenemoObject * orig)2280 dnm_clone_object (DenemoObject * orig)
2281 {
2282 DenemoObject *ret = NULL;
2283 if (orig != NULL)
2284 {
2285 switch (orig->type)
2286 {
2287 case CHORD:
2288 ret = clone_chord (orig);
2289 break;
2290
2291 case TUPOPEN:
2292 ret = (DenemoObject *) tuplet_open_new (((tupopen *) orig->object)->numerator, ((tupopen *) orig->object)->denominator);
2293 ((tupopen *) ret->object)->directives = clone_directives (((tupopen *) orig->object)->directives);
2294
2295 break;
2296 case TUPCLOSE:
2297 ret = (DenemoObject *) tuplet_close_new ();
2298 ((tupopen *) ret->object)->directives = clone_directives (((tupopen *) orig->object)->directives);
2299
2300 break;
2301 case CLEF:
2302 ret = clef_new (((clef *) orig->object)->type);
2303 ((clef *) ret->object)->directives = clone_directives (((clef *) orig->object)->directives);
2304 break;
2305 case TIMESIG:
2306 ret = dnm_newtimesigobj (((timesig *) orig->object)->time1, ((timesig *) orig->object)->time2);
2307 ((timesig *) ret->object)->directives = clone_directives (((timesig *) orig->object)->directives);
2308
2309 break;
2310 case KEYSIG:
2311 ret = dnm_newkeyobj (((keysig *) orig->object)->number, ((keysig *) orig->object)->isminor, ((keysig *) orig->object)->mode);
2312 ((keysig *) ret->object)->directives = clone_directives (((keysig *) orig->object)->directives);
2313
2314 break;
2315 break;
2316 case STEMDIRECTIVE:
2317 ret = dnm_stem_directive_new (((stemdirective *) orig->object)->type);
2318
2319 ((stemdirective *) ret->object)->directives = clone_directives (((stemdirective *) orig->object)->directives);
2320
2321 break;
2322 case MEASUREBREAK:
2323 ret = newmeasurebreakobject ();
2324 break;
2325 case STAFFBREAK:
2326 ret = newstaffbreakobject ();
2327 break;
2328 case LILYDIRECTIVE:
2329 {
2330 lilydirective *curlily = (lilydirective *) orig->object;
2331 ret = directive_object_new (clone_directive (curlily));
2332 ret->durinticks = orig->durinticks;
2333 ret->basic_durinticks = orig->basic_durinticks;
2334
2335 }
2336 break;
2337 default:
2338 g_warning ("Unknown object type %x", orig->type);
2339 ret = lily_directive_new ("%unknown object\n");
2340 break;
2341 }
2342 }
2343 if(ret){
2344 if (orig->lilypond)
2345 ret->lilypond = g_strdup (orig->lilypond);
2346 else
2347 ret->lilypond = NULL;
2348
2349 ret->isinvisible = orig->isinvisible;
2350 }
2351 return ret;
2352 }
2353
2354 /**
2355 * Create a new stem directive
2356 * @param type the stem directive type
2357 * @return the stem directive
2358 */
2359 DenemoObject *
dnm_stem_directive_new(enum stemdirections type)2360 dnm_stem_directive_new (enum stemdirections type)
2361 {
2362 DenemoObject *ret;
2363 stemdirective *newstemdir = (stemdirective *) g_malloc (sizeof (stemdirective));
2364 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2365 ret->type = STEMDIRECTIVE;
2366 ret->isinvisible = FALSE;
2367 newstemdir->type = type;
2368 ret->object = newstemdir;
2369 set_basic_numticks (ret);
2370 setpixelmin (ret);
2371 return ret;
2372 }
2373
2374 /**
2375 * Create a new lilypond directive
2376 *
2377 * @param type the lilypond directive body
2378 * @return the lilypond directive
2379 *
2380 */
2381 DenemoObject *
lily_directive_new(gchar * type)2382 lily_directive_new (gchar * type)
2383 {
2384 DenemoObject *ret;
2385 lilydirective *newlily = (lilydirective *) g_malloc0 (sizeof (lilydirective));
2386 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2387 ret->type = LILYDIRECTIVE;
2388 newlily->postfix = g_string_new (type);
2389 ret->object = newlily;
2390 set_basic_numticks (ret);
2391 setpixelmin (ret);
2392 return ret;
2393 }
2394
2395 DenemoObject *
directive_object_new(DenemoDirective * directive)2396 directive_object_new (DenemoDirective * directive)
2397 {
2398 DenemoObject *ret;
2399 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2400 ret->type = LILYDIRECTIVE;
2401 ret->object = directive;
2402 set_basic_numticks (ret);
2403 setpixelmin (ret);
2404 return ret;
2405 }
2406
2407 /**
2408 * Create a new dynamic object
2409 * @param type the dynamic to create
2410 * @return the dynamic
2411 */
2412 DenemoObject *
dynamic_new(gchar * type)2413 dynamic_new (gchar * type)
2414 {
2415 DenemoObject *ret;
2416 dynamic *newdyn = (dynamic *) g_malloc0 (sizeof (dynamic));
2417 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2418 ret->type = DYNAMIC;
2419 ret->isinvisible = FALSE;
2420 newdyn->type = g_string_new (type);
2421 ret->object = newdyn;
2422 set_basic_numticks (ret);
2423 setpixelmin (ret);
2424 return ret;
2425 }
2426
2427 /**
2428 * Create a new lyric object
2429 * @param type the lyric to create
2430 * @param position whether it shoul be centered or not
2431 * @param syllable whether it is a syllable
2432 * @return the dynamic
2433 */
2434 DenemoObject *
dnm_lyric_new(gchar * type,gint position,gboolean syllable)2435 dnm_lyric_new (gchar * type, gint position, gboolean syllable)
2436 {
2437 DenemoObject *ret;
2438 lyric *newlyric = (lyric *) g_malloc0 (sizeof (lyric));
2439 ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2440 ret->type = LYRIC;
2441 ret->isinvisible = FALSE;
2442
2443
2444 newlyric->lyrics = g_string_new (type);
2445 newlyric->position = position;
2446 newlyric->is_syllable = syllable;
2447 ret->object = newlyric;
2448 set_basic_numticks (ret);
2449 setpixelmin (ret);
2450 return ret;
2451 }
2452
2453 /**
2454 * Create a DenemoObject
2455 * @param type DenemoObject type
2456 * @return the DenemoObject
2457 */
2458
2459 DenemoObject *
dnm_newobj(DenemoObjType type)2460 dnm_newobj (DenemoObjType type)
2461 {
2462 DenemoObject *ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));;
2463 ret->type = type;
2464 set_basic_numticks (ret);
2465 setpixelmin (ret); /* these do nothing at present - but if we introduce
2466 a show markers option then we will want to allot
2467 some space
2468 */
2469 return ret;
2470 }
2471
2472 /**
2473 * Set the key signature into the score
2474 * @param curstaff the current staff
2475 * @param tokey the key sig to insert
2476 * @param type major/minor/mode
2477 */
2478 void
dnm_setinitialkeysig(DenemoStaff * curstaff,gint tokey,gint type)2479 dnm_setinitialkeysig (DenemoStaff * curstaff, gint tokey, gint type)
2480 {
2481 take_snapshot ();
2482 curstaff->keysig.number = tokey;
2483 curstaff->keysig.isminor = type;
2484
2485 initkeyaccs (curstaff->keysig.accs, tokey);
2486 curstaff->leftmost_keysig = &curstaff->keysig;
2487 staff_show_which_accidentals (curstaff);
2488 adjust_tonal_center (curstaff->keysig.accs);
2489 displayhelper (Denemo.project);
2490 score_status(Denemo.project, TRUE);
2491 }
2492