Skip to content

Notes for implementing word wrap

Jack Pearson edited this page Mar 27, 2020 · 37 revisions

insert text frame command is called at scoreview.cpp::2312.

A text frame is a class TBox, defined in textframe.cpp

Also probably relevant: class Text, defined in text.cpp. Uses QXmlStreamReader.

ScoreView::startEdit also relevant.

^^ all of that is storage of text after it has been edited and the user pressed esc. Now I need to find how it's displayed in the editor (and also how it's drawn after it's been edited).

Maybe use UI to find what code is used for user editing? Text inspector used to change text properties?

mscore/inspector/inspector_stafftext

redrawing UI is done in MuseScore::endCmd

TextBlock::insert is indirectly called by TextBase::edit

TextBase has an array of TextBlocks, each of which is a row in TextBase. Each TextBase has an array of TextFragments.

TBox has a member Text* that is initialized to a new Text and never modified. So basically the text is just a normal member.

TextBase::drawEditMode draws some stuff. Maybe look for other draw functions?

Nah, TextBase::genText() is where you're gonna want to put your code. Looks like genText reads TextBase's TextBlocks and uses that to generate xml, which is the temporary, more easily readable version of the text. You can put your word wraps in there.

TextBase::genText() uses XmlWriter::xmlString(f.text) to make its text. The string it returns is probably where you'll want to put text wrapping. Actually it may make more sense naming and scope-wise to put that code in genText(). Just do it after the whole XML string has been generated.

Functions I'll add: TextBase::wordWrap, and a helper function that identifies a formatted character's width. Put it in XmlReader.

Test changes aren't working as expected. Try to understand more about textEdit.

So uh character insertion is actually done in score's undo function in textEdit.cpp::400. It calls redo internally.

TextBase::editInsertText calls cursor->curLine().insert(cursor, s), pretty sure this is where stuff happens.

REMINDER: verify that export music to XML still works after this and tests pass and make new tests

TextBase::endCmd uses genText to set the value of genText's associated TextBase. So now I need two functions that do something similar to genText. I'll need an actualText() function that returns the text the user has inputted, and a wrappedText() function that returns the wrapped version of actualText(). I'll also need to find out where to replace genText with wrappedText.

There is a loop at the end of TextBase::draw that uses TextBlocks to draw the TextBase. Add a method to TextBase that returns a text-wrapped TextBase that loop() can iterate through?

Use Ms::SPATIUM20 to convert from pixels to spatium.

Use QFontMetrics to measure character widths.

Done with implementing word wrapped TBoxes. Now I need to get drawEditMode and probably text insertion to play nice with wrapped text.

In drawEditMode, need to translate ted using this to ted using wrapped, including the associated TextCursor.

In TextBase::insert, will need to figure out input.

Now last every cursor position is getting translated right except the very last character of the row, and when it's at the first character of the next (non-existent) row. Both are getting mapped to the first pos.

(Done) Need to test with unicode characters

Bugs:

Crashes on copy pasted line breaks. This is because copy pasted line breaks are somehow added after the fact...?

Cannot use mouse to select text.

TBox has zero height when user inputs just a space. (this has been around for a while)

Home key moves to beginning of previous line.

Clone this wiki locally