Gå til innhold

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). None gir 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 ny DocumentId).

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.