NotificationDisplay: proper handling of marks at insert position

Basically we create a pair of marks, with left/right gravity and then
inject the content between. Unfortunately, when the insert position
is the very end of the buffer (which it always is), this trick
leads to nesting the marked regions into each other.

As a remedy, we first insert the trailing newline,
and then attach the insert position one step before
This commit is contained in:
Fischlurch 2018-10-03 19:13:39 +02:00
parent 4635d18265
commit e9527d6304
2 changed files with 132 additions and 30 deletions

View file

@ -109,7 +109,8 @@ namespace widget {
}
/**
/*********************************************************************//**
* Widget to display log and error messages.
* Based on a multiline text display box with scrollbars.
* Warning and error messages are highlighted by special formatting.
@ -168,6 +169,7 @@ namespace widget {
textLog_.get_buffer()->set_text (placeholder); // discard existing content
}
/** just add normal information message to buffer,
* without special markup and without expanding the widget */
void
@ -201,7 +203,7 @@ namespace widget {
/**
* clear all mere information messages;
* retain just the errors with tags
* retain just the previously tagged errors
* @remark in fact populates a new buffer
*/
void
@ -211,12 +213,15 @@ namespace widget {
vector<Entry> newMarks;
for (Entry& entry : errorMarks_)
{
newBuff->insert (newBuff->end(), "\n");
auto pos = newBuff->end();
--pos;
newMarks.emplace_back(
make_pair (
newBuff->create_mark (newBuff->end(), true), // "left gravity": stays to the left of inserted text
newBuff->create_mark (newBuff->end(), false))); // "right gravity": sticks right behind the inserted text))
newBuff->create_mark (pos, true), // "left gravity" : stays to the left of inserted text
newBuff->create_mark (pos, false))); // "right gravity": sticks right behind the inserted text))
newBuff->insert (newBuff->end()
newBuff->insert (pos // copy from old to new buffer, complete with formatting tag
,entry.first->get_iter()
,entry.second->get_iter()
);
@ -250,27 +255,32 @@ namespace widget {
private:/* ===== Internals ===== */
/** add message entry to the (ever growing) text buffer.
* @remark According to the [GTKmm tutorial], `TextView::scroll_to(iter)` is not reliable;
* rather we need to use a text mark and set that text mark to the insert position.
* Actually, there is always one predefined text mark [called "insert"][insert-mark],
* which corresponds to the text cursor. Thus it suffices to navigate to text end,
* insert and scroll into view.
* @return pair of anonymous marks bracketing the content added
* @remark an entry is content sans the following line break, which is appended automatically.
* We inject the content _between_ two marks, which will adjust when content is altered.
* @remark According to the [API doc], `TextView::scroll_to(iter)` is not reliable; preferably
* we should use a text mark and set that text mark to the [insert position][insert-mark].
* The handling of marks and tags is described in the [GTKmm tutorial].
* @warning Each entry creates a new pair of marks. Not sure about the impact on performance...
*
* [GTKmm tutorial]: https://developer.gnome.org/gtkmm-tutorial/stable/sec-textview-buffer.html.en#textview-marks
* [insert-mark]: https://developer.gnome.org/gtkmm/3.22/classGtk_1_1TextMark.html#details
* [API doc]: https://developer.gnome.org/gtkmm/3.22/classGtk_1_1TextView.html#a8412941c4da9a71a381052d6049164e4
*/
Entry
addEntry (string const& text, Literal markupTagName =nullptr)
{
auto buff = textLog_.get_buffer();
auto begin = buff->create_mark (buff->end(), true); // "left gravity": stays to the left of inserted text
auto after = buff->create_mark (buff->end(), false);// "right gravity": sticks right behind the inserted text
if (markupTagName)
buff->insert_with_tag(buff->end(), text, cuString{markupTagName});
else
buff->insert (buff->end(), text);
buff->insert (buff->end(), "\n");
textLog_.scroll_to (after);
auto pos = buff->end();
--pos;
auto begin = buff->create_mark (pos, true); // "left gravity" : stays to the left of inserted text
auto after = buff->create_mark (pos, false);// "right gravity": sticks right behind the inserted text
if (markupTagName)
buff->insert_with_tag(pos, text, cuString{markupTagName});
else
buff->insert (pos, text);
textLog_.scroll_to (begin);
return make_pair (move(begin), move(after));
}
};

View file

@ -1773,7 +1773,8 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534850841673" ID="ID_375492094" MODIFIED="1538263469667" TEXT="ParentView-Interface">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1504203667130" ID="ID_1745777873" MODIFIED="1538263469667" TEXT="vorl&#xe4;ufig Empf&#xe4;nger f&#xfc;r Fehler-Log">
<node CREATED="1504203667130" HGAP="50" ID="ID_1745777873" MODIFIED="1538584290312" TEXT="vorl&#xe4;ufig Empf&#xe4;nger f&#xfc;r Fehler-Log" VSHIFT="2">
<arrowlink COLOR="#98a2c5" DESTINATION="ID_217810080" ENDARROW="Default" ENDINCLINATION="1891;-1228;" ID="Arrow_ID_1688804340" STARTARROW="None" STARTINCLINATION="-1261;74;"/>
<linktarget COLOR="#7893b2" DESTINATION="ID_1745777873" ENDARROW="Default" ENDINCLINATION="-499;-464;" ID="Arrow_ID_1590510093" SOURCE="ID_812129962" STARTARROW="None" STARTINCLINATION="808;0;"/>
<linktarget COLOR="#628195" DESTINATION="ID_1745777873" ENDARROW="Default" ENDINCLINATION="245;349;" ID="Arrow_ID_1743659141" SOURCE="ID_1981930639" STARTARROW="None" STARTINCLINATION="397;197;"/>
<icon BUILTIN="forward"/>
@ -2116,8 +2117,8 @@
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534725501467" ID="ID_1420459325" MODIFIED="1538263469669" TEXT="Bookmark speichern">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1534725501467" ID="ID_1420459325" MODIFIED="1538586532645" TEXT="Bookmark speichern">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1537535919147" ID="ID_1338221225" MODIFIED="1538263469669" TEXT="Technologie">
<icon BUILTIN="info"/>
<node CREATED="1537535925874" ID="ID_196796680" MODIFIED="1538263469669" TEXT="Tag / TagTable">
@ -2146,7 +2147,7 @@
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1538581570783" ID="ID_1599117331" MODIFIED="1538581665660" TEXT="Problem: Ende wandert mit...">
<node COLOR="#338800" CREATED="1538581570783" ID="ID_1599117331" MODIFIED="1538586033692" TEXT="Problem: Ende wandert mit...">
<richcontent TYPE="NOTE"><html>
<head>
@ -2161,10 +2162,27 @@
</body>
</html>
</richcontent>
<icon BUILTIN="flag-pink"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1538585387424" ID="ID_151756918" MODIFIED="1538585442447" TEXT="Trick: erst abschlie&#xdf;enden Zeilenumbruch">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1537571882918" ID="ID_620353485" MODIFIED="1538263469669" TEXT="reorganisieren">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1538585409653" ID="ID_584738161" MODIFIED="1538585447421">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
...dann Einf&#252;gestelle <i>davor</i>&#160;platzieren
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1537571882918" ID="ID_620353485" MODIFIED="1538586057629" TEXT="reorganisieren">
<icon BUILTIN="button_cancel"/>
<node CREATED="1538586059134" ID="ID_5616537" MODIFIED="1538586065889" TEXT="besser wegwerfen und neu bauen"/>
</node>
</node>
</node>
@ -2210,8 +2228,8 @@
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534725142756" ID="ID_343395831" MODIFIED="1538263469669" TEXT="clearInfoMsg">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1534725142756" ID="ID_343395831" MODIFIED="1538586610313" TEXT="clearInfoMsg">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1538581145248" ID="ID_643768128" MODIFIED="1538581206025" TEXT="neuen TextBuffer anlegen">
<icon BUILTIN="button_ok"/>
</node>
@ -2756,8 +2774,8 @@
<icon BUILTIN="info"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534120150463" ID="ID_183847307" MODIFIED="1538263469672" TEXT="doClearMsg()">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1534120150463" ID="ID_183847307" MODIFIED="1538586631566" TEXT="doClearMsg()">
<icon BUILTIN="button_ok"/>
<node CREATED="1534120150463" ID="ID_1378278687" MODIFIED="1538263469672" TEXT="&quot;remove all mere information messages&quot;">
<icon BUILTIN="info"/>
</node>
@ -5014,9 +5032,20 @@
</ul>
</body>
</html></richcontent>
<node CREATED="1538583873795" ID="ID_1515056203" MODIFIED="1538583876382" TEXT="spezifisch">
<node CREATED="1537659880597" ID="ID_1214109906" MODIFIED="1537659889631" TEXT="Timecode"/>
<node CREATED="1537659890292" ID="ID_1230379898" MODIFIED="1537659892520" TEXT="Placement"/>
</node>
<node CREATED="1538583877106" ID="ID_1825646582" MODIFIED="1538583879910" TEXT="generisch">
<node CREATED="1538583886065" ID="ID_217810080" MODIFIED="1538584290312" TEXT="ErrorLogView">
<linktarget COLOR="#98a2c5" DESTINATION="ID_217810080" ENDARROW="Default" ENDINCLINATION="1891;-1228;" ID="Arrow_ID_1688804340" SOURCE="ID_1745777873" STARTARROW="None" STARTINCLINATION="-1261;74;"/>
<node CREATED="1538583894072" ID="ID_1836686899" MODIFIED="1538584118864" TEXT="Gtk::TextView + Mark-Index">
<arrowlink COLOR="#3251a9" DESTINATION="ID_243616989" ENDARROW="Default" ENDINCLINATION="-2060;-1360;" ID="Arrow_ID_794678010" STARTARROW="None" STARTINCLINATION="-3506;-148;"/>
<icon BUILTIN="info"/>
</node>
</node>
</node>
</node>
<node CREATED="1537961656982" ID="ID_1251358269" MODIFIED="1537961731447" TEXT="frameworks">
<richcontent TYPE="NOTE"><html>
<head>
@ -5028,7 +5057,7 @@
</p>
</body>
</html></richcontent>
<node CREATED="1537961734956" ID="ID_345535043" MODIFIED="1537961770028" TEXT="Notebook-Widget">
<node CREATED="1537961734956" FOLDED="true" ID="ID_345535043" MODIFIED="1538583863918" TEXT="Notebook-Widget">
<node CREATED="1537961776184" ID="ID_167848646" MODIFIED="1537961791126" TEXT="Problematik">
<icon BUILTIN="forward"/>
<node CREATED="1537961797061" ID="ID_104206298" MODIFIED="1537961806159" TEXT="extrem viele Komponenten-Widgets"/>
@ -37869,8 +37898,9 @@
<node CREATED="1534635322938" ID="ID_1532459469" MODIFIED="1534635328573" TEXT="show_all zeigt rekursiv an"/>
</node>
</node>
<node CREATED="1534634259498" ID="ID_1900017952" MODIFIED="1534635809110" TEXT="&quot;Schlie&#xdf;en&quot;">
<node CREATED="1534634259498" FOLDED="true" ID="ID_1900017952" MODIFIED="1538583305997" TEXT="&quot;Schlie&#xdf;en&quot;">
<linktarget COLOR="#6f7ab9" DESTINATION="ID_1900017952" ENDARROW="Default" ENDINCLINATION="-2264;0;" ID="Arrow_ID_1220603071" SOURCE="ID_146943890" STARTARROW="None" STARTINCLINATION="-6278;0;"/>
<icon BUILTIN="button_cancel"/>
<node CREATED="1534634292477" ID="ID_1867321008" MODIFIED="1534634310281">
<richcontent TYPE="NODE"><html>
<head>
@ -38812,6 +38842,68 @@
</node>
</node>
</node>
<node CREATED="1538583396203" ID="ID_243616989" MODIFIED="1538584118865" TEXT="TextView">
<linktarget COLOR="#3251a9" DESTINATION="ID_243616989" ENDARROW="Default" ENDINCLINATION="-2060;-1360;" ID="Arrow_ID_794678010" SOURCE="ID_1836686899" STARTARROW="None" STARTINCLINATION="-3506;-148;"/>
<node CREATED="1538583408897" ID="ID_1222725022" MODIFIED="1538583418805" TEXT="das Editor-Widget">
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1538583420272" ID="ID_438604441" MODIFIED="1538583449944" TEXT="Model == Buffer">
<node CREATED="1538583478040" ID="ID_511541932" MODIFIED="1538583483915" TEXT="kann getauscht werden"/>
<node CREATED="1538583484647" ID="ID_457973011" MODIFIED="1538583504768" TEXT="Buffer gemeinsam verwenden"/>
</node>
<node CREATED="1538583507988" HGAP="72" ID="ID_1806257929" MODIFIED="1538583518616" TEXT="TextBuffer" VSHIFT="18">
<node CREATED="1538583533033" ID="ID_964637986" MODIFIED="1538583734951" TEXT="Konzepte">
<icon BUILTIN="info"/>
<node CREATED="1538583627852" ID="ID_1431409524" MODIFIED="1538583630676" TEXT="Position">
<node CREATED="1538583632075" ID="ID_1308223917" MODIFIED="1538583654421">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
stets <i>zwischen </i>den Zeichen
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1538583655744" ID="ID_415292974" MODIFIED="1538583682595">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<b>Danke</b>! endlich bekommt das mal jemand korrekt hin
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node CREATED="1538583535896" ID="ID_81892828" MODIFIED="1538583539908" TEXT="TextIterator">
<node CREATED="1538583541231" ID="ID_1777219378" MODIFIED="1538583544571" TEXT="fl&#xfc;chtig"/>
<node CREATED="1538583546679" ID="ID_1182183621" MODIFIED="1538583555801" TEXT="kann intelligent navigieren">
<node CREATED="1538583567436" ID="ID_750990432" MODIFIED="1538583573647" TEXT="Zeichen"/>
<node CREATED="1538583573995" ID="ID_881520087" MODIFIED="1538583579166" TEXT="n&#xe4;chstes Wort"/>
<node CREATED="1538583579754" ID="ID_198678641" MODIFIED="1538583582742" TEXT="n&#xe4;chste Zeile"/>
</node>
<node CREATED="1538583556374" ID="ID_661377638" MODIFIED="1538583562128" TEXT="wei&#xdf; viel &#xfc;ber seine Position"/>
</node>
<node CREATED="1538583588689" ID="ID_1850195952" MODIFIED="1538583593741" TEXT="TextMark">
<node CREATED="1538583596768" ID="ID_281650917" MODIFIED="1538583612602" TEXT="dauerhafte Positionsmarke"/>
<node CREATED="1538583613326" ID="ID_1642730307" MODIFIED="1538583618193" TEXT="wandert mit"/>
<node CREATED="1538583618989" ID="ID_870667973" MODIFIED="1538583624848" TEXT="left/right gravity"/>
</node>
<node CREATED="1538583722679" ID="ID_80198934" MODIFIED="1538583725898" TEXT="TextTag">
<node CREATED="1538583726990" ID="ID_679389681" MODIFIED="1538583730874" TEXT="Formatierung / Markup"/>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1477526858307" ID="ID_676269117" MODIFIED="1518487921100" TEXT="custom widget">
<node COLOR="#ca1b00" CREATED="1477526864162" ID="ID_1385929770" LINK="https://developer.gnome.org/gtkmm-tutorial/stable/sec-custom-widgets.html.en" MODIFIED="1518487921100" TEXT="Beispiel">