V této lekci se seznámíme s následujícími věcmi:
Jak zobrazit webovou stránku pomocí jádra WebKit.
Jak pracovat s obsahem webové stránky pomocí funkcí DOM jádra WebKit.
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 ohledně výuky základů GTK+.
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.
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.
Ve studiu Anjuta klikněte na
Vyberte
Na stránce
Vypněte volbu
Potřebujete vývojářskému studiu Anjuta říct, že ve svém projektu používáte WebKitGTK+. Na stránce
Po té, co projdete průvodcem nového projektu, otevřete gtk/gtk.h
přidejte následující řádek:
#include <webkit/webkit.h>
Ověřte, že vše, co máte doposud hotovo, funguje. Klikněte na
Nyní byste měli být schopni program spustit. Klikněte na
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:
static GtkWidget*
create_window (void)
{
GtkWidget *window, *box, *scroll, *view, *entry;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
gtk_window_set_title (GTK_WINDOW (window), "Message Board");
g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_container_set_border_width (GTK_CONTAINER (box), 6);
gtk_container_add (GTK_CONTAINER (window), box);
entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
scroll = gtk_scrolled_window_new (NULL, NULL);
g_object_set (scroll, "shadow-type", GTK_SHADOW_IN, NULL);
gtk_box_pack_start (GTK_BOX (box), scroll, TRUE, TRUE, 0);
view = webkit_web_view_new ();
gtk_container_add (GTK_CONTAINER (scroll), view);
webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
"<html><body></body></html>",
"text/html",
"UTF-8",
NULL);
gtk_widget_show_all (GTK_WIDGET (box));
return window;
}
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.
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.
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.
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.
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:
WEBKIT_WEB_VIEW (view)
Vlastní zobrazení. Protože view
je typováno jako GtkWidget*
, musíte požít WEBKIT_WEB_VIEW
, aby se objekt bezpečně přetypoval.
"<html><body></body></html>"
Nejjednodušší soubor HTML, který byste mohli napsat.
"text/html"
Typ MIME obsahu, který poskytujete. V tomto případě používáte prosté HTML.
"UTF-8"
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.
NULL
Základní adresa URI. V tomto příkladu ji nepotřebujeme, ale možná budete chtít zadat URI
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.
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
.)
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í.
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 create_window
kamkoliv za definici entry
a view
:
g_signal_connect (entry, "activate", G_CALLBACK (entry_activate_cb), view);
Potom můžete totiž definovat entry_activate_cb
. Nadefinujte jej následovně kdekoliv nad create_window
:
static void
entry_activate_cb (GtkEntry *entry, WebKitWebView *view)
{
WebKitDOMDocument *document;
WebKitDOMElement *body, *div;
document = webkit_web_view_get_dom_document (view);
body = webkit_dom_document_query_selector (document, "body", NULL);
div = webkit_dom_document_create_element (document, "div", NULL);
webkit_dom_node_set_text_content (WEBKIT_DOM_NODE (div),
gtk_entry_get_text (entry),
NULL);
webkit_dom_node_append_child (WEBKIT_DOM_NODE (body),
WEBKIT_DOM_NODE (div),
NULL);
gtk_entry_set_text (entry, "");
}
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.
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.
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.
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.
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.
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.
static const guchar CSS[] =
"body { margin: 0; padding: 0; }\n"
"div { "
" -webkit-border-radius: 2px;"
" background: -webkit-gradient(linear, 0% 100%, 0% 0%,"
" from(#f1f1f1), to(white));"
" border: solid 1px #c6c6c6;"
" -webkit-box-shadow: 0px 0px 2px #c6c6c6;"
" margin: 12px; padding: 6px;"
"}";
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.
Aby se použilo CSS, nastavte user-stylesheet-uri
ve funkci create_window
kdekoliv za definicí view
.
tmp = g_base64_encode (CSS, strlen((gchar *) CSS));
css = g_strconcat ("data:text/css;charset=utf-8;base64,",
tmp, NULL);
g_object_set (webkit_web_view_get_settings (WEBKIT_WEB_VIEW (view)),
"user-stylesheet-uri", css, NULL);
g_free (css);
g_free (tmp);
Rovněž zajistěte přidání deklarací proměnných pro tmp
a css
na začátku create_window
.
gchar *tmp, *css;
Datová URI začíná
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.
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.
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ů:
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.
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í.
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.
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.