Blame platform-demos/cs/message-board.c.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="message-board.c" xml:lang="cs">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <title type="text">Vývěska (C)</title>
Packit 1470ea
    <link type="guide" xref="c#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>Jednoduchý program používající WebKitGTK+ a DOM.</desc>
Packit 1470ea
Packit 1470ea
    <revision pkgversion="0.1" version="0.1" date="2010-12-06" status="draft"/>
Packit 1470ea
    <credit type="author copyright">
Packit 1470ea
      <name>Shaun McCance</name>
Packit 1470ea
      <email its:translate="no">shaunm@gnome.org</email>
Packit 1470ea
      <years>2010</years>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="editor">
Packit 1470ea
      <name>Marta Maria Casetti</name>
Packit 1470ea
      <email its:translate="no">mmcasetti@gmail.com</email>
Packit 1470ea
      <years>2013</years>
Packit 1470ea
    </credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>Vývěska</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

V této lekci se seznámíme s následujícími věcmi:

Packit 1470ea
  <list style="compact">
Packit 1470ea
    <item>

Jak zobrazit webovou stránku pomocí jádra WebKit.

</item>
Packit 1470ea
    <item>

Jak pracovat s obsahem webové stránky pomocí funkcí DOM jádra WebKit.

</item>
Packit 1470ea
  </list>
Packit 1470ea
  

Tato lekce předpokládá, že máte znalosti programování v jazyce C a základní povědomí o GTK+, včetně toho, jak vytvořit a umístit widgety a jak připojit funkce zpětného volání k signálům. Viz <link xref="image-viewer.c"/> ohledně výuky základů GTK+.

Packit 1470ea
</synopsis>
Packit 1470ea
Packit 1470ea
<media type="video" mime="video/ogg" src="media/message-board.ogv"/>
Packit 1470ea
Packit 1470ea
<links type="section"/>
Packit 1470ea
Packit 1470ea
<section id="create">
Packit 1470ea
  <title>Vytvoření projektu ve studiu Anjuta</title>
Packit 1470ea
Packit 1470ea
  

Součástí platformy GNOME je WebKitGTK+ vycházející z mocné základní konstrukce WebKit pro HTML. WebKit je používán napříč celým GNOME, ne jen pro zobrazení webových stránek z Internetu, ale také k vytváření vizuálně bohatého uživatelského rozhraní, které lze jednoduše stylovat pomocí CSS.

Packit 1470ea
Packit 1470ea
  

V této lekci vytvoříme jednoduchou vývěsku pomocí knihovny WebKit. Vývěska bude umožňovat vkládat text a přidávat jej do seznamu zpráv v HTML. Než začneme, potřebujeme vytvořit projekt v IDE Anjuta.

Packit 1470ea
Packit 1470ea
  <steps>
Packit 1470ea
    <item>

Ve studiu Anjuta klikněte na <guiseq><gui>Soubor</gui> <gui>Nový</gui> <gui>Projekt</gui></guiseq>, aby se otevřel průvodce novým projektem.

</item>
Packit 1470ea
    <item>

Vyberte <gui>GTK+ (jednoduchý)</gui> na kartě <gui>C</gui> a klikněte na <gui>Pokračovat</gui>.

</item>
Packit 1470ea
    <item>

Na stránce <gui>Základní informace</gui> vyplňte své údaje. Jako název projektu použijte <input>message-board</input>. Klikněte na <gui>Pokračovat</gui>.

</item>
Packit 1470ea
    <item>

Vypněte volbu <gui>Použít GtkBuilder k tvorbě uživatelského rozhraní</gui>, protože jej chceme v této lekci vytvořit ručně.

Packit 1470ea
    </item>
Packit 1470ea
    <item>

Potřebujete vývojářskému studiu Anjuta říct, že ve svém projektu používáte WebKitGTK+. Na stránce <gui>Volby projektu</gui> vyberte <gui>Konfigurovat externí balíčky</gui>. Klikněte na <gui>Pokračovat</gui> a na stránce <gui>Konfigurace externích balíčků</gui> zaškrtněte <gui>webkitgtk-3.0</gui>.

</item>
Packit 1470ea
  </steps>
Packit 1470ea
Packit 1470ea
  

Po té, co projdete průvodcem nového projektu, otevřete <file>src/main.c</file> na kartě <gui>Projekt</gui> nebo <gui>Soubor</gui>. Anjuta jej vyplní nějakým základním kódem GTK+ ze šablony. Protože vytváříte projekt s knihovnou WebKit, potřebujete nejdříve vložit příslušné hlavičkové soubory. Za řádek, který vkládá gtk/gtk.h přidejte následující řádek:

Packit 1470ea
Packit 1470ea
  #include <webkit/webkit.h>
Packit 1470ea
Packit 1470ea
  

Ověřte, že vše, co máte doposud hotovo, funguje. Klikněte na <guiseq><gui>Sestavit</gui> <gui>Sestavit projekt</gui></guiseq> nebo jen zmáčkněte <keyseq><key>Shift</key> <key>F7</key></keyseq>. Při prvním sestavení budete dotázáni na některé volby konfigurace. Stačí přijmout výchozí hodnoty a kliknout na <gui>Spustit</gui>.

Packit 1470ea
Packit 1470ea
  

Nyní byste měli být schopni program spustit. Klikněte na <guiseq><gui>Spustit</gui> <gui>Spustit</gui></guiseq> nebo jen zmáčkněte <key>F3</key>. Měli byste spatřit prázdné okno.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="webview">
Packit 1470ea
  <title>Rozvržení vašeho okna a webového zobrazení</title>
Packit 1470ea
Packit 1470ea
  

Nyní, když můžete zobrazit okno, je načase začít pracovat s knihovnou WebKit. V této lekci vytvoříte textové vstupní pole a webové zobrazení a obojí zabalíte do okna. Najděte funkci create_window a nahraďte ji následujícím:

Packit 1470ea
Packit 1470ea
Packit 1470ea
static GtkWidget*
Packit 1470ea
create_window (void)
Packit 1470ea
{
Packit 1470ea
    GtkWidget *window, *box, *scroll, *view, *entry;
Packit 1470ea
Packit 1470ea
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 1470ea
    gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
Packit 1470ea
    gtk_window_set_title (GTK_WINDOW (window), "Message Board");
Packit 1470ea
    g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
Packit 1470ea
Packit 1470ea
    box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
Packit 1470ea
    gtk_container_set_border_width (GTK_CONTAINER (box), 6);
Packit 1470ea
    gtk_container_add (GTK_CONTAINER (window), box);
Packit 1470ea
Packit 1470ea
    entry = gtk_entry_new ();
Packit 1470ea
    gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
Packit 1470ea
Packit 1470ea
    scroll = gtk_scrolled_window_new (NULL, NULL);
Packit 1470ea
    g_object_set (scroll, "shadow-type", GTK_SHADOW_IN, NULL);
Packit 1470ea
    gtk_box_pack_start (GTK_BOX (box), scroll, TRUE, TRUE, 0);
Packit 1470ea
Packit 1470ea
    view = webkit_web_view_new ();
Packit 1470ea
    gtk_container_add (GTK_CONTAINER (scroll), view);
Packit 1470ea
    webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
Packit 1470ea
                                 "<html><body></body></html>",
Packit 1470ea
                                 "text/html",
Packit 1470ea
                                 "UTF-8",
Packit 1470ea
                                 NULL);
Packit 1470ea
Packit 1470ea
    gtk_widget_show_all (GTK_WIDGET (box));
Packit 1470ea
    return window;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

Nejprve vytvoříte objekt GtkWindow a nastavíte jeho název do záhlaví a výchozí velikost. Rovněž napojíte funkci gtk_main_quit na signál "delete-event". Tento signál je vyslán, když je okno zavřeno. Funkce gtk_main_quit je součástí GTK a ukončí aplikaci.

Packit 1470ea
Packit 1470ea
  

Pak vytvoříte svislý box a přidáte jej do okna. Okno může obsahovat jen jediný synovský widget, takže potřebujete box, abyste mohli přidat víc widgetů. Druhým argumentem u funkce gtk_box_new se nastaví velikost odsazení (v pixelech) mezi jednotlivými potomky a následující řádek vloží 6pixelový okraj okolo toho všeho.

Packit 1470ea
Packit 1470ea
  

Následně vytvoříte objekt GtkEntry a zabalíte jej do boxu. Třetí argument u gtk_box_pack_start určují, že vstupní pole by nemělo zabírat žádné místo navíc, které je v boxu dostupné. Čtvrtý argument je velikost odsazení okolo vstupního pole. V tomto případě jej nastavte na nulu, protože o odsazení se postará box.

Packit 1470ea
Packit 1470ea
  

Než přidáte webové zobrazení, musíte vytvořit okno s posuvníky, do kterého jej pak vložíte. Okno s posuvníky umístí v případě potřeby doprava a dolů posuvníky a zabrání vašemu webovému zobrazení, aby zaplnilo celou obrazovku. Tentokrát funkci gtk_box_pack_start předejte TRUE a TRUE, aby umožnila oknu s posuvníky (a tím webovému zobrazení) použít dodatečné místo dostupné v boxu.

Packit 1470ea
Packit 1470ea
  

Nakonec vytvoříte WebKitWebView a přidáte jej do okna s posuvníky. Potom načtěte úplně základní stránku v HTML do webového zobrazení zavoláním webkit_web_view_load_string s následujícími parametry:

Packit 1470ea
Packit 1470ea
  <terms>
Packit 1470ea
    <item>
Packit 1470ea
      <title>WEBKIT_WEB_VIEW (view)</title>
Packit 1470ea
      

Vlastní zobrazení. Protože view je typováno jako GtkWidget*, musíte požít WEBKIT_WEB_VIEW, aby se objekt bezpečně přetypoval.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      <title>"<html><body></body></html>"</title>
Packit 1470ea
      

Nejjednodušší soubor HTML, který byste mohli napsat.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      <title>"text/html"</title>
Packit 1470ea
      

Typ MIME obsahu, který poskytujete. V tomto případě používáte prosté HTML.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      <title>"UTF-8"</title>
Packit 1470ea
      

Kódování znaků v obsahu, který poskytujete. I když použijete jen znaky ASCII, je dobrým pravidlem zadat UTF-8. UTF-8 je totiž používáno jako výchozí kódování napříč celou platformou GNOME.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
      <title>NULL</title>
Packit 1470ea
      

Základní adresa URI. V tomto příkladu ji nepotřebujeme, ale možná budete chtít zadat URI <sys>file:</sys>, kdybyste přidali obrázky nebo jinou funkčnost, ve které chcete použít relativní odkazy URI.

Packit 1470ea
    </item>
Packit 1470ea
  </terms>
Packit 1470ea
Packit 1470ea
  <note style="sidebar">
Packit 1470ea
    

Pokaždé, když přidáte widget, musíte pro něj zavolat gtk_widget_show, aby byl viditelný. Když zavoláte gtk_widget_show_all pro kontejnerový widget, jako je GtkBox, zobrazí GTK+ automaticky všechny widgety uvnitř kontejneru do libovolné hloubky. Občas nemusíte chtít gtk_widget_show_all volat, třeba když chcete dynamicky skrývat a zobrazovat některé widgety v reakci na události.

Packit 1470ea
  </note>
Packit 1470ea
Packit 1470ea
  

Nakonec musíme v boxu zavolat gtk_widget_show_all, jinak nebude žádný vytvořený widget viditelný. (Okno je zobrazeno ve funkci main pomocí gtk_widget_show.)

Packit 1470ea
Packit 1470ea
  

Sestavte a spusťte vývěsku znovu. Měli byste vidět okno s textovým vstupním polem a webové zobrazení. Zatím to nic nedělá, protože vstupní pole a webové zobrazení o sobě navzájem nic neví.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="signals">
Packit 1470ea
  <title>Zaháčkování signálů</title>
Packit 1470ea
Packit 1470ea
  

Nyní chcete vývěsku naučit něco udělat, když zadáte text do textového vstupního pole. To se provede tak, že se napojí funkce zpětného volání na signál "activate" objektu entry. GTK+ vyšle signále "activate", kdykoliv uživatel ve vstupním poli zmáčkne <key>Enter</key>. Následující kód přidejte do create_window kamkoliv za definici entry a view:

Packit 1470ea
Packit 1470ea
Packit 1470ea
g_signal_connect (entry, "activate", G_CALLBACK (entry_activate_cb), view);
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

Potom můžete totiž definovat entry_activate_cb. Nadefinujte jej následovně kdekoliv nad create_window:

Packit 1470ea
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
entry_activate_cb (GtkEntry *entry, WebKitWebView *view)
Packit 1470ea
{
Packit 1470ea
    WebKitDOMDocument *document;
Packit 1470ea
    WebKitDOMElement *body, *div;
Packit 1470ea
Packit 1470ea
    document = webkit_web_view_get_dom_document (view);
Packit 1470ea
    body = webkit_dom_document_query_selector (document, "body", NULL);
Packit 1470ea
    div = webkit_dom_document_create_element (document, "div", NULL);
Packit 1470ea
    webkit_dom_node_set_text_content (WEBKIT_DOM_NODE (div),
Packit 1470ea
                                      gtk_entry_get_text (entry),
Packit 1470ea
                                      NULL);
Packit 1470ea
    webkit_dom_node_append_child (WEBKIT_DOM_NODE (body),
Packit 1470ea
                                  WEBKIT_DOM_NODE (div),
Packit 1470ea
                                  NULL);
Packit 1470ea
    gtk_entry_set_text (entry, "");
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

První věc, kterou uděláte, je, že získáte objekt WebKitDOMDocument, který představuje dokument HTML zobrazený ve widgetu view. Třídy a metody DOM v knihovně WebKit umožňují procházet a upravovat dokument HTML a fungují velmi podobně jako API k DOM, které můžete znát z jazyka JavaScript.

Packit 1470ea
Packit 1470ea
  

Jakmile máme dokument, chceme se dostat k prvku body, protože do něj můžeme přidat prvky div. Funkce webkit_dom_document_query_selector umožňuje najít prvek v dokumentu pomocí selektorů CSS. Tím si ušetříte psaní jednotvárných smyček pro procházení dokumentu.

Packit 1470ea
Packit 1470ea
  

V dalším kroku vytvoříme nový prvek div, ve kterém bude zpráva. Každý prvek, který vytvoříte, musí být připojen do dokumentu, takže funkce, která prvky vytváří, přebírá jako první argument WebKitDOMDocument. Pak nastavíte textový obsah prvku na obsah z textového vstupního pole. Protože gtk_entry_get_text vrací const gchar*, nemusíte výsledek uvolňovat z paměti.

Packit 1470ea
Packit 1470ea
  

Nakonec přidáme nový prvek div do těla a vymažeme textové vstupní pole, takže můžete napsat něco dalšího. Sestavte a spusťte program znovu a otestujte si jej.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
Packit 1470ea
<section id="css">
Packit 1470ea
  <title>Vytvoření hezčího vzhledu pomocí CSS</title>
Packit 1470ea
Packit 1470ea
  

V tuto chvíli je program plně funkční, ale ne moc hezký. Můžeme ostylovat zobrazení zpráv pomocí CSS, podobně jako to můžete udělat s kteroukoliv stránkou v HTML. Existuje mnoho způsobů, jak připojit stylopis do stránky: Mohli byste jej přidat do počátečního dokumentu HTML. Mohli byste jej vložit pomocí atributu style v prvku div. Mohli byste jej i sestrojit pomoci API k DOM.

Packit 1470ea
Packit 1470ea
  

V této lekci připojíme CSS pomocí vlastnosti user-stylesheet-uri objektu WebKitWebSetting připojeného do vašeho webového zobrazení. Ve složitějších aplikacích byste asi chtěli soubor HTML ukládat a načítat. Udržením stylopisu mimo HTML znamená, že může měnit styl přímo ve své aplikaci, bez zásahu do uživatelských souborů. Normálně by vám stačilo nainstalovat soubor se stylopisem spolu s vaší aplikací, ale aby pro potřeby této ukázky zůstalo vše uchováno v jednom souboru, použijeme trik nazvaný datová URI. Nejprve nadefinujeme CSS jako statický řetězec poblíž začátku vašeho souboru.

Packit 1470ea
Packit 1470ea
Packit 1470ea
static const guchar CSS[] =
Packit 1470ea
"body { margin: 0; padding: 0; }\n"
Packit 1470ea
"div { "
Packit 1470ea
" -webkit-border-radius: 2px;"
Packit 1470ea
" background: -webkit-gradient(linear, 0% 100%, 0% 0%,"
Packit 1470ea
" from(#f1f1f1), to(white));"
Packit 1470ea
" border: solid 1px #c6c6c6;"
Packit 1470ea
" -webkit-box-shadow: 0px 0px 2px #c6c6c6;"
Packit 1470ea
" margin: 12px; padding: 6px;"
Packit 1470ea
"}";
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

Vše, co máme v tomto příkladu, jsou prvky div uvnitř prvku body. Kdybyste vytvořili složitější HTML, mohli byste použít cokoliv by CSS bylo potřeba. Jestli jste s CSS obeznámeni, můžete si opravdu zkusit nějaké změny, aby se vám vzhled víc líbil.

Packit 1470ea
Packit 1470ea
  

Aby se použilo CSS, nastavte user-stylesheet-uri ve funkci create_window kdekoliv za definicí view.

Packit 1470ea
Packit 1470ea
Packit 1470ea
tmp = g_base64_encode (CSS, strlen((gchar *) CSS));
Packit 1470ea
css = g_strconcat ("data:text/css;charset=utf-8;base64,",
Packit 1470ea
                   tmp, NULL);
Packit 1470ea
g_object_set (webkit_web_view_get_settings (WEBKIT_WEB_VIEW (view)),
Packit 1470ea
              "user-stylesheet-uri", css, NULL);
Packit 1470ea
g_free (css);
Packit 1470ea
g_free (tmp);
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

Rovněž zajistěte přidání deklarací proměnných pro tmp a css na začátku create_window.

Packit 1470ea
Packit 1470ea
Packit 1470ea
gchar *tmp, *css;
Packit 1470ea
Packit 1470ea
Packit 1470ea
 

Datová URI začíná <sys>data:</sys> a některými informacemi o typu obsahu a kódování dat. Skutečná data následují za čárkou, v tomto případě zakódovaná v Base64. Narozdíl od jiných schémat URI, jako je <sys>http:</sys>, <sys>ftp:</sys> a <sys>file:</sys>, schéma URI <sys>data:</sys> nespecifikuje, kde najít soubor k načtení. Místo toho poskytuje rovnou celý obsah souboru.

Packit 1470ea
Packit 1470ea
 

Předchozí kód nejprve zakóduje vaši definici CSS v Base64 a pak ji zkombinuje s pevným řetězcem, aby vytvořil datovou URI. Funkce g_strconcat může přebírat libovolný počet řetězcových argumentů a spojit je dohromady, proto jí musíte jako poslední argument předat NULL, aby věděla kdy přestat. A až stylopis správně nastavíte, nezapomeňte uvolnit tyto dočasné řetězce z paměti.

Packit 1470ea
Packit 1470ea
 

Sestavte a spusťte program znovu. Měl by fungovat úplně stejně jako na konci předchozí části, vyjma toho, že zprávy jsou hezky ostylované pomocí okrajů a pozadí s jemným přechodem.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="more">
Packit 1470ea
  <title>Jak se naučit více</title>
Packit 1470ea
Packit 1470ea
  

V této lekci jsme si ukázali, jak vytvořit základní aplikaci pomocí knihoven GTK+ a WebKit, včetně zobrazení dokumentu a manipulace s jeho obsahem. Pro vytvoření reálné aplikace byste nejspíše museli udělat něco navíc. Zkuste si přidat vlastní funkčnost. Zde je pár nápadů:

Packit 1470ea
Packit 1470ea
  <list>
Packit 1470ea
    <item>

Pokud máte CSS rádi, zkuste si změnit styl zobrazených zpráv. S CSS se snadno začíná, ale i roste k mocnějšímu využití. Na Internetu je k dispozici nepřeberné množství výukových materiálů k CSS a téměř vše, co můžete udělat na webu, můžete udělat i v této aplikaci.

</item>
Packit 1470ea
Packit 1470ea
    <item>

V současné stavu přijdete o všechny své zprávy, když vývěsku zavřete. Zkuste obsah v HTML ukládat po každém příspěvku a načítat jej z uloženého souboru (když existuje) při spuštění.

</item>
Packit 1470ea
Packit 1470ea
    <item>

Až budete mít své zprávy uchované po dlouhou dobu, možná vás začne zajímat, kdy vlastně byly zveřejněny. Přidejte ke každé zprávě při jejím zveřejnění časové razítko. Možná budete potřebovat vytvořit další synovský prvek div s jinou třídou, abyste to mohli ostylovat pomocí CSS.

Packit 1470ea
    </item>
Packit 1470ea
Packit 1470ea
    <item>

Tento program uchovává zprávy navždy. Popřemýšlejte o způsobu, jak by uživatel mohl zprávy mazat. Třeba můžete chtít, aby zprávy samy mizely, když jsou příliš staré nebo když množství zpráv před nimi dosáhne určitého počtu. Nebo můžete ke každé zprávě přidat odkaz na její smazání. Mohli byste také přepsat kontextovou nabídku, která se objeví po kliknutí pravým tlačítkem. Tyto funkce znamenají hlubší prozkoumání API k DOM knihovny WebKit.

</item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
</page>