parameter for distance between fret diagram and chord symbol doesn't do anything

• Feb 3, 2014 - 12:11
Type
Functional
Severity
S4 - Minor
Status
closed
Project

See #24349: Set the size of fretboard offset text as part of the style, esp. this comment :

"there is an existing parameter for distance between fret diagram and chord symbol, but that it doesn't seem to do anything. It seems from the code it affects chord symbol position *if* the chord symbol is a child of the fret diagram rather than of the segment, but I don't see any way to make that happen. I think this is leftover from when for a while there was a concept of a frame containing both?"

Maybe it should be made possible to select a fretboard diagram and than hit Strk-K to add a chord symbol to it?
Or have the fretboard diagram check whether a chord symbol is attached to the same chord and 'adopt' it?


Comments

I could be wrong, but I think the whole concept of a fretboard frame owning a chord symbol has gone away. So rather than try to make the fretboard diagram adopt the chord symbol - which would probably break other things - the better fix would be to simply check to see if there is a fretboard diagram on the same segment as the chord symbol.

I haven't tested to see if this code actually works or causes any other problems. But in theory at least, getting this option up and running could be as simple as taking the current code in Harmony::Layout() where it checks parent()->type() and uses one "yy" value for SEGMENT and another for FRET_DIAGRAM, and replacing it with code that loops through parent->annotations() (since as far as I can tell parent() is always SEGMENT) and, if it finds a FRET_DIAGRAM with the the same track() value as that of the Harmony object, using the ST_harmonyFretDist value - otherwise doing what it does now.

BTW, I might have assumed from the word of the option that this option sets the distance above the fret diagram and should hence be a small negative value, but it looks like this value is the actual vertical height above the staff, so it has to be big enough to clear the fret diagram. The style option should probably be re-wored to make this clear. Assuming it isn't easy to actually calculate the top of the fret diagram at this point in the code (it's possible it hasn't been computer yet) and apply this as an offset.

There are 2 scenarios:
1st the fretboard diagram is there first and the chord symbol added after
2nd the chord symbol entered first, the fret diagram after.
So either constructor needs to check for the existence of the other and put the chord symbol at the right place, in the latter case by moving it up, in the former case by creating it further up.
Also I'd consider it intuitive if selecting a fret diagram and doing a Ctrl-K would work too, currently it has to be a note or rest being selected.

BTW, see also #20676: Include chord name above fretboard diagram

I don't think the order they are created in matters. This isn't a constructor - it's the layout() function. layout() isn't called just once on creation of an element, but practically every time you touch anything at all (this is why performance degrades as scores get larger - every single element gets laid out anew on every single operation). So if you create the chord first, it will be laid out in its regular position, but the act of adding the fret diagram will cause layout() to be called again, and this time the fret diagram will be there in the annotation list.

It's probably relatively easy to make Ctrl+K work with a fret diagram selected, too. But considering that most chords are entered via Space or Tab after entering a previous chord, not by clicking individual notes, this change would not really likely to be much of win. You'd probably use that function once per score, then just hit Space or Tab from then on. Assuming you even did the fret diagrams first - my guess is, most people would add those later. So anyhow, if it's simple, sure, no reason not to go for it as far as I am concerned, but it's probably not as useful as the other things you've been looking at.

Nice catch finding that, but unless I'm mistaken, this still doesn't relate to the order in which the user adds the elements, but rather, the order in which they are laid out by MuseScore. That is, when it comes time to lay out segment "s" that has a chord symbol and fret diagram attached, this implies the chord symbol element gets laid out moments before the fret diagram - which unfortunately probably means you can't get a meaningful size/position value from the fret diagram while in Harmony::layout(), because you'll be looking at old values.

So regardless of what order the elements are added in, once both are present, all subsequent layout() operations will do the chord symbol before the fret diagram. The moment you add the chord symbol after the fret diagram - or vice versa - both are present, and ther very next layout operation (which will probably happen milliseconds later - I think most element creation operations conclude by calling layout() although I could be wrong) will lay them both out, and always in that same order.

Mhh, what's wrong about this, resp. why doesn't this work but crash instead?
Inserted at harmony.cpp, line 845
{syntaxhighlighter brush:cpp}
foreach(Element* e, *(parent()->links())) {
if (e != this && e->type() == FRET_DIAGRAM) {
setParent(e);
break;
}
}
{/syntaxhighlighter}

A couple of things.

First, I don't think it's links() you want - that's for linked staves/parts, I believe. Try annotations(). It's

Second, without testing it, I would reiterate what I said before - while there may at one time have been a concept in MuseScore of a frame that could contain a fret diagram and/or a chord symbol, that all seems to have been removed from the code. Everywhere else it appears to be assumed a chord symbol will have a segment as a parent. So you can't force a chord symbol to have a fret diagram as a parent - that's going break the assumptions made elsewhere. Instead of calling setParent() when you find a match, just set a flag. Then later you set the vertical position based on that.

Also, it looks like your code just checks for the existenceof a fret diagram on the same segment, but you want to make sure it's on the same staff, too. No sense adjusting the position of a chord symbol on the flute staff because of a fret diagram on the guitar staff.

Ah, getting closer...
something like this:

{syntaxhighlighter brush:cpp}
qreal yy = 0.0;
if (parent()->type() == SEGMENT) {
Measure* m = static_cast(parent()->parent());
yy = track() < 0 ? 0.0 : m->system()->staff(staffIdx())->y();
yy += score()->styleP(ST_harmonyY);
Segment* s = static_cast(parent());
for (Element* e : s->annotations()) {
if (e != this && e->type() == FRET_DIAGRAM && e->track() == track()) {
yy = score()->styleP(ST_harmonyFretDist);
yy -= score()->styleP(ST_staffFretDist);
// yy -= hight_of_fretboard_diagram;
break;
}
}
}
else if (parent()->type() == FRET_DIAGRAM)
yy = score()->styleP(ST_harmonyFretDist);
yy += textStyle().offset(spatium()).y();
{/syntaxhighlighter}