Linjemerker og margklikket¶
Et linjemerke er et symbol i redigererens bokmerkekolonne og/eller en farging
over hele linjen, festet til en linje i et dokument og ført med den mens
brukeren redigerer. Stoppunkter (fylte, hule, betingede), en pil for gjeldende
setning og endringsstripene fra versjonskontroll er alle linjemerker. Du når
tjenesten gjennom IPluginContext::lineMarkers()
(PluginApi/ILineMarkerService.h).
Programtillegget beskriver hvordan en type merke ser ut og hvor merker av den typen står; tegningen, margen og redigeringsmotorens merkeplasser tilhører redigereren. Ingen pikselstørrelse, intet motornummer og ingen Qt-type krysser grensen.
Typer¶
Registrer hver type merke én gang, i initialize(), og ta vare på tokenet:
enum class LineMarkerGlyph : std::int32_t {
None, Circle, CircleHollow, CircleBar, Arrow, Strip
};
struct LineMarkerKind {
LineMarkerGlyph glyph = LineMarkerGlyph::Circle;
std::string glyphColor; // a theme category you registered
std::string lineTint; // a theme category; empty = no tint
std::int32_t zOrder = 0; // higher draws above lower
};
m_breakpoint = ctx.lineMarkers().registerKind(kind); // LineMarkerKindToken
if (!m_breakpoint.valid()) { /* no slot left: see below */ }
- Farger er ID-er for temakategorier du selv har registrert med
ctx.themePalette(), så merkene følger det aktive temaet og brukeren kan farge dem om i Temaredigereren; redigereren bruker dem på nytt ved hvert temabytte. - Symboler er et lite, fast sett som hver vert kan tegne i en smal marg ved
alle zoomnivåer:
Circle(et stoppunkt),CircleHollow(et deaktivert eller ubekreftet stoppunkt),CircleBar(et betinget stoppunkt),Arrow(gjeldende setning),Strip(en endret linje).Nonegir en type som bare farger. - zOrder avgjør hvilket merke som tegnes øverst når flere deler en linje (pilen for gjeldende setning over et stoppunkt, et stoppunkt over en endringsstripe); ved like verdier havner typen som ble registrert sist, øverst. Rekkefølgen gjelder også på tvers av programtillegg.
- Registreringen kan mislykkes. Redigeringsmotoren har et lite, fast antall merkeplasser som alle programtillegg deler — ni; en type med symbol og farging bruker to. Når de er brukt opp, kommer tokenet tilbake tomt, og loggen sier hvorfor. Registrer typene du trenger, én gang og ta vare på dem; registrer aldri en type per dokument eller per merke.
- Å ødelegge tokenet fjerner alle merker av den typen fra alle dokumenter og trekker typen tilbake.
Merker¶
using LineMarkerId = std::uint64_t; // 0 is never valid
LineMarkerId id = ctx.lineMarkers().addMarker(m_breakpoint.id(), doc, line);
std::int64_t now = ctx.lineMarkers().lineOf(id); // -1 = gone
auto all = ctx.lineMarkers().markers(m_breakpoint.id(), doc); // {id, line} by line
ctx.lineMarkers().removeMarker(id);
ctx.lineMarkers().clearMarkers(m_breakpoint.id(), 0); // 0 = every document
addMarker returnerer 0 — og plasserer ingenting — når typen ikke lever,
dokumentet ikke er åpent eller linjen ligger utenfor dokumentet. En linje
avgrenses ikke: et stoppunkt på feil linje er verre enn ingen. Et håndtak er
en enkel verdi, ikke et token; hold på så mange du trenger.
Hva som skjer med et merke etterpå:
- Redigeringer flytter det sammen med linjen: linjer som settes inn eller slettes ovenfor, forskyver det, å skrive på linjen beholder det — slik følger et stoppunkt koden.
- Linjen blir slettet (del av et fjernet område): merket overlever og havner på linjen der det slettede området begynte. To merker kan dermed havne på én linje.
- Hele bufferen byttes ut (en ny innlasting etter en endring utenfra,
IEditorService::setText): hvert merke blir stående på samme linjenummer; et merke hvis linje ikke lenger finnes, fjernes. Redigereren sammenligner ikke gammel og ny tekst. - Dokumentet lukkes: merkene fjernes og håndtakene slutter å gjelde.
Redigereren lagrer aldri merker — et programtillegg som tar vare på merker
etter en lukking (stoppunkter), holder dem i sin egen modell og legger dem til
igjen ved
DocumentOpened(en gjenåpnet fil er en nyDocumentId).
Merker hører til dokumentet: plassert én gang vises de i hver rute i et
delt dokument. Minikartet, forhåndsvisningen
ved peking og sammenligningsvisningen viser dem aldri. Bokmerker er ikke merker
i denne tjenesten; de beholder sine egne IEditorService-kall.
Margklikket¶
Hvert venstreklikk i bokmerkekolonnen i en redigerer publiseres som
events::MarginClicked:
struct MarginClicked {
DocumentId doc;
std::int64_t line; // 0-based, level with the click
EditorMargin margin; // EditorMargin::Symbol
KeyModifiers modifiers; // key_modifier::kShift | kControl | kAlt | kMeta
};
Navnene på modifikatorene følger de flyttbare hurtigtaststrengene: kControl er
Ctrl på Windows og Linux og Command (⌘) på macOS, kAlt er Alt / Option (⌥),
kMeta er Windows-tasten / Control (⌃) på macOS. Klikk i brettekolonnen bretter,
og klikk på linjenumrene merker; ingen av dem publiseres.
Som standard slår redigereren også et bokmerke av eller på på linjen det ble klikket på, slik den alltid har gjort. Et programtillegg som gir klikket en egen betydning — en feilsøker som slår et stoppunkt av og på med et vanlig klikk og redigerer betingelsen med et klikk med modifikator — gjør krav på det:
m_marginClaim = ctx.lineMarkers().claimMarginClick(); // MarginClickToken
m_clicks = ctx.events().subscribe<events::MarginClicked>(
[this](const events::MarginClicked& e) { onMarginClick(e); });
Så lenge minst ett krav lever — fra et hvilket som helst programtillegg — overlater redigereren klikket til programtilleggene og publiserer bare hendelsen; når det siste tokenet ødelegges, slår klikket bokmerker av og på igjen. Hendelsen publiseres uansett om noen har et krav eller ikke, så et programtillegg som bare følger med på klikk, trenger ikke noe. Bokmerkekommandoene og hurtigtastene deres påvirkes ikke. Krav telles, de settes ikke i kø: to programtillegg som begge gjør krav på klikket, får det begge og må ikke begge handle på det.
Python¶
Den samme tjenesten er ctx.line_markers for
Python-programtillegg, og klikket
er @ctx.events.on_margin_clicked.