TextView (JavaScript) Taryn Fox jewelfox@fursona.net 2012 Víceřádkový textový editor TextView

TextView (textové zobrazení) je ve skutečnosti, nebo alespoň většinou, sada tří vnořených objektů.

Vespod je TextBuffer. Ten uchovává vlastní text.

Uprostřed je TextView, což je widget, který umožňuje zobrazit a upravovat text z vyrovnávací paměti. Automaticky mění svoji velikost v závislosti na množství textu v něm.

Protože automatické změny mohou učinit TextView neprakticky použitelným, je běžnou praxí umístit jej do widgetu ScrolledWindow. Navzdory výrazu „window“ v názvu se nejedná o běžně známe okno se záhlavím a tlačítkem ×, ale o widget, který vložený do aplikace bude fungovat jako okno do lépe zvládnutého zobrazení textu. Když bude text ve vyrovnávací paměti delší, než se vleze, objeví se posuvníky.

Když chcete změnit text, který je v TextView zobrazen, musíte pracovat s objektem TextBuffer, protože právě v něm je text uložen. To samé platí, když chcete vidět, co někdo do něj napsal. Tato ukázková aplikace umožňuje promluvit si se (smyšleným) tučňákem a kontroluje TextBuffer, aby zjistila, jestli jste někde nenapsali slovo „fish“ (ryba).

Ve skutečném světe populace tučňáků rychle klesá, protože změny klimatu způsobují tání ledovců, na kterých žijí, a zabíjí ryby, které jí. Jestli si chcete v GNOME zahrát (poněkud bláznivou) hru založenou na tomto předpokladu, podívejte se na Pingus.

Importované knihovny #!/usr/bin/gjs const Gtk = imports.gi.Gtk; const Lang = imports.lang;

Toto jsou knihovny, které potřebujeme naimportovat, aby aplikace běžela. Pamatujte si, že řádek, který GNOME říká, že používáme Gjs, musí být vždy na začátku.

Vytvoření okna aplikace const TextViewExample = new Lang.Class ({ Name: 'TextView Example', // Vytvoří vlastní aplikaci _init: function () { this.application = new Gtk.Application ({ application_id: 'org.example.jstextview' }); // Připojí signály "activate" a "startup" k funkcím zpětného volání this.application.connect('activate', Lang.bind(this, this._onActivate)); this.application.connect('startup', Lang.bind(this, this._onStartup)); }, // Funkce zpětného volání pro signál "activate" zobrazujicí okno při aktivaci _onActivate: function () { this._window.present (); }, // Funkce zpětného volání pro signál "startup" sestavující uživatelské rozhraní _onStartup: function () { this._buildUI (); },

Všechen kód této ukázky je ve třídě TextViewExample. Výše uvedený kód vytvoří Gtk.Application pro naše widgety a okno, ve kterém budou.

// Sestaví uživatelské rozhraní aplikace _buildUI: function () { // Vytvoří okno aplikace this._window = new Gtk.ApplicationWindow ({ application: this.application, window_position: Gtk.WindowPosition.CENTER, title: "Talk to a Penguin", default_height: 400, default_width: 440, border_width: 20 });

Funkce _buildUI je místo, ze kterého voláme všechen kód, který vytváří uživatelské rozhraní aplikace. Prvním krokem je vytvoření nového Gtk.ApplicationWindow, do kterého vložíme všechny naše widgety.

Vytvoření TextView // Vytvoří popisek přes který k vám bude promlouvat tučňák this._penguin = new Gtk.Label ({ height_request: 180, width_request: 400, label: "Squaaaak?", wrap: true });

Naším prvním krokem v tomto příkladu bude vytvořit Label, který tučňák používá k proslovům. Pomocí nastavení vlastnosti wrap na true zajistíme, že text se může zalamovat, ale u widgetu TextView použijeme jinou metodu, která nám umožní jemnější řízení.

// Vytvoří textové zobrazení, přes které můžete mluvit na tučňáka this.buffer = new Gtk.TextBuffer(); this._textView = new Gtk.TextView ({ buffer: this.buffer, editable: true, wrap_mode: Gtk.WrapMode.WORD });

Jako první krok je vytvořen TextBuffer pro vkládání slov. Po té zde vytvoříme TextView a řekneme mu, že má používat právě vytvořený TextBuffer. Rovněž se nastaví jako upravitelný, protože chceme mít možnost do něj psát nové věci.

Vlastnost wrap_mode dává možnost vybrat si ze čtyř různých režimů zalamování. Například Gtk.WrapMode.CHAR způsobí zalomení uprostřed slova, když budete pokračovat v psaní za okraj. Většina lidí pravděpodobně použije Gtk.WrapMode.WORD, který automaticky přesune psané slovo na další řádek, když je příliš dlouhé.

// Vytvoří okno s posuvníky pro vložení textového zobrazení, aby // mohlo posouvat svůj obsah this._scrolled = new Gtk.ScrolledWindow ({ hscrollbar_policy: Gtk.PolicyType.AUTOMATIC, vscrollbar_policy: Gtk.PolicyType.AUTOMATIC, shadow_type: Gtk.ShadowType.ETCHED_IN, height_request: 180, width_request: 400, }); // Vloží textové zobrazení do okna s posuvníky this._scrolled.add_with_viewport (this._textView);

Zde vytvoříme okno s posuvníky a nastavíme jej, aby automaticky poskytlo posuvníky, když dostaneme příliš velký obsah, ať už vodorovně nebo svisle. Rovněž získáme hezky vypadající okraj ETCHED_IN (prohnutý). Po té dovnitř vložíme TextView a řekneme oknu s posuvníky, aby nám pro něj poskytlo pohled.

Vytvoření zbytku uživatelského rozhraní // Vytvoří mřížku pro uspořádání widgetů this._grid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER }); // Vloží popisek a textové zobrazení do mřížky, jeden nad druhý this._grid.attach (this._penguin, 0, 0, 1, 1); this._grid.attach (this._scrolled, 0, 1, 1, 1);

První widget Grid, který jsme vytvořili, má uvnitř jen popisek a okno s posuvníky.

// Vytvoří tlačítko pro odeslání vaší zprávy tučňákovi this._send = new Gtk.Button ({ halign: Gtk.Align.END, margin_top: 20, label: "Send" }); this._send.connect ('clicked', Lang.bind (this, this._chat)); // Vytvoří mřížku pro poddružnou mřížku nahoře a tlačítko dole this._mainGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER }); // Přidá poddružnou mřížku a tlačítko do hlavní mřížky this._mainGrid.attach (this._grid, 0, 0, 1, 1); this._mainGrid.attach (this._send, 0, 1, 1, 1);

Vytvoříme widget Button, který odešle vaši zprávu tučňákovi, a mřížku, která bude nahoře obsahovat předchozí mřížku a dole tlačítko. Tlačítko má nahoře okraj, díky čemuž se nelepí na okno s posuvníky.

// Připojí hlavní mřížku do okna this._window.add (this._mainGrid); // Zobrazení okno a všechny jeho synovské widgety this._window.show_all(); },

Nakonec připojíme hlavní mřížku do okna, kterému řekneme, aby sebe a vše v něm nastavilo jako viditelné, když se spustí aplikace.

Funkce, která se stará o odpovědi tučňáka _chat: function () { // Vytvoří náhodné číslo, které určí, co tučňák řekne this.number = Math.floor ((Math.random() * 3) + 1); // Řekli jste právě něco? if (this.buffer.text) { // Zmínili jste rybu? if (this.buffer.text.match (/fish/gi)) { // Tučňák musí zaskřehovat o rybě if (this.number == 1) this._penguin.set_label ("FISH!"); else if (this.number == 2) this._penguin.set_label ("Fish fish fish fish. Fish!"); else this._penguin.set_label ("Fish? Fish fish fish. Fish fish. FISH!"); } // Myslím, že jsem se nezmínil o rybě else { // Tučňák pokecá o všedních záležitostech tučňáků if (this.number == 1) this._penguin.set_label ("SQUAAK!"); else if (this.number == 2) this._penguin.set_label ("Ork ork ork ork squaak. Squaak squaak! *waves flippers*"); else this._penguin.set_label ("Ork ork ork ork ork?"); } } // Vymaže vyrovnávací paměť this.buffer.text = ""; // Předá zaměření zpět textovému zobrazení, abyste do něj nemuseli znovu klikat this._textView.has_focus = true; } });

Zde používámě některé základní funkce jazyka JavaScript k tomu, aby náš tučňák promluvil. Když na to přijde, tučňáci mají rádi ryby, takže pokud zmíníte rybu, chceme, aby na to tučňák reagoval. K tomu použijeme metodu objektu String, který má JavaScript zabudovaný, vůči this.buffer.text, což vrací obsah našeho objektu TextBuffer.

Protože chceme, aby se náš TextBuffer pokaždé, když kliknete na Send vymazal, nastavíme po té this.buffer.text na prázdný řetězec. Pak vrátím zaměření textovému zobrazení, takže můžete pokračovat v psaní, aniž byste na něj před tím museli klikat.

// Spustí aplikaci let app = new TextViewExample (); app.application.run (ARGV);

Nakonec vytvoříme novou instanci konečné třídy TextViewExample a aplikaci spustíme.

Úplný kód ukázky #!/usr/bin/gjs imports.gi.versions.Gtk = '3.0'; const Gtk = imports.gi.Gtk; class TextViewExample { // Vytvoří vlastní aplikaci constructor() { this.application = new Gtk.Application({ application_id: 'org.example.jstextview' }); // Napojí signály "activate" a "startup" k funkcím zpětného volání this.application.connect('activate', this._onActivate.bind(this)); this.application.connect('startup', this._onStartup.bind(this)); } // Funkce zpětného volání pro signál "activate" zobrazujicí okno při aktivaci _onActivate() { this._window.present(); } // Funkce zpětného volání pro signál "startup" sestavující uživatelské rozhraní _onStartup() { this._buildUI(); } // Sestaví uživatelské rozhraní aplikace _buildUI() { // Vytvoří okno aplikace this._window = new Gtk.ApplicationWindow ({ application: this.application, window_position: Gtk.WindowPosition.CENTER, title: "Talk to a Penguin", default_height: 400, default_width: 440, border_width: 20 }); // Vytvoří popisek přes který k vám bude promlouvat tučňák this._penguin = new Gtk.Label ({ height_request: 180, width_request: 400, label: "Squaaaak?", wrap: true }); // Vytvoří textové zobrazení, přes které můžete mluvit na tučňáka this.buffer = new Gtk.TextBuffer(); this._textView = new Gtk.TextView ({ buffer: this.buffer, editable: true, wrap_mode: Gtk.WrapMode.WORD }); // Vytvoří okno s posuvníky pro vložení textového zobrazení, aby // mohlo posouvat svůj obsah this._scrolled = new Gtk.ScrolledWindow ({ hscrollbar_policy: Gtk.PolicyType.AUTOMATIC, vscrollbar_policy: Gtk.PolicyType.AUTOMATIC, shadow_type: Gtk.ShadowType.ETCHED_IN, height_request: 180, width_request: 400, }); // Vloží textové zobrazení do okna s posuvníky this._scrolled.add_with_viewport (this._textView); // Vytvoří mřížku pro uspořádní widgetů this._grid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER }); // Vloží popisek a textové zobrazení do mřížky, jeden nad druhý this._grid.attach (this._penguin, 0, 0, 1, 1); this._grid.attach (this._scrolled, 0, 1, 1, 1); // Vytvoří tlačítko pro odeslání vaší zprávy tučňákovi this._send = new Gtk.Button ({ halign: Gtk.Align.END, margin_top: 20, label: "Send" }); this._send.connect ('clicked', this._chat.bind(this)); // Vytvoří mřížku pro poddružnou mřížku nahoře a tlačítko dole this._mainGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER }); // Přidá poddružnou mřížku a tlačítko do hlavní mřížky this._mainGrid.attach (this._grid, 0, 0, 1, 1); this._mainGrid.attach (this._send, 0, 1, 1, 1); // Připojí hlavní mřížku do okna this._window.add (this._mainGrid); // Zobrazí okno a všechny jeho synovské widgety this._window.show_all(); } _chat() { // Vytvoří náhodné číslo, které určí, co tučňák řekne this.number = Math.floor ((Math.random() * 3) + 1); // Řekli jste právě něco? if (this.buffer.text) { // Zmínili jste rybu? if (this.buffer.text.match (/fish/gi)) { // Tučňák musí zaskřehovat o rybě if (this.number == 1) this._penguin.set_label ("FISH!"); else if (this.number == 2) this._penguin.set_label ("Fish fish fish fish. Fish!"); else this._penguin.set_label ("Fish? Fish fish fish. Fish fish. FISH!"); } // Myslím, že jsem se nezmínil o rybě else { // Tučňák pokecá o všedních záležitostech tučňáků if (this.number == 1) this._penguin.set_label ("SQUAAK!"); else if (this.number == 2) this._penguin.set_label ("Ork ork ork ork squaak. Squaak squaak! *waves flippers*"); else this._penguin.set_label ("Ork ork ork ork ork?"); } } // Vymaže vyrovnávací paměť this.buffer.text = ""; // Předá zaměření zpět textovému zobrazení, abyste do něj nemuseli znovu klikat this._textView.has_focus = true; } }; // Spustí aplikaci let app = new TextViewExample (); app.application.run (ARGV);
Dokumentace jdoucí do hloubky

Gtk.Application

Gtk.ApplicationWindow

Gtk.Button

Gtk.Grid

Gtk.Label

Gtk.RadioButton

Gtk.ScrolledWindow

Gtk.TextBuffer

Gtk.TextView