Monthly Archives: julij 2008

Sedaj resnično nimam veliko prostega časa za razvoj Teuthide. Veliko dela je v službi in pridem pozno popoldne domov. Med vikendom pa ponavadi počivam. No sedaj sem si vzel malo časa za moj projekt. Malo pogledal kaj je narejenega in kaj manjka.

Izvorna koda ima dobrih 5000 vrstic, ki omogočajo:

  • ustvarjanje delovne površine poljubne velikosti,
  • pomanjšava, povečava delovne površine,
  • premikanje, brisanje, ustvarjanje predmetov,
  • spreminjanje velikosti predmetov (ima še malenkost napak),
  • spreminjanje lastnosti predmetov – barva ospredja, barva ozadja, besedilo,
  • urejanje povezave med predmeti, izgled povezav, napis povezave, barva povezave,
  • izvoz delovne površine v PNG sliko,
  • shranjevanje in nalaganje delovne površine.

In ravno zadnja točka potrebuje popolno predelavo. Sedaj se delovna površina shrani v XML zapis. V tem zapisu je pa vsak element na površini zapisan kot kopija vseh točk, ki ga opisuje. Se pravi, če imamo nek predmet, ki je izrisan iz sedmih, točk, morajo vse te točke imeti svoj zapis v obliki XY koordinat. In to za vsak predmet. Če imamo na površini 12 takšnih predmetov, pomeni to 84 XY zapisov za vse te predmete. In menim, da se ta problem lahko reši veliko bolj elegantno.

Zato premišljujem o sistemu, ki bi izrazil obliko nekega predmeta brez XY koordinat. Verjetno bo potrebno izdelati nek nov XML zapis posebej za predmete, ki bo poleg SVG zapisa vključeval še dodatne informacije. Delnoma je to že narejeno preko dodatne datoteke, ki jo ima vsak predmet, vendar se mi to zdi grda rešitev.

Ah da še to omenim: v podjetju iščemo kompetentne sodelavce z Python ali Ruby ali Enterprise Java znanjem za razvoj web aplikacij. Če je kdo zainteresiran, naj se mi javi na mail ali pa na pošto, ki jo najdete na domači strani podjetja.

En članek, ki je vreden omembe, je pritegnil mojo pozornost v zastonjskem časupisu Žurnal, izdaja 25. 7. 2008. Namreč članek z naslovom “Ne čakajte na študije” je bralce pozival na preventivo pred domnevno škodljivim sevanjem mobilnikov. In da je stvar še bolj slastna, omenjajo nekega “vodilnega ameriškega raziskovalca raka”

Čeprav se zadnje dneve Žurnal hvali, da je eden najbolj branih časopisov v Sloveniji, se prav bojim takšnih člankov ki imajo vprašljivo kvaliteto. Zakaj le se bi ljudje zanašali na študije, če pa imajo svoje instinkte, ki jim nekako povejo, da mobilniki povzročajo raka (kar v nobeni študiji ni dokazano). Še malo, pa bo Žurnal šel v filozofijo politike, kjer domneva postane resnica. Ta resnica pa kasneje zgodovina. V žurnalu malce pogrešam kolumne in ne samo odmeve. V članku želim prebrati tudi “zakaj” in “to pomeni” in ne “je rekel” ali pa “… se dogovorili”.

Ta članek me je spomnil na nek prispevek v oddaji 24ur, kjer so pokazali posnetek, ki naj bi prikazoval kako sevanje vpliva na jajce. Preizkus je bil sledeči: Med srovim jajcem sta bila postavljena dva mobilnika, vsak na svoji strani. Za nekaj časa (koliko dolgo se ne spomnem, mislim da okoli 10 minut) sta bila mobilnika povezana. Ko so preizkus končali, je kamera pokazala jajce, ki se je nato razbilo. In glej ga, jajce je bilo na mehko kuhano. No avtor tega prispevka se je spraševal ali je morda kaj na tem. Zanimivo se mi je zdelo za novinarja, da sam ni izvedel ta preizkus, ki pa le ni zapleten. Ampak ne, gledalec je ostal v temi in lahko samo ugibal. No čez nekaj časa je nekdo drug ta preizkus ponovil in se je izkazalo, da jajce na takšen način ni mogoče zakuhati, tudi če sta mobilnika povezana dlje časa. Tukaj ugotovimo dve stvari: slovenski novinarji ne znajo narediti dobre reportaže in da moramo ohraniti zdravi skepticizem pri takšnih “kontraverznih” rečeh.

Ne ne govorim o jeziku Objective-C ampak o dobrem starem ANSI C. Malo bolje spoznavam knjižnico GObject. Gre se za C knjižnico, ki nudi emulacijo C++ razredov in veliko več.

S to knjižnico lahko ustvarjamo razrede tipa, ki ga mi ustvarimo. Takšni razredi imajo nekatere zmožnosti kot so npr. virtualne metode. Vendar veliko bolj napredne razrede lahko ustvarimo, če so tipa GObject. Takšni razredi imajo veliko zmožnosti:

  • samodejno uporavljanje s pomnilnikom,
  • virtualne metode,
  • lastnosti,
  • signali,
  • skriti in javni člani,
  • konstruktor in desktruktor,

Za ustvarjanje GObject razreda je sicer potrebno nekaj standardnih deklaracij in je potrebno upoštevati konvencije kako se pišejo GObject razredi. Vendar ko smo s tem upravili, imamo pravi razred v C-ju.

GObject knjižnica se najbolj uporablja pri orodju Gtk+ za gradnjo grafičnih programov. Vendar je knjižnica veliko bolj splošna.

Če se vam ne da ukvarjati s C objektim, si pa lahko pogledate nov jezik Vala, ki ima C# sintakso vendar se programi prevedejo v C funkcije, te pa nato v binarne programe brez kakšne virtualne mašine, kot jih imata .NET in Java. Jezik Vala za ustvarjanje razredov uporablja GObject, ko program prevaja iz Vala sintakse v C kodo.

Nabavil sem si zunanji disk 2.5″, kjer imam backup pomembnih dokumentov. Sedaj me pa zanima če obstaja kakšno Linux orodje, ki bi ob priklopu pogona samodejno preveril določene imenike in jih uskladil, če se razlikujejo od prvotnih. Mora imeti lastnosti:

  • sinhronizacija imenikov – pri tem me najprej vpraša ali res želim sinhronizirat imenik,
  • opazovanje – takoj ko spremenim datoteko lokalno na disku, se tudi različica na prenosnem disku osveži,
  • samodejni zagon grafičnega vmesnika ob priklopu,
  • dodajanje več imenikov

Na letošnjem GUADEC srečanju v Turčiji so nekateri Gnome razvijalci presenetili z načrtom za namizje Gnome 3.0. Tako Lucas piše o prehodu iz Gnome 2.30 v različico 3.0, skupaj z Gtk+ 3.0. No po teh predstavitvah razvijalci doživljajo nekakšno 3.0 evforijo in spreminjajo svoje projekte za novo namizno paradigmo za različico 3.0: jezički, jezički. Kar pomeni, da bo celotno namizje močno izkoriščalo jezičke (ang. tabs) pri vsaki Gnome aplikaciji. In da mislijo resno, so tudi že prilagodili kar nekaj programov.

Eden od razvijalcev je naredil spremembo predmeta za navidezna namizja tako, da so namesto sivih kvadradkov sedaj jezički:

Če gre verjeti načrtom, naj bi namizje 3.0 bilo pripravljeno čez približno leto in pol, glede na to da nova Gnome različica izhaja vsakih 6 mesecev.

V prvem delu smo se razjasnili glede izrisa gradnikov in poiskali kodo, ki sproži izris glavnega okna. Sedaj pa bomo pogledali dejansko kodo, ki izriše okno.

Ko program želi prikazati okno, ga ne mora direktno izrisati na zaslon, ampak kliče posebno funkcijo za X strežnik, ta pa ustvari novo “površino” in jo prikaže. Upravitelj oken pa poskrbi za okvir in naslovnico okoli okna. Tukaj Gtk+ nima vpliva razen tega, da je sprožil to dogajanje. Torej X strežnik oz. odjemalska knjižnica Xlib poskrbi da ima gtk+ neko površino, na katero ima dovoljenje za risanje. Tukaj se pa nato sproži “expose” signal okna, ki nato izriše njegovo ozadje. Nato se sproži rekurzivna funkcija, ki še hierarhično izrisuje vse otroke (gradnike znotraj okna) in sprožuje njihov “expose” signal.

Ker pa ne želimo stikati po gtk+ izvorni kodi, si raje izberemo pogon, ki ga bomo spremenili. Pa vzemimo pogon Murrine. Ta pogon vse izrise opravlja preko cairo vektorske knjižnice in trenutno velja za najbolj prilagosdljiv pogon.

V pogonu sedaj iščemo funkcijo , ki pripada klicu draw_flat_box(). V izvorni kodi jo najdemo v datoteki murrine_style.c pod imenom murrine_style_draw_flat_box(). Nekje v vrstici 1551 v isti datoteki pa tudi vidimo, kako pogon prevzame klice na funkcijo draw_flat_box() z:

style_class->draw_flat_box = murrine_style_draw_flat_box;

Torej omenjeno funkcijo bodo klicali vsi gradniki, ki bodo potrebovali nek pobarvan okvir. Mi pa želimo gladke robove omejiti samo na okna, zato moramo preverjati, da bo izris robov samo pri gradnikih vrste GtkWindow. Pogon murrine ima že spisano funkcijo, ki z cairo funkcijami ustvari pravokotnik z glajenimi robovi. Zato to tudi uporabimo. Pred koncem funkcije vstavimo naslednjo kodo:


if (GTK_IS_WINDOW(widget)) {
cairo_t *cr = murrine_begin_paint (window, area);
int x, y, w, h, d;

cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
gdk_window_get_geometry(window, &x, &y, &w, &h, &d);
clearlooks_rounded_rectangle (cr, 0, 0, w, h, 20.0, MRN_CORNER_TOPLEFT | MRN_CORNER_TOPRIGHT | MRN_CORNER_BOTTOMRIGHT | MRN_CORNER_BOTTOMLEFT);

cairo_fill(cr);
cairo_destroy (cr);
}

Tukaj smo najprej preverili, če je funkcijo murrine_style_draw_flat_box() klicalo glavno okno. Nato iz okna pridobimo cairo podlago za risanje. Nastavimo barvo na sivo in narišemo pravokotnik. Spremenjen pogon prevedemo in namestimo (make && sudo make install). In kar takoj, ko temo uveljavimo, vidimo spremembe:
Shrani.si

Se pravi da smo na pravi poti. Gladki robovi se res izrišejo. Sedaj pa je potrebno tisti preostanek pri robovih odstraniti, da bo skozi vidno ozadje.

Nadaljevanje v tretjem delu.

Kot sem že v mojem prejšnjem postu omenu, se na Ubuntu straneh nahaja zelo dober predlog za GTK+ temo nove generacije. Pa si bom od avtorja malce sposodil sliko.

Poglejmo si, kakšni bi bilo pogovorno okno za vnos administratorskega gesla, kadar želimo pognati program, ki potrebuje sistemske privilegije:
mockup

Kar odstopa, so glajeni robovi okna in rahel metalski preliv kot ozadje. Ko se gtk+ program prikazuje, se najprej naloži t.i. pogon izrisa (theme engine), ki vsebuje funkcije za izris posameznih gradnikov. Namreč gradniki v gtk+ so implementirani tako, da kadar se mora gradnik izrisati, se kliče signal, ki je dejansko kazalec na neko funkcijo, ki upravi izris. Če pogon ne implementira te funkcije, izris gradnika prevzame gtk+ z lastno implementacijo. Vsak pogon pa lahko še ima stile (gtkrc styles), ki lahko določajo npr. barve in robove.

Izris hipotetičnega gumba:

Gumb -> [klic "expose" signala za ponoven izris] -> [klic pogona] -> [branje stila] -> izris na zaslon

če pogona ni, tudi pogonskega dela ni:

Gumb -> [klic "expose" signala za ponoven izris] -> [klic notranje Gtk+ funkcije] -> izris na zaslon

Vsak gradnik, ki je izrisljiv, ima posebno strukturo, ki se imenuje GdkWindow in vsebuje poleg bitne slike gradnika še dodatne informacije npr. stil teme. Najbolj pomembna signala za izrisljive gradnike sta “realize”, ki prvič ustvari GdkWindow strukturo “expose”, ki se samodejno kliče vsakič, ko Gtk+ ugotovi, da je izrisano področje gradnika na zaslonu “poškodovano” in potrebuje osvežitev.

Če želimo karkoli izrisati na katerikoli gradnik, ki se prikaže, moramo najprej pridobiti njegovo GdkWindow strukturo. In ta je na voljo ravno pri signali “expose” in “realize”. Sedaj če pogledamo v Gtk+ izvorno kodo, bomo našli imenik gtk, kjer se nahaja koda za vsak gradnik, izrisljiv in neizrisljiv. Mi pa iščemo glavno okno, torej GtkWindow. Če v kodi iščemo za signal “expose”, ga kar kmalu najdemo. Zgleda pa takole:

static gint
gtk_window_expose (GtkWidget *widget,
GdkEventExpose *event)
{
if (!GTK_WIDGET_APP_PAINTABLE (widget))
gtk_window_paint (widget, &event->area);

if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);

return FALSE;
}

To je privzeta funkcija za signal “expose”, ki bo izrisovala okno. Ta privzeti dogodek lahko prepišemo z lastnim. Vendar to ne želimo. V tej funkciji še ni nobene kode za risanje, torej gremo dalje. Funckija gtk_window_paint() se nahaja še v enaki datoteki, vsebina pa je:

static void
gtk_window_paint (GtkWidget *widget,
GdkRectangle *area)
{
gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
}

Tudi ta funkcija ne vsebuje kode za risanje. Dalje s funkcijo gtk_paint_flat_box. Tukaj si pomagamo z orodjem grep, ki ugotovi, da je funkcija v datoteki gtkstyle.c. Sedaj pa v funkciji opazimo to, o čemer sem govoril. Funkcija gtk_paint_flat_box() kliče funkcijo draw_flat_box(), ki bi jo moral ponujati pogon:

GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type,
(GdkRectangle *) area, widget, detail,
x, y, width, height);

Nadaljujemo v drugem delu.

Na virtualno mašino sem namestil Ubuntu Intrepid Ibex Alpha 1. Namestitev je skozi šla gladko. Vendar je na voljo samo alternativni cd in trenutno še ni Live CD izdaje.

Ubuntujevci mislijo resno, ko pravijo o svežem izgledu. Tako nova tema za namizje Gnome uporablja čisto nov pogon Murrine, ki je v temni podobi.

Privzeto namizje:

Shrani.si

Nautilus v Gnome 2.23.4:

Shrani.si

In še glavni meni:

Shrani.si

Če so vklopljeni 3D efekti, so nekatera okna rahlo prosojna, ker je Murrina pogon, ki podpira izris RGBA barv, se pravi da vključuje prosojnost, tretnutno samo za programe, ki to novost tudi podpirajo. Našel pa sem osnutek, ki naj bi bilo navodilo za novo temo prihjajajoče Ubuntu izdaje. Demonstracije programov, ki bi uporabile takšno temo, so zelo impresivne. Posebej mi je všeč zaobljeni robovi pri oknih brez dekoracije.