Značky řádků a kliknutí na okraj¶
Značka řádku je symbol ve sloupci záložek editoru a/nebo podbarvení přes
celý řádek, připojené k řádku dokumentu a přenášené s ním, zatímco uživatel
upravuje text. Zarážky (plné, prázdné, podmíněné), šipka aktuálního příkazu a
pruhy změn ze správy verzí jsou všechno značky řádků. Ke službě se dostanete
přes IPluginContext::lineMarkers() (PluginApi/ILineMarkerService.h).
Modul popisuje, jak druh značky vypadá a kde značky toho druhu stojí; vykreslování, okraj a sloty pro značky v editačním jádře patří editoru. Hranici nepřekračuje žádná velikost v pixelech, číslo jádra ani typ Qt.
Druhy¶
Každý druh značky zaregistrujte jednou, v initialize(), a token si ponechte:
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 */ }
- Barvy jsou id kategorií motivu, které jste si sami zaregistrovali přes
ctx.themePalette(), takže značky sledují aktivní motiv a uživatel je může přebarvit v Editoru motivů; editor je znovu použije při každé změně motivu. - Symboly jsou malá pevná sada, kterou umí každý hostitel vykreslit v úzkém
okraji při jakémkoli přiblížení:
Circle(zarážka),CircleHollow(vypnutá nebo neověřená zarážka),CircleBar(podmíněná zarážka),Arrow(aktuální příkaz),Strip(změněný řádek).Nonevytvoří druh, který jen podbarvuje. - zOrder rozhoduje, která značka se vykreslí nahoře, když jich několik sdílí jeden řádek (šipka aktuálního příkazu nad zarážkou, zarážka nad pruhem změn); při shodných hodnotách je nahoře druh zaregistrovaný později. Pořadí platí i napříč moduly.
- Registrace může selhat. Editační jádro má malý pevný počet slotů pro značky, sdílený všemi moduly — devět; druh se symbolem i podbarvením zabírá dva. Když dojdou, token se vrátí prázdný a protokol řekne proč. Potřebné druhy registrujte jednou a ponechte si je; nikdy neregistrujte druh pro každý dokument nebo každou značku.
- Zničení tokenu odstraní všechny značky toho druhu ze všech dokumentů a druh stáhne.
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átí 0 — a nic neumístí — když druh nežije, dokument není otevřený
nebo řádek leží mimo dokument. Řádek se neořezává: zarážka na špatném řádku
je horší než žádná. Popisovač je obyčejná hodnota, ne token; držte jich, kolik
potřebujete.
Co se se značkou děje potom:
- Úpravy ji posouvají spolu s jejím řádkem: řádky vložené nebo smazané nad ní ji posunou, psaní na řádku ji ponechá — tak zarážka sleduje kód.
- Její řádek se smaže (je součástí odstraněného rozsahu): značka přežije a přesune se na řádek, kde odstraněný rozsah začínal. Dvě značky tak mohou skončit na jednom řádku.
- Nahradí se celý buffer (znovunačtení po změně zvenčí,
IEditorService::setText): každá značka zůstane na stejném čísle řádku; značka, jejíž řádek už neexistuje, se odstraní. Editor starý a nový text neporovnává. - Dokument se zavře: jeho značky se odstraní a jejich popisovače přestanou
platit. Editor značky nikdy neukládá — modul, který si značky ponechává i po
zavření (zarážky), je drží ve vlastním modelu a při
DocumentOpenedje přidá znovu (znovu otevřený soubor má novéDocumentId).
Značky patří dokumentu: jednou umístěné se zobrazí v každém panelu
rozděleného dokumentu. Minimapa, její náhled
při najetí a zobrazení porovnání je nikdy neukazují. Záložky nejsou značkami
této služby; ponechávají si vlastní volání IEditorService.
Kliknutí na okraj¶
Každé kliknutí levým tlačítkem do sloupce záložek editoru se publikuje jako
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átorů odpovídají přenositelným řetězcům zkratek: kControl je Ctrl
ve Windows a Linuxu a Command (⌘) v macOS, kAlt je Alt / Option (⌥), kMeta
je klávesa Windows / Control (⌃) v macOS. Kliknutí do sloupce sbalování
sbalují a kliknutí na čísla řádků vybírají; ani jedno se nepublikuje.
Ve výchozím stavu editor navíc na kliknutém řádku přepne záložku, jako to dělal vždy. Modul, který kliknutí dává vlastní význam — ladicí program, který prostým kliknutím přepíná zarážku a kliknutím s modifikátorem upravuje její podmínku —, si ho nárokuje:
m_marginClaim = ctx.lineMarkers().claimMarginClick(); // MarginClickToken
m_clicks = ctx.events().subscribe<events::MarginClicked>(
[this](const events::MarginClicked& e) { onMarginClick(e); });
Dokud žije aspoň jeden nárok — od kteréhokoli modulu —, editor kliknutí přenechá modulům a jen publikuje událost; zničení posledního tokenu vrátí přepínání záložek. Událost se publikuje bez ohledu na to, zda někdo drží nárok, takže modul, který kliknutí jen sleduje, žádný nepotřebuje. Příkazy záložek a jejich zkratky se nemění. Nároky se počítají, neřadí se do fronty: dva moduly, které si kliknutí oba nárokují, ho oba dostanou a nesmějí na něj oba reagovat.
Python¶
Tatáž služba je ctx.line_markers pro
moduly v Pythonu a kliknutí je
@ctx.events.on_margin_clicked.