denemo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Denemo-devel] Custom menus


From: Richard Shann
Subject: Re: [Denemo-devel] Custom menus
Date: Thu, 03 Jul 2008 17:44:11 +0100

More design notes for the custom lilypond-insert menu items.

One of the commonest things to insert is a LilyPond directive that
applies to a section of the music. For example:

\transpose c c' {
several measures of music
}
would put the several measures up an octave. Likewise \repeat volta 2 {
starts a repeat, but requires a } to close it.

I think it will be worth giving some serious support to this. The
LilyPond directives would have an attribute with values
Open/Close/Standalone to set indicating if it requires a
following/previous LilyPond directive to Close/Open whatever it is
doing. (They can never cross).
When such a LilyPond directive is inserted into a measure it holds a
pointer (initially NULL) pointing to its partner. This pointer is filled
in whenever needed, by searching forward/backward for a LilyPond
directive with the correct attribute. Recall, they can never cross, so
the search for a partner may fail, leaving the pointer NULL. The search
can pass any number of nested Open/Close pairs before finding or failing
to find a partner.
Now, unless we adopt good object-oriented practice here, this is an open
invitation to dangling pointers. So, all deletions must go via the same
delete routines; I believe this has been followed in the Denemo code,
but it will be worth checking that no one has simply NULLed out a field
to make a chord or a measure or whatever vanish.
In particular if you cut a LilyPond directive and then paste it back the
delete routine for the LilyPond directive will remove the reference in
its partner before the cut, and will seek out its partner on paste.
Failing to find the partner just means it has a NULL pointer when pasted
back (if for instance it is pasted back in an impossible place). Such
unpartnered LilyPond directives can get special treatment: e.g. exclude
them from printing attempts, file save etc. And it should be possible to
help the user understand what/where they are.
I think it is better to allow unpartnered direcives than to try and
enforce the pairing programatically - this has been tried with the
tuplet insert and in other places, and has caused a lot of trouble.
In fact, there are several things in Denemo which could be subsumed into
the LilyDirective scheme. Slurs, for example, will not need special code
to handle them once the display of the LilyPond directives becomes
sophisticated enough. (At the moment, LilyPond directives display
themselves in the crudest possible way, but that could change).
If anyone can see any snags that I haven't foreseen please say.

Richard


On Mon, 2008-06-30 at 18:17 +0100, Richard Shann wrote:
> 
> On Mon, 2008-06-30 at 18:13 +0100, Richard Shann wrote:
> > 
> > Below is a design for how to incorporate custom lilypond-insert
menus
> > into Denemo, based on Jean-Rene`s code managing the keybindings.
> > What is described is the basic building block, an on-line gallery of
> > useful thumbnailed LilyPond directives contributed by users would be
a
> > final goal.
> > This is for 0.8.0 and I would like to start soon!
> > 
> > Design for including custom LilyPond insertion actions into Denemo.
> > 
> > The simple case of inserting a fixed LilyPond string is described
here.
> > The basic idea is that we can include custom commands in the keymap
> > file, which define an action name, label, location in the menu
system,
> > tooltip, keybinding,
> > and which when the keymap is loaded causes the menu item to be
inserted
> > and the command to appear in the command store (keymap->commands).
> > Activation is a callback to the function that inserts the LilyPond
> > directive.
> > To achieve this I propose to expand the 
> > typedef enum
> > {
> >     KeymapEntry,
> >     KeymapToggleEntry,
> >     KeymapRadioEntry,
> >     KeymapLilyPondAction,
> >     KeymapModeAction
> > }KeymapCommandType;
> > 
> > to include LilyPond and Mode command types (the COL_ENTRY column for
> > KeymapLilyPondEntry
> I meant KeymapLilyPondAction here and below (I changed the name when I
> realized you don't have a GtkActionEntry if you are creating actions
> programmatically)
> >  will be a  GtkAction*
> > while for KeymapModeEntry they will be GtkRadioAction* rather than a
> > GtkActionEntry*
> > I'll omit further details on how the KeymapModeAction type will work
for
> > now.
> > 
> > In save_keymap we save extra fields in each <row> which is found to
have
> > the type KeymapLilyPondEntry
> > the fields saved in this case are <type>, <tooltip>, <label>,
> > <lilypond>, <location>
> > 
> > In load keymap at parseBinding (rename this to parseAction) we parse
the
> > <type> and for
> > type KeymapLilyPondEntry instead of lookup_index_from_name we create
the
> > GtkAction (which will shortly have tooltip, label and lilypond
fields
> > attached) and register it - essentially this is the add_favorite
> > function I have already prototyped (in view.c). We also parse the
> > location and insert the menuitem in the menu system.
> > The tooltip etc which we attach to the action are now parsed as
well,
> > and attached to the action.
> > 
> > Then the code continues as a present.
> > When looking up the type, we have extra cases, e.g. in kbd-custom.c
as
> > well as
> > 
> >           case KeymapEntry:
> >               names[i] = ((GtkActionEntry *) entry)->name;
> >               break;
> > etc we have
> > 
> >           case KeymapLilyPondAction:
> >               names[i] = g_object_get_data(entry, "name");
> > //note: we could use
> > gtk_action_get_name(GTK_ACTION(entry));     but this would create a
copy of
> > the name, whereas the others are just references
> >               break;
> > 
> > another example is
> >       case KeymapEntry:
> >           f = (((GtkActionEntry *) row.entry)->callback);
> >           if (!f) {
> >             res = FALSE;
> >           }
> >           break;
> > which has the extra case
> >       case KeymapLilyPondAction:
> >           f = myactivate;
> >           break;
> > where myactivate is the name of the function attached to the action
in
> > the add_favorite routine (this name will need to be something
sensible,
> > to do with the fact that it is a custom lilypond activation).
> > 
> > at the end of the load, if we have registered new commands we
re-sort
> > the list using the end_register function.
> > 
> > That is all there is to it, I think.
> > comments please - particularly are there internationalization issues
> > which I don't understand?
> > Richard
> > 
> > 
> > 
> > _______________________________________________
> > Denemo-devel mailing list
> > address@hidden
> > http://lists.gnu.org/mailman/listinfo/denemo-devel
> 
> 
> 
> _______________________________________________
> Denemo-devel mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/denemo-devel






reply via email to

[Prev in Thread] Current Thread [Next in Thread]