Preskočiť na obsah

Značky riadkov a kliknutie na okraj

Značka riadka je symbol v stĺpci záložiek editora a/alebo podfarbenie cez celý riadok, pripojené k riadku dokumentu a prenášané s ním, kým používateľ upravuje text. Zarážky (plné, prázdne, podmienené), šípka aktuálneho príkazu a pásy zmien zo správy verzií sú všetko značky riadkov. K službe sa dostanete cez IPluginContext::lineMarkers() (PluginApi/ILineMarkerService.h).

Modul opisuje, ako druh značky vyzerá a kde značky toho druhu stoja; vykresľovanie, okraj a sloty na značky v editačnom jadre patria editoru. Hranicu neprekračuje žiadna veľkosť v pixeloch, číslo jadra ani typ Qt.

Druhy

Každý druh značky zaregistrujte raz, v initialize(), a token si ponechajte:

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 */ }
  • Farby sú id kategórií motívu, ktoré ste si sami zaregistrovali cez ctx.themePalette(), takže značky sledujú aktívny motív a používateľ ich môže prefarbiť v Editore motívov; editor ich znova použije pri každej zmene motívu.
  • Symboly sú malá pevná sada, ktorú vie každý hostiteľ vykresliť v úzkom okraji pri akomkoľvek priblížení: Circle (zarážka), CircleHollow (vypnutá alebo neoverená zarážka), CircleBar (podmienená zarážka), Arrow (aktuálny príkaz), Strip (zmenený riadok). None vytvorí druh, ktorý iba podfarbuje.
  • zOrder rozhoduje, ktorá značka sa vykreslí navrchu, keď ich niekoľko zdieľa jeden riadok (šípka aktuálneho príkazu nad zarážkou, zarážka nad pásom zmien); pri rovnakých hodnotách je navrchu druh zaregistrovaný neskôr. Poradie platí aj naprieč modulmi.
  • Registrácia môže zlyhať. Editačné jadro má malý pevný počet slotov na značky, ktorý zdieľajú všetky moduly — deväť; druh so symbolom aj podfarbením zaberá dva. Keď sa minú, token sa vráti prázdny a log povie prečo. Potrebné druhy registrujte raz a ponechajte si ich; nikdy neregistrujte druh pre každý dokument alebo každú značku.
  • Zničenie tokenu odstráni všetky značky toho druhu zo všetkých dokumentov a druh stiahne.

Značky

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 vráti 0 — a nič neumiestni — keď druh nežije, dokument nie je otvorený alebo riadok leží mimo dokumentu. Riadok sa neorezáva: zarážka na nesprávnom riadku je horšia ako žiadna. Popisovač je obyčajná hodnota, nie token; držte ich, koľko potrebujete.

Čo sa so značkou deje potom:

  • Úpravy ju posúvajú spolu s jej riadkom: riadky vložené alebo zmazané nad ňou ju posunú, písanie na riadku ju ponechá — tak zarážka sleduje kód.
  • Jej riadok sa zmaže (je súčasťou odstráneného rozsahu): značka prežije a presunie sa na riadok, kde odstránený rozsah začínal. Dve značky tak môžu skončiť na jednom riadku.
  • Nahradí sa celý buffer (opätovné načítanie po zmene zvonku, IEditorService::setText): každá značka zostane na rovnakom čísle riadka; značka, ktorej riadok už neexistuje, sa odstráni. Editor starý a nový text neporovnáva.
  • Dokument sa zatvorí: jeho značky sa odstránia a ich popisovače prestanú platiť. Editor značky nikdy neukladá — modul, ktorý si značky ponecháva aj po zatvorení (zarážky), ich drží vo vlastnom modeli a pri DocumentOpened ich pridá znova (znova otvorený súbor má nové DocumentId).

Značky patria dokumentu: raz umiestnené sa zobrazia v každom table rozdeleného dokumentu. Minimapa, jej náhľad pri najazdení a zobrazenie porovnania ich nikdy neukazujú. Záložky nie sú značkami tejto služby; ponechávajú si vlastné volania IEditorService.

Kliknutie na okraj

Každé kliknutie ľavým tlačidlom do stĺpca záložiek editora sa zverejní ako 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
};

Názvy modifikátorov zodpovedajú prenosným reťazcom skratiek: kControl je Ctrl vo Windows a Linuxe a Command (⌘) v macOS, kAlt je Alt / Option (⌥), kMeta je kláves Windows / Control (⌃) v macOS. Kliknutia do stĺpca zbaľovania zbaľujú a kliknutia na čísla riadkov vyberajú; ani jedno sa nezverejňuje.

Predvolene editor navyše na kliknutom riadku prepne záložku, ako to robil vždy. Modul, ktorý kliknutiu dáva vlastný význam — ladiaci program, ktorý obyčajným kliknutím prepína zarážku a kliknutím s modifikátorom upravuje jej podmienku —, si ho nárokuje:

m_marginClaim = ctx.lineMarkers().claimMarginClick();   // MarginClickToken
m_clicks = ctx.events().subscribe<events::MarginClicked>(
    [this](const events::MarginClicked& e) { onMarginClick(e); });

Kým žije aspoň jeden nárok — od ktoréhokoľvek modulu —, editor kliknutie prenechá modulom a iba zverejní udalosť; zničenie posledného tokenu vráti prepínanie záložiek. Udalosť sa zverejňuje bez ohľadu na to, či niekto drží nárok, takže modul, ktorý kliknutia iba sleduje, žiadny nepotrebuje. Príkazy záložiek a ich skratky sa nemenia. Nároky sa počítajú, neradia sa do frontu: dva moduly, ktoré si kliknutie oba nárokujú, ho oba dostanú a nesmú naň oba reagovať.

Python

Tá istá služba je ctx.line_markers pre moduly v Pythone a kliknutie je @ctx.events.on_margin_clicked.