<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2001/XInclude" type="guide" style="task" id="combobox.js" xml:lang="cs">
<info>
<title type="text">ComboBox (JavaScript)</title>
<link type="guide" xref="beginner.js#menu-combo-toolbar"/>
<link type="seealso" xref="GtkApplicationWindow.js"/>
<link type="seealso" xref="comboboxtext.js"/>
<link type="seealso" xref="messagedialog.js"/>
<link type="seealso" xref="treeview_simple_liststore.js"/>
<revision version="0.1" date="2012-07-09" status="draft"/>
<credit type="author copyright">
<name>Taryn Fox</name>
<email its:translate="no">jewelfox@fursona.net</email>
<years>2012</years>
</credit>
<desc>Přizpůsobitelná rozbalovací nabídka</desc>
</info>
<title>ComboBox</title>
<media type="image" mime="image/png" src="media/combobox_multicolumn.png"/>
<p><code>ComboBox</code> (rozbalovací seznam) je vysoce přizpůsobitelná rozbalovací nabídka. Obsahuje obdobu widgetu <link xref="treeview_simple_liststore.js">TreeView</link>, který se objeví po kliknutí, doplněného modelem <code>ListStore</code> (což je v zásadě tabulka), který udává, co se nachází v řádcích a sloupcích. V tomto příkladu má náš <code>ListStore</code> v jednom sloupci název volby a v druhém název standardní ikony, který je v rozbalovacím seznamu přeměněn na ikonu u každé z voleb.</p>
<p>Vybíráte celý řádek naráz, takže ikona není oddělenou volbou. Ona a text vedle ní tvoří jednu volbu, na kterou můžete kliknout.</p>
<note style="tip"><p>Práce s <code>ListStore</code> zabere nějaký čas. Jestli chcete jen jednoduchou čistě textovou rozbalovací nabídku, podívejte se na <link xref="comboboxtext.js">ComboBoxText</link>. Jeho vytvoření nezabere tolik času a jednodušeji se s ním pracuje.</p></note>
<links type="section"/>
<section id="imports">
<title>Importované knihovny</title>
<code mime="application/javascript">
#!/usr/bin/gjs
imports.gi.versions.Gtk = '3.0';
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
</code>
<p>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.</p>
</section>
<section id="applicationwindow">
<title>Vytvoření okna aplikace</title>
<code mime="application/javascript">
class ComboBoxExample {
// Vytvoří vlastní aplikaci
constructor() {
this.application = new Gtk.Application ({
application_id: 'org.example.jscombobox'});
// 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", která zobrazí okno při aktivaci
_onActivate() {
this._window.present ();
}
// Funkce zpětného volání pro signál "startup", která sestaví uživatelské rozhraní
_onStartup() {
this._buildUI ();
}
</code>
<p>Všechen kód této ukázky je ve třídě <code>ComboBoxExample</code>. Výše uvedený kód vytvoří <link href="http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gtk.Application.html">Gtk.Application</link> pro naše widgety a okno, ve kterém budou.</p>
<code mime="application/javascript">
// Sestaví uživatelské rozhraní aplikace
_buildUI() {
// Vytvoří okno aplikace
this._window = new Gtk.ApplicationWindow ({
application: this.application,
window_position: Gtk.WindowPosition.CENTER,
title: "Welcome to GNOME",
default_width: 200,
border_width: 10 });
</code>
<p>Funkce <code>_buildUI</code> 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 <link xref="GtkApplicationWindow.js">Gtk.ApplicationWindow</link>, do kterého vložíme všechny naše widgety.</p>
</section>
<section id="liststore">
<title>Vytvoření ListStore</title>
<code mime="application/javascript">
// Vytvoří ListStore pro vložení našich voleb
this._listStore = new Gtk.ListStore();
this._listStore.set_column_types ([
GObject.TYPE_STRING,
GObject.TYPE_STRING]);
</code>
<p>ListStore funguje podobně, jako ten použitý v příkladu <link xref="treeview_simple_liststore.js">TreeView</link>. Dáme mu dva sloupce, oba řetězcové, přičemž jeden z nich bude obsahovat názvy <link href="https://developer.gnome.org/gtk3/3.4/gtk3-Stock-Items.html">standardních ikon Gtk</link>.</p>
<p>Pokud byste chtěli použít své vlastní ikony, protože nechcete ty zabudované v GNOME, museli byste místo toho použít <file>gtk.gdk.Pixbuf</file>. Zde je pár dalších typů, které můžete použít:</p>
<list>
<item><p><file>GObject.TYPE_BOOLEAN</file> – Pravda nebo nepravda</p></item>
<item><p><file>GObject.TYPE_FLOAT</file> – Desetinné číslo (tj. s plovoucí desetinou čárkou, resp. tečkou)</p></item>
<item><p><file>GObject.TYPE_STRING</file> – Řetězec písmen a číslic</p></item>
</list>
<note style="tip"><p>Abyste mohli používat typy GObject, potřebujete vložit řádek <file>const GObject = imports.gi.GObject;</file> na začátek kódu aplikace tak, jako jsem učinili v tomto příkladu.</p></note>
<code mime="application/javascript">
// Toto pole uchovává seznam voleb a jejich ikony
let options = [{ name: "Select" },
{ name: "New", icon: Gtk.STOCK_NEW },
{ name: "Open", icon: Gtk.STOCK_OPEN },
{ name: "Save", icon: Gtk.STOCK_SAVE }];
// Vložení voleb do ListStore
for (let i = 0; i < options.length; i++ ) {
let option = options[i];
let iter = this._listStore.append();
this._listStore.set (iter, [0], [option.name]);
if ('icon' in option)
this._listStore.set (iter, [1], [option.icon]);
}
</code>
<p>Zde vytváříme pole s textovými volbami a jim odpovídajícími ikonami a pak je vložíme do <code>ListStore</code> více méně stejným způsobem, jako jsem použili pro <code>ListStore</code> v ukázce <link xref="treeview_simple_liststore.js">TreeView</link>. Ikonu chceme vložit jen v případě, že v položce pole opravdu nějaká je, takže to nejprve zkontrolujeme.</p>
<note style="tip"><p>Položka „Select“ není skutečná volba, ale jen takové pozvání ke kliknutí na náš rozbalovací seznam, a proto nemá ikonu.</p></note>
</section>
<section id="combobox">
<title>Vytvoření ComboBox</title>
<code mime="application/javascript">
// Vytvoří rozbalovací seznam
this._comboBox = new Gtk.ComboBox({
model: this._listStore});
</code>
<p>Každý rozbalovací seznam má podkladový „model“ obsahující všechny jeho volby. Pokud máte rozbalovací seznam s rozvětvenými volbami, můžete použít <code>TreeStore</code> (stromové úložiště). V tomto případě používáme již vytvořený <code>ListStore</code> (seznamové úložiště).</p>
<code mime="application/javascript">
// Vytvoří vykreslovač buněk pro položky v jednotlivých sloupcích
let rendererPixbuf = new Gtk.CellRendererPixbuf();
let rendererText = new Gtk.CellRendererText();
// Zabalí vykreslovač buněk do rozbalovacího seznamu v pořadí, v jakém je chcem vidět
this._comboBox.pack_start (rendererPixbuf, false);
this._comboBox.pack_start (rendererText, false);
// Nataví vykreslovač buněk, aby se používaly informace z našeho ListStore
this._comboBox.add_attribute (rendererText, "text", 0);
this._comboBox.add_attribute (rendererPixbuf, "stock_id", 1);
</code>
<p>Tato část opět pracuje podobně, jako u vytváření vykreslovačů buněk a balení položek do sloupců u příkladu s <link xref="treeview_simple_liststore.js">TreeView</link>. Největší rozdíl je, že nepotřebujeme vytvářet sloupce rozbalovacího seznamu jako oddělené objekty. Jednoduše zabalíme vykreslovače buněk do <code>ComboBox</code> v pořadí, v jakém chceme objekty zobrazovat, a řekneme jim, že mají informace získávat z <code>ListStore</code> (a typ dat, která očekáváme).</p>
<p>Používáme <code>CellRendererText</code> pro zobrazení textu a <code>CellRendererPixbuf</code> pro zobrazení ikon. Názvy standardních ikon můžeme uchovávat v podobě řetězců, ale když je potřeba, zobrazíme je pomocí příslušného vykreslovače jako obrázky.</p>
<note style="tip"><p>Obdobně, jako u <code>TreeView</code>, jsou „model“ (v tomto případě <code>ListStore</code>) a „zobrazení“ (v tomto případě <code>ComboBox</code>) oddělené. Díky tomu můžeme dělat věci, jako je mít sloupce v nějakém pořadí v <code>ListStore</code> a vykreslovače buněk pak zabalit tak, že budou tyto sloupce odpovídat jinému pořadí v <code>ComboBox</code>. Můžeme vytvořit <code>TreeView</code> nebo jiný widget, který zobrazuje informace z <code>ListStore</code> v jiném pořadí, aniž by to ovlivnilo náš rozbalovací seznam.</p></note>
<code mime="application/javascript">
// Nastavení prvního řádku v rozbalovacím seznamu, aby byl aktivní po spuštění
this._comboBox.set_active (0);
// Napojení signálu „changed“ od rozbalovacího seznamu na naši funkci zpětného volání
this._comboBox.connect ('changed', this._onComboChanged.bind(this));
</code>
<p>Chceme, aby součástí byl text „Select“, který lidé uvidí jako první, aby je vyzval ke kliknutí na rozbalovací seznam. Takže jej nastavíme, aby byl aktivní položkou. Dále pak napojíme signál <code>"changed"</code> rozbalovacího seznamu na funkci zpětného volání, takže kdykoliv někdo klikne na novou volbu, něco se stane. V tomto případě jen zobrazíme dialogové okno s drobnou haiku.</p>
<code mime="application/javascript">
// Přidá rozbalovací seznam do okna
this._window.add (this._comboBox);
// Zobrazí okno a všechny jeho synovské widgety
this._window.show_all();
}
</code>
<p>Nakonec přidáme <code>ComboBox</code> do okna a oknu řekneme ať zobrazí sebe a vše co obsahuje.</p>
</section>
<section id="function">
<title>Funkce, která zpracovává váš výběr</title>
<code mime="application/javascript">
_selected() {
// Bláznivá pseudohaiku, kterou použijeme do dialogového okna se zprávou
let haiku = ["",
"You ask for the new\nwith no thought for the aged\nlike fallen leaves trod.",
"Like a simple clam\nrevealing a lustrous pearl\nit opens for you.",
"A moment in time\na memory on the breeze\nthese things can't be saved."];
</code>
<p>Nyní pojďme vytvořit vyskakovací <link xref="messagedialog.js">MessageDialog</link>, který vám zobrazí bláznivou haiku odpovídající tomu, kterou distribuci vyberete. Nejprve vytvoříme pole použitých haiku. Protože první řetězec v našem rozbalovacím seznamu je jen zpráva „Select“, ponecháme první řetězec v poli prázdný.</p>
<code mime="application/javascript">
// Která položka v rozbalovacím seznamu je aktivní?
let activeItem = this._comboBox.get_active();
// Žádné dialogové okno se zprávou, když zvolíte „Select“
if (activeItem != 0) {
this._popUp = new Gtk.MessageDialog ({
transient_for: this._window,
modal: true,
buttons: Gtk.ButtonsType.OK,
message_type: Gtk.MessageType.INFO,
text: haiku[activeItem]});
// Napojí tlačítko OK na zpracující funkci
this._popUp.connect ('response', this._onDialogResponse.bind(this));
// Zobrazí dialogové okno se zprávou
this._popUp.show();
}
}
</code>
<p>Než dialogové okno se zprávou zobrazíme, provedeme test, abychom se ujistili, než není vybrána zpráva „Select“. Pak pro něj nastavíme text haiku z pole, který bude odpovídat aktivní položce v našem rozbalovacím seznamu. To uděláme pomocí metody <code>get_active</code>, která vrací číselné ID výběru.</p>
<note style="tip"><p>Jinými metodami, které bychom mohli použít jsou <code>get_active_id</code>, která vrací textové ID přiřazené metodou <code>append</code>, a <code>get_active_text</code>, která vrací celý text ve vybrané položce.</p></note>
<p>Po té, co vytvoříme <code>MessageDialog</code>, napojíme jeho signál <code>"response"</code> na funkci <code>_onDialogResponse</code> a následně řekneme oknu, ať se zobrazí.</p>
<code mime="application/javascript">
_onDialogResponse() {
this._popUp.destroy ();
}
};
</code>
<p>Protože jediným tlačítkem, které dialogové okno se zprávou má, je tlačítko <gui>OK</gui>, nepotřebujeme testovat hodnotu <code>response_id</code>, abychom zjistili, na které tlačítko bylo kliknuto. Vše, co uděláme, je, že dialogové okno zlikvidujeme.</p>
<code mime="application/javascript">
// Spustí aplikaci
let app = new ComboBoxExample ();
app.application.run (ARGV);
</code>
<p>Nakonec vytvoříme novou instanci konečné třídy ComboBoxExample a aplikaci spustíme.</p>
</section>
<section id="complete">
<title>Úplný kód ukázky</title>
<code mime="application/javascript" style="numbered">#!/usr/bin/gjs
imports.gi.versions.Gtk = '3.0';
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
class ComboBoxExample {
// Vytvoří vlastní aplikaci
constructor() {
this.application = new Gtk.Application ({
application_id: 'org.example.jscombobox'});
// 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", která zobrazí okno při aktivaci
_onActivate() {
this._window.present ();
}
// Funkce zpětného volání pro signál "startup", která sestaví 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: "Welcome to GNOME",
default_width: 200,
border_width: 10 });
// Vytvoří ListStore pro vložení našich voleb
this._listStore = new Gtk.ListStore();
this._listStore.set_column_types ([
GObject.TYPE_STRING,
GObject.TYPE_STRING]);
// Toto pole uchovává seznam voleb a jejich ikony
let options = [{ name: "Select" },
{ name: "New", icon: Gtk.STOCK_NEW },
{ name: "Open", icon: Gtk.STOCK_OPEN },
{ name: "Save", icon: Gtk.STOCK_SAVE }];
// Vloží volby do ListStore
for (let i = 0; i < options.length; i++ ) {
let option = options[i];
let iter = this._listStore.append();
this._listStore.set (iter, [0], [option.name]);
if ('icon' in option)
this._listStore.set (iter, [1], [option.icon]);
}
// Vytvoří rozbalovací seznam
this._comboBox = new Gtk.ComboBox({
model: this._listStore});
// Vytvoří vykreslovače buněk pro položky v jednotlivých sloupcích
let rendererPixbuf = new Gtk.CellRendererPixbuf();
let rendererText = new Gtk.CellRendererText();
// Zabalí vykreslovače buněk do rozbalovacího seznamu v pořadí, v jakém je chcem vidět
this._comboBox.pack_start (rendererPixbuf, false);
this._comboBox.pack_start (rendererText, false);
// Nataví vykreslovače buněk, aby používaly informace z našeho ListStore
this._comboBox.add_attribute (rendererText, "text", 0);
this._comboBox.add_attribute (rendererPixbuf, "stock_id", 1);
// Nastaví první řádek v rozbalovacím seznamu, aby byl aktivní po spuštění
this._comboBox.set_active (0);
// Napojí signály „changed“ od rozbalovacího seznamu na naši funkci zpětného volání
this._comboBox.connect ('changed', this._onComboChanged.bind(this));
// Přidá rozbalovací seznam do okna
this._window.add (this._comboBox);
// Zobrazí okno a všechny jeho synovské widgety
this._window.show_all();
}
_onComboChanged() {
// Bláznivá pseudohaiku, kterou použijeme do dialogového okna se zprávou
let haiku = ["",
"You ask for the new\nwith no thought for the aged\nlike fallen leaves trod.",
"Like a simple clam\nrevealing a lustrous pearl\nit opens for you.",
"A moment in time\na memory on the breeze\nthese things can't be saved."];
// Která položka v rozbalovacím seznamu je aktivní?
let activeItem = this._comboBox.get_active();
// Žádné dialogové okno se zprávou, když zvolíte „Select“
if (activeItem != 0) {
this._popUp = new Gtk.MessageDialog ({
transient_for: this._window,
modal: true,
buttons: Gtk.ButtonsType.OK,
message_type: Gtk.MessageType.INFO,
text: haiku[activeItem]});
// Napojí tlačítko OK na zpracující funkci
this._popUp.connect ('response', this._onDialogResponse.bind(this));
// Zobrazí dialogové okno se zprávou
this._popUp.show();
}
}
_onDialogResponse() {
this._popUp.destroy ();
}
};
// Spustí aplikaci
let app = new ComboBoxExample ();
app.application.run (ARGV);
</code>
</section>
<section id="in-depth">
<title>Dokumentace jdoucí do hloubky</title>
<p>V této ukázce se používá následující:</p>
<list>
<item><p><link href="http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gtk.Application.html">Gtk.Application</link></p></item>
<item><p><link href="http://developer.gnome.org/gtk3/stable/GtkApplicationWindow.html">Gtk.ApplicationWindow</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.CellRendererPixbuf.html">Gtk.CellRendererPixbuf</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.CellRendererText.html">Gtk.CellRendererText</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.ComboBox.html">Gtk.ComboBox</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.ListStore.html">Gtk.ListStore</link></p></item>
<item><p><link href="http://www.roojs.com/seed/gir-1.2-gtk-3.0/gjs/Gtk.MessageDialog.html">Gtk.MessageDialog</link></p></item>
<item><p><link href="http://www.roojs.org/seed/gir-1.2-gtk-3.0/gjs/Gtk.TreeIter.html">Gtk.TreeIter</link></p></item>
</list>
</section>
</page>