Archive | Techblog RSS for this section

Nie zapominaj o RSS autodiscovery!

Przeglądając sobie stare śmieci trafiłem na adres do stronki Minds.pl. Pomyślałem sobie, że może warto będzie śledzić ich kanał RSS. Patrzę sobie na pasek adresu i nie widzę znajomej mi ikonki. Pobieżnie przeglądam witrynę, również nie znalazłem nic co by przypominało ikonkę kanału RSS. Zrezygnowany chciałem już opuszczać witrynę, gdy nagle udało mi się odnaleźć to co poszukiwałem. Potrzebowałem na to ok. minuty, co w zasadzie oznacza, że poświęciłem sporo czasu na odnalezienie tylko jednej rzeczy!

Normalnie to ZU po prostu opuściłby przeglądaną witrynę. Pomyśleć, że wystarczyłoby dodać RSS Autodiscovery i byłby jeden problem mniej.

Pamiętaj, jeśli już robisz kanały RSS/Atom to nie zapomnij również o tej jakże przydatnej rzeczy. Zdecydowanie zwiększy użyteczność i zwiększy zapewne oglądalność (o ile użytkownik będzie śledził feedy).

AdBlock potrafi zirytować

Osobiście uważam, że AdBlock jest jednym z najlepszych rozszerzeń dostępnych dla Firefoksa. Świat bez reklam jest milszy. Niestety nie zawsze. Okazało się, że podczas pisania kolejnego frontendu, oraz przy pracach nad Just Proto AdBlock sporo namieszał. Zaczęły znikać poszczególne boksy, lub całe grafiki (nawet z tła). Zanim wpadliśmy na to co jest przyczyną stracono sporo czasu.

Najczęściej jest to wina omyłkowego nazwania elementów, lub plików. Robiąc zaślepkę, która w nazwie ma frazę “_300x250″ ryzykuję, że jej nie ujrzę. Podobnie może się stać nadając boksom z ogłoszeniem nazwę typu “Ad”. Pamiętaj, gdy ze stroną dzieją się cuda, upewnij się, czy to przypadkiem nie jest zasługa AdBlocka.

Pomówmy o prototypowaniu

Pracując jako programista nie raz, nie dwa musiałem się zmierzyć z tym co klient ma na myśli. Niestety specyfikacja nie oddaje tego jak w rzeczywistości dane funkcjonalności mają się prezentować. Sprawia to sporo problemów. Przede wszystkim konieczność wprowadzania masy poprawek z tego względu, że wyobrażenie klienta było zupełnie inne od wizji programisty.

Jest pewna metoda, która może skutecznie pomóc w poprawieniu tworzenia aplikacji oraz uniknąć wprowadzania zbędnych (a czasami czasochłonnych) poprawek. Ów metoda to, wspomniane w tytule, prototypowanie.

Prototypy pozwalają urzeczywistnić wizję tego jak poszczególne funkcjonalności, a zarazem cała aplikacja mają wyglądać. Pozwalają klientowi w początkowej fazie na ustawienie wszystkiego zgodnie z tym jak chce, a w późniejszych etapach ułatwiają stworzenie serwisu.

Miałem okazję tworzyć serwis zgodnie z wytycznymi dostarczonymi w prototypie. Muszę przyznać, że dostarczony prototyp okazał się niesamowicie pomocny i zdecydowanie przyspieszył stworzenie aplikacji z bardzo prostego powodu – uniknięcia zbędnych pytań oraz tworzenia kolejnych poprawek.

Skoro prototypy są przydatne to jakie są sposoby na ich tworzenie ? Otóż metod jest kilka, każda różni się diametralnie od innej. Każda ma jakieś zalety, ale również wady, którym postaramy się przyjrzeć.

PowerPoint – wykorzystanie prezentacji

Jest to sposób, który był również wykorzystywany w mojej firmie. Polega on na tym, że szkielet serwisu jest tworzony w aplikacji do tworzenia prezentacji. Trzeba przyznać, że dziwne zastosowanie, ale skuteczne. Okazuje się, że sporo osób do prototypowania wykorzystuje tą metodę.

Można się domyślić jak może wyglądać proces tworzenia prototypu w takiej aplikacji. Mimo swojej pozornej prostoty i łatwości taka metoda ma sporą wadę – za każdym razem trzeba wysyłać wynikowy plik do klienta, żeby mógł sobie obejrzeć całość. Co więcej, jeśli na prototyp trzeba nanieść poprawki to cały cykl trzeba powtórzyć.

Kartka – the traditional way

Sposób, który IMHO jest najzabawniejszy. Cały prototyp jest szkicowany na kartce (kartkach) papieru. Nie wiem czy muszę tłumaczyć jak ten sposób wydaje się być śmieszny z wielu względów. Najdrobniejszy błąd w prototypie wymaga stworzenia go od nowa. Poza tym problemem jest przesłanie takiego prototypu do klienta.

Co ciekawe znana firma Corel swego czasu tworzyła prototypy na papierze, które później były wykorzystywane do testów usability. Na YouTube można znaleźć film prezentujący taki test. Myślę, że po obejrzeniu tego filmu nie będzie trzeba wymieniać wad.

JustProto.com – nowe podejście do prototypowania!

Jestem dumny z tego, że mogę przedstawić na moim blogu produkt, w którego tworzeniu również miałem okazję uczestniczyć. Mowa o JustProto, serwisie umożliwiającym tworzenie prototypów online.

Jakie są zalety naszego rozwiązania? Przede wszystkim jest to prostota. Wszystko staraliśmy się zrobić prosto ze względu na to, że nie chcemy uczyć użytkowników obsługi naszej aplikacji. Wszystko ma być intuicyjne dzięki czemu nie będziecie tracili czasu na poznawanie nowego środowiska.

Co więcej? Prototypy tworzone w JustProto są interaktywne. Oznacza to, że można stworzyć dynamiczny prototyp z odnośnikami prowadzącymi na kolejne podstrony.

Ze względu na to, że wszystko jest online prototyp jest dostępny z każdego miejsca, bez konieczności instalowania dodatkowych aplikacji.

Jedną z najważniejszych zalet jest generowanie wersji online prototypu, dzięki czemu wystarczy klientowi dostarczyć odpowiedni link a ten będzie mógł na bieżąco oglądać zmiany robione w prototypie – wystarczy F5 :)

Opinie innych użytkowników nt. JustProto

Zaproszenia

JustProto pozwala na skorzystanie z darmowej 30 dniowej wersji trial. Jednakże jeśli wydaje się to dla Ciebie za mało to wystarczy się zgłosić do mnie po kupon z promocyjnym kodem, który wydłuża wersję testową do 60 dni.

Jeśli jesteś zainteresowany tworzeniem prototypów to serdecznie zapraszam :)

Instalacja modemu Huawei e169 na Arch Linux

Słowem wstępu, a zarazem nawiązując do wcześniejszej notki musiałem chwilkę powalczyć z tym, żeby odpalić ten modem pod Linuksem. Podczas lektury wyników z googla naczytałem się o różnych sposobach typu usb_modeswitch. Tak naprawdę okazały się zbędne. Ten problem można rozwiązać na dwa sposoby.

wvdial

Osobiście wydaje mi się, że jest to najwygodniejsza opcja. Wystarczy prosty config (niżej zamieszczam), oraz jeszcze prostszy skrypt w bashu, który jest odpowiedzialny za połączenie i rozłączenie i to wszystko. Rozłączanie jest tym bardziej zabawne (jak dla mnie), ponieważ wystarczy ubić proces wvdial, a ten (wyłapując odpowiedni sygnał) wszystko ładnie po sobie posprząta.

Muszę jeszcze dodać, że aby wszystko działało muszę tworzyć ręcznie interfejs ppp, poleceniem “mknod /dev/ppp c 108 0″.

Niestety wvdial służy tylko i wyłącznie do ustanawiania połączeń. Modem ma nieco większe możliwości (chociażby wysyłanie/odbieranie smsów, książka adresowa, no ale pewnie to zasługa karty sim w środku :) ), których w ten sposób nie obsłużymy. Z drugiej jednak strony nie wiem czy to jest specjalnie do czegoś potrzebne.


umtsmon

Dziwny to program, paskudny z wyglądu, ale co ciekawe skuteczny. Na początku problem sprawiło mi to, że nie chciał się włączyć. Powód był tak banalny, że dziwię się programistom, że nie mogli tego załatwić inaczej. Otóż locale mam na laptopie ustawione na pl_PL, a umtsmon nie ma takiej wersji językowej. Ot cała filozofia. Szkoda tylko, że zamiast ładować angielską wersję, program się posypał. Rozwiązanie – ‘export LANG=en_EN’.

Gdy już mogłem zobaczyć okienko zdziwiło mnie, że prawie od razu widać było siłę sygnału itd. Było troszkę problemów z ustanowieniem połączenia, ale chwila grzebania w opcjach dała rezultat. Przede wszystkim trzeba było zaznaczyć opcję ‘no auth’ i odznaczyć ‘default route..’. Po ustawieniu tego okazało się, że (podobnie jak w przypadku wvdial) muszę ręcznie stworzyć interfejs ppp, wykonując to samo polecenie.

Po tych zabiegach wszystko zaczęło śmigać. umtsmon ma jeszcze jedną zaletę – dostęp do SIM, chociaż nie wiem w jakim zakresie. Nie udało mi się nawet odczytać smsa, którego otrzymałem, a później po prostu go wyłączyłem. Nie spodobało mi się to, że nie minimalizuje się do traya, oraz fakt, że musiałem go odpalać z roota, tak aby miał dostęp do modemu.

Mini podsumowanie

W moim przypadku padł wybór na wvdial. Jest prosty, skuteczny i tyle :) Muszę jeszcze wykombinować żeby podpiąć odpowiednie zdarzenia do udev’a, tak żeby mój magiczny skrypt sam się wykonywał. Gdzieś mam regułkę odpowiedzialną za to, niestety po wpięciu do niej tego skryptu nic się nie działo. Poza tym można by było za pośrednictwem tegoż udev’a zrobić rozłączanie z internetem, zaraz po wyjęciu modemu.

Dodam, że nie testowałem tego rozwiązania na innych systemach, także nie mam pewności czy tam będzie działało.

Niżej załączam konfigurację do wvdial (ps nic w nim się nie zmienia, nie podaje haseł etc. Możliwe, że podziała również w sieciach Plus, ale gwarancji nie daję), oraz skrypt odpalający neta.

wvdial.conf

[Dialer Defaults]
Phone = *99#
Username = "blank"
Password = "blank"
Stupid Mode = 1
Dial Command = ATD

[Dialer hsdpa]
Modem = /dev/ttyUSB0
Baud = 460800
Init2 = ATZ
Init3 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ISDN = 0
Modem Type = Analog Modem

play.sh

#!/bin/bash
case $1 in
  "disconnect") sudo kill `pidof wvdial` ;;
  *)
	if [ ! -e /dev/ppp ]; then
		mknod /dev/ppp c 108 0
	fi;
 	sudo wvdial hsdpa > /dev/null 2>&1 &
 ;;
esac

Prawie jak firebug w Operze

Dziw nastał. Wielu twierdzi, że Firefox trzymał webdeveloperów dzięki wtyczkom takim jak “Firebug“. Dzisiaj znajomy podrzucił mi ciekawego linka do części developerskiej Opery. (PS, żeby było zabawniej to jest wiadomość z 2006 roku, dziwne, że wcześniej o tym nie słyszałem)

Mamy do czynienia z czymś na wzór skryptozakładki, która pozwala na przeglądanie drzewa DOM, wraz z jego modyfikacją i możliwością podejrzenia zmian. Chwilkę się pobawiłem tą zabawką i muszę przyznać, że mamy coś podobnego do Firebug’a. Ten dodatek, choć bardzo fajny (pozwala dodatkowo modyfikować Cookies + nagłówki HTTP), ma pewne dziwne i mało wygodne rozwiązania.

Podobnie jak Firebug ta skryptozakładka (hmm chyba bez nazwy?) potrafi podświetlać dowolny element, ale najpierw trzeba go znaleźć w drzewie DOM. Biorąc pod uwagę, że nie wie się za bardzo gdzie to może być to ten bajer troszkę jest zbędny. Tym bardziej, że element jest podświetlony na 3-4 sek, po czym wszystko wraca do normy.

Problemem też może być edycja tekstu w bloku. Jeśli znajdują się w nim elementy takie jak “<br/>” to musimy za każdym razem wybierać etykietę “text” nad tym <br/>, a później z osobna edytować kolejną etykietkę “text”, która już jest pod <br/>. Szkoda, że nie można po prostu zmodyfikować kodu HTML, tak jak w Firebug.

Z ciekawszych rzeczy mamy oczywiście inspektora DOM, oraz możliwość podglądu (edycji?) kodu JS – tego akurat nie sprawdzałem.

Podsumowując bajer fajny, pewnie o wiele szybszy, lecz niestety jeszcze nie dorównujący wtyczce Firebug.
Niżej zamieszczam przykładowego screena + button, które możecie w swojej Operze dodać.

Drag Developer Console

Free Image Hosting at www.ImageShack.us

ATI Radeon Xpress 1100 na ubuntu – działa!

Jednak nie było aż tak źle. Wcześniej strasznie się męczyłem, bo sterowniki ze strony ATI nie chciały w ogóle się włączać. Dzisiaj pobrałem plik “ati-driver-installer-8.40.4-x86.x86_64.run“, a potem już w konsoli:

chmod +x ati-driver-installer-8.40.4-x86.x86_64.run
./ati-driver-installer-8.40.4-x86.x86_64.run --buildpkg Ubuntu/feisty
sudo dpkg -i ./*.deb
sudo m-a prepare,update
sudo m-a build,install fglrx-kernel
sudo depmod

Restart X-ów, i tyle. U mnie działa :)

Edit: teraz dopiero się zorientowałem, że pobrałem wersję 64 bitową, a mój laptop ma procesor 32 bitowy.. o_0

Akordeon

Przyznam się, że nie wiedziałem jak nazwać tą notkę także wybaczcie mi to ;-) Chciałem napisać (specjalnie na prośbę Grzegorza Piechuły ;-] ) sposób w jaki przedstawione są u mnie notatki z minibloga.

Cel jaki chcemy osiągnąć to warstwa (w niej będzie treść notek), która zwija się i rozwija. Poza tym zrobimy tak, że gdy jedna notka będzie rozwinięta, a chcemy zobaczyć drugą to ta pierwsza posłusznie się zwinie, a dopiero później pokaże się druga.

Całość oparłem o framework jQuery, także należy się w niego wyposażyć. Na początku zaczniemy od zakodowania naszych notek:

<div id="notes">
        <h3>Nagłówek 1</h3>
        <div>
                <p>
                Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
                Morbi vel elit vel nulla accumsan euismod. 
                Cras nulla elit, aliquam placerat, consectetuer pulvinar, mattis in, lacus. 
                Maecenas nulla sapien, sollicitudin id, gravida non, porttitor quis, sapien.
                </p>
                <p class="up">[zamknij]</p>
        </div>
        
        <h3>Nagłówek 2</h3>
        <div>
                <p>
                Maecenas sed magna adipiscing justo facilisis volutpat. Maecenas at tellus. Aliquam erat volutpat.
                Morbi lobortis viverra urna. Sed non augue quis justo adipiscing blandit. 
                Aenean eros turpis, aliquet ac, adipiscing ut, porta mollis, ante.
                Aenean massa massa, faucibus ut, lacinia sed, dictum vitae, nulla.
                </p>
                <p class="up">[zamknij]</p>
        </div>
</div>

Poza tym możemy jeszcze ładnie opisać CSSem nasze notatki tak, żeby ładniej wyglądały ;-) Tak na stronie będą się one prezentowały na przeglądarkach, które nie korzystają, lub mają wyłączoną obsługę JavaScript.

Chciałem od razu uprzedzić, że blok z klasą “up” będzie służył do zamykania otwartych okienek, także na samym początku warto w stylach dopisać do tej klasy (“.up”) display na none tak aby blok niepotrzebnie pokazywał się w przeglądarce bez JSa.

Dla tych, którym nie chce się pisać wszystkiego zapraszam tutaj.

Teraz przejdziemy do kolejnego kroku. Dołączymy jQuery, oraz zapiszemy pierwsze linijki kodu, który “ułoży” nasze notatki w jednym miejscu oraz je schowie.

W sekcji head dopisujemy:

<script src="/sciezka/do/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(
function()
{
        // (...) <- tutaj będziemy wstawiali nasz kod ;-]
}
);
</script>

Do arkusza stylów dopisujemy klasę dla bloków div, w których są notki. Ta klasa będzie nadawała każdej notce pozycję absolutną (gdyby co chodzi o position:absolute; ;-] ), oraz będzie chowała w/w notki. Na potrzeby tego tekstu tą klasę nazwę po prostu “j”.

Nasz skrypt, zaraz po załadowaniu drzewa DOM, musi nadawać wszystkim notkom klasę “j” (tak aby ją schować), oraz pokazać bloki z klasą “up”, tak aby były widoczne po rozwinięciu notki. Przypominam, że bloki z klasą “up” będą służyły do zamykania rozwiniętych notatek.

$("#notes > div").addClass("j");
$("#notes p.up").show();

Teraz nadajemy zdarzenie click nagłówkom h3, które będzie pokazywało odpowiednie notki. Przy okazji nadamy blokom z klasą “up” zdarzenie click, po którym nasza notka schowie się.

$("#notes").children("h3").click(
function()
{
        $(this).next("div").slideToggle("normal");
        $("#notes > h3").not(this).next("div:visible").slideUp("fast");
}
);
$("#notes p.up").click(
function()
{
        $(this).parent().slideUp("normal");
}
);

Demo

Niestety jeszcze nie osiągnęliśmy do końca oczekiwanego efektu. Wprawdzie notka się rozwija, zwija itd… Problem jest w tym, że gdy chcemy zobaczyć drugą notkę, podczas gdy pierwsza jest widoczna, to jedna notka zwija się przy czym jednocześnie druga się rozwija. My chcemy zrobić tak aby najpierw pierwsza notka się zwinęła, a dopiero później druga się rozwinęła.

Można by było kombinować z wykorzystaniem jakiś funkcji typu sleep(), jednak gdy do metody slideUp (i nie tylko tej) przekażemy drugi parametr (pierwszy to prędkość zwijania/rozwijania) jako funkcję, zostanie ona wykonana po zakończeniu zwijania.

Brzmi strasznie? Na szczęście tak nie jest ;-) Zmienimy zdarzenie click nadane elementowi h3.

Problemem jest to jak sprawdzić czy już jakiś div jest rozwinięty. Na szczęście możemy wykorzystać metodę is(), która zwraca wartość TRUE, lub FALSE, a korzystamy z niej podobnie jak z metody filter().

Jakoś nie potrafię opisać wszystkiego słowami także przedstawię kod, a w komentarzach opiszę całość.

$("#notes").children("h3").click(
function()
{
        var tmp = $(this); // musimy przypisać obiekt do zmiennej pomocniczej, ponieważ w innym wypadku nie uda nam się rozwinąć notki
        if( $(this).next("div").is(":visible") )
        {
                // Jeśli notka o wybranym tytule już była pokazana, w tym momencie zostanie schowana
                $(this).next("div").slideUp("normal");
        }
        else if( $("#notes h3").next("div").is(":visible") )
        {
                // zwinięcie rozwiniętej notki, a dopiero pozniej rozwiniecie kolejnej
                $("#notes h3").next("div:visible").slideUp("normal",
                        function() { tmp.next("div").slideDown("normal"); }
                        // w tym miejscu wykorzystujemy właśnie zmienną pomocniczą _tmp_
                        // bez niej niesety nie byłoby możliwe rozwinięcie nowej notki
                );
        }
        else
        {
                $(this).next("div").slideDown("normal");
                // Jesli nie ma zadnej notki, ta zostanie rozwinięta
        }
}
);

Demo

To by było tyle. Wiem, że nie potrafię dobrze takich rzeczy opisywać, ale uwierzcie – starałem się.

Kurs PHP-GTK cz. 2

Już minęło sporo czasu od pojawienia się pierwszej części kursu PHP-GTK. Chciałem mocno przeprosić za to, że musieliście czekać, niestety w sporej mierze to wina mojego lenistwa…

Dzisiaj zajmiemy się czymś bardziej skomplikowanym. Stworzymy formularz logowania, który pokaże komunikat błędu jeśli wpiszemy złe hasło/login.


Screeny

Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us

Zaczynamy

Na początku tworzymy nowy obiekt-okno, nadajemy mu tytuł, oraz tworzymy proste dowiązanie przerywające główną pętlę (Gtk::main).

<?php
$wnd = new GtkWindow();
$wnd->set_title('Login');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));
?>

Później tworzymy dwa pola, do których będziemy mogli wpisać login i hasło. Podobnie jak w wypadku labela tworzymy dwie zmienne, które będą po prostu obiektami.

$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();

Dodatkowo do tych pól stwórzmy etykietki, aby rozróżnić oba pola.

$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);

Zwróćcie uwagę, że dodano jeszcze drugi parametr. Jest on opcjonalny, a gdy jest ustawiony na true, to literka przed którą będzie znak ‘_’, będzie podkreślona.

Pozostało nam jeszcze stworzenie dwóch przycisków – “Login” i “Cancel”.

$btnLogin    = new GtkButton('_Login');
$btnCancel   = new GtkButton('_Cancel');

W odróżnieniu od GtkLabel(), w przypadku GtkButton() nie musimy podawać drugiego parametru aby kolejna litera po ‘_’ była podkreślona.

Teraz ustawimy połączenie pomiędzy GtkLabel, a GtkEntry. Ktoś się spyta, co to takiego? Już tłumaczę. To podkreślenie, które ustwiliśmy jest niczym innym jak skrótem klawiszowym. Po wciśnięciu kombinacji [Alt]+[u] pole Username zostanie aktywowane, podobnie jest z drugim polem. Aby stworzyć takie połączenie wykorzystujemy metodę set_mnemonic_widget.

$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);

Pozostaje nam jeszcze najważniejsze. Ustawienie odpowiednich zdarzeń, które muszą nastąpić po wciśnięciu na Buttony.

$btnCancel->connect_simple('clicked', array($wnd, 'destroy'));
$btnLogin ->connect_simple('clicked', 'login', $wnd, $txtUsername, $txtPassword);

Po wciśnięciu “Cancel” program po prostu się wyłączy. Po wciśnięciu “Login” zostanie wywołana (jeszcze nie opisana) funkcja “login”, zmienne $wnd, $txtUsername, $txtPassword są po prostu parametrami przesyłanymi do funkcji.

Już wcześniej wspominałem, że okno może trzymać bezpośrednio tylko jeden widżet. Rozwiązaniem są różne kontenery, które wszystko przetrzymują wewnątrz, a potem są “doklejane” do głównego okna. W tym wypadku posłużymy się GtkTable, które w przejrzysty sposób utrzyma nasze widżety (zmienna $lblCredit, będzie jedynie przechowywała krótki komunikat).

Aby zamieścić nasze widżety w tabelkę należy wykonać coś takiego:

$tbl = new GtkTable(3, 2);
$tbl->attach($lblCredit, 0, 2, 0, 1);
$tbl->attach($lblUsername, 0, 1, 1, 2);
$tbl->attach($txtUsername, 1, 2, 1, 2);
$tbl->attach($lblPassword, 0, 1, 2, 3);
$tbl->attach($txtPassword, 1, 2, 2, 3);

Niestety umieszczanie elementów w tabeli wydaje się IMO wyjątkowo udziwnione. Żeby to jakoś ułatwić, postaram się króciutko wyjaśnić co oznaczają kolejne parametry.

void attach(GtkWidget child, int left_attach, int right_attach, int top_attach, int bottom_attach [, GtkAttachOptions xoptions = Gtk::EXPAND|Gtk::FILL [, GtkAttachOptions yoptions = Gtk::EXPAND|Gtk::FILL [, int xpadding = Gtk::EXPAND|Gtk::FILL [, int ypadding = Gtk::EXPAND|Gtk::FILL]]]]);

Taki jest początek opisu tej metody. Nie chcę straszyć nikogo także wytłumaczę tylko czym są te cyferki ;-)

int left_attach – oznacza miejsce od lewej strony
int right_attach – oznacza miejsce od prawej strony
int top_attach – oznacza miejsce od góry
int bottom_attach – oznacza miejsce od dołu

Możliwe, że źle zrozumiałem sposób umiejscowienia w tabelce elementów, także poprawcie mnie jeśli się mylę.

Przyciski dostaną swój własny kontener.

$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnCancel);
$bbox->add($btnLogin);

Stworzyliśmy dwa osobne kontenery, ale główne okno, może mieć “przyczepiony” tylko jeden widżet, także oba kontenery dodamy do kolejnego.

$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);

Dopiero teraz możemy dodać nasze widżety na główne okno (konkretniej dodajemy kontener, który przechowuje wszystkie widżety).

$wnd->add($vbox);
$wnd->show_all();
Gtk::main();

Teraz pozostaje nam zapis funkcji logowania. Jeśli jakieś z pól pozostanie puste, wyświetli się komunikat o błędzie. Jeśli uda nam się zalogować to dostaniemy komunikat, że wszystko jest ok, po czym program się wyłączy.

Aby wyciągnąć zawartość pól “Username” i “Password”, posługujemy się metodą get_text() dołączoną do klasy GtkEntry.

$strUsername = $txtUsername->get_text();
$strPassword = $txtPassword->get_text();

Poprawność wpisanego tekstu sprawdzamy poprzez zwykłe funkcje PHP (nie zapominajcie, że to jest tylko dodatek do PHP ;-] ).

W celu wyświetlenia okna dialogowego wystarczy wpisać:

$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $errors);
$dialog->set_markup("W I A D O M O S C");
$dialog->run();
$dialog->destroy();

Na koniec załączam gotowy kod (można go również pobrać z phpfi):

<?php
if (!class_exists('gtk')) {
    die("Please load the php-gtk2 module in your php.ini\r\n");
}

/**
*   Ta funkcja zostaje wywołana po kliknieciu buttona "Login"
*
*   @param GtkWindow $wnd           Okno logowania, potrzebne, zeby je pozniej 
*                                   zamknac
*   @param GtkEntry $txtUsername    Pole tekstowe, potrzebny zeby wyciagnac 
*                                   tekst
*   @param GtkEntry $txtPassword    Tak samo jak wyzej
*/

function login(GtkWindow $wnd, GtkEntry $txtUsername, GtkEntry $txtPassword)
{
    //pobranie wartosci pol tekstowych
    $strUsername = $txtUsername->get_text();
    $strPassword = $txtPassword->get_text();
 
    //sprawdzanie potrzebnych rzeczy
    $errors = null;
    if (strlen($strUsername) == 0) {
        $errors .= "Brakuje nazwy uzytkownika.\r\n";
    }
    if (strlen($strPassword) == 0) {
        $errors .= "Brakuje hasla.\r\n";
    }
 
    if ($errors !== null) {
        //Jesli byl przynajmniej blad to powinno sie pokazac okno dialogowe
        $dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL,
            Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $errors);
        $dialog->set_markup(
            "Wystapily pewne problemy:\r\n"
            . "<span foreground='red'>" . $errors . "</span>"
        );
        $dialog->run();
        $dialog->destroy();
    } else {
        $msg = "Witaj $strUsername!\r\n";
        $msg .= "Twoje magiczne haslo to: $strPassword ;-]";

        $dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK, $msg);
        $dialog->set_markup($msg);
        $dialog->run();
        $dialog->destroy();
        $wnd->destroy();
    }
}
 
$wnd = new GtkWindow();
$wnd->set_title('Login');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));

// stworzenie pol tekstowych
$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();

// stworzenie etykiet
$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);
$lblCredit = new GtkLabel('Please login');

// stworzenie buttonow
$btnLogin    = new GtkButton('_Login');
$btnCancel   = new GtkButton('_Cancel');

// ustawienie skrotow klawiszowych
$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);

// polaczenie zdarzen
$btnCancel->connect_simple('clicked', array($wnd, 'destroy'));
$btnLogin ->connect_simple('clicked', 'login', $wnd, $txtUsername, $txtPassword);

// stworzenie tabelki
$tbl = new GtkTable(3, 2);
$tbl->attach($lblCredit, 0, 2, 0, 1);
$tbl->attach($lblUsername, 0, 1, 1, 2);
$tbl->attach($txtUsername, 1, 2, 1, 2);
$tbl->attach($lblPassword, 0, 1, 2, 3);
$tbl->attach($txtPassword, 1, 2, 2, 3);

// kontener na przyciski
$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnCancel);
$bbox->add($btnLogin);

// kontener przechowujacy tabelke i buttony
$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);

$wnd->add($vbox);
$wnd->show_all();
Gtk::main();
?>

Przypominam, że póki co ten kurs jest jedynie tłumaczeniem oficjalnego kursu, którego można znaleźć na stronie php.net

Status serwera wykorzystując CSS – podejście drugie

Tym razem będzie krótka notka. Dawniej pisałem o tym jak za pomocą CSS można wyświetlać status serwera (czyli to czy jest offline, czy też online). Niedawno przyszedł mi do głowy nieco inny sposób na wykorzystanie CSSa do tego celu.

Podstawowym problemem poprzedniego pomysłu był fakt ładowania się strony. Jeżeli serwer był offline to strona ładowała się niesamowicie długo z tego względu, że nie mogła załadować CSSa znajdującego się na tym serwerze (przypomnę, że ten arkusz zmieniał wyświetlanie dwóch elementów, przez co “zmieniał” się napis). To co mi niedawno zaświeciło w głowie to załadowanie obrazka jako background dla jakiegoś elementu. W praktyce to wyglądałoby tak:

W kodzie strony:

<div id=”status”>&nbsp;</div>

Natomiast w CSS:

#status { background-image: url(‘http://example.com/blah.jpg’); }

Oczywiście styl można dowolnie wzbogacić, tutaj został przedstawiony wyjątkowo uproszczony..

Jaka jest zaleta takiego rozwiązania? Z tego co zauważyłem strona ładuje się normalnie, a wszelkie obrazki (które są użyte jako tło) ładują się nie wpływając na resztę. Niejednokrotnie zauważyłem, że cała strona jest już załadowana, a tło dla jakiegoś elementu załadowało sie dopiero po jakimś czasie. Dlatego też takie rozwiązanie jest wygodne, ponieważ nie powinno za bardzo spowolnić ładowania strony.

Wadą tego jest to, że jeśli faktycznie serwer jest offline, to element blokowy nie pokaże żadnej informacji na ten temat. Ew. można zrobić tak, że do takiego elementu nada się jeszcze jakiś kolor tła, który będzie symbolizował to, że serwer jest offline.

Kurs PHP-GTK cz.1

PHP-GTK to rozszerzenie PHP stworzone przez Andrieja Zmiewskiego pozwalające używać popularnej biblioteki GTK+ służącej do tworzenia graficznych interfejsów użytkownika na podstawie zestawu dostępnych widgetów (kontrolek). Programy korzystające z PHP-GTK wyróżniają się łatwością i szybkością napisania.

via Wikipedia

Już od dawna chciałem chociaż troszkę poznać to rozszerzenie. Trochę to potrwało zanim cokolwiek się dowiedziałem. Aktualnie sam poznaję PHP-GTK, ale mogę już opisać pewne “podstawy podstaw”. Ten kurs proszę traktujcie raczej jako wolne tłumaczenie kolejnego z rozdziałów tutoriala znajdującego się na stronie projektu.


Instalacja

Aby zainstalować rozszerzenie PHP-GTK należy skompilować jego źródła. Dobry kurs na zrobienie tego pod Ubuntu (czyli pewnie też i pod Debianem) znajduje się na forum Ubuntu. Ja tylko przypomnę jak należy skompilować tą paczkę.

Źródła można pobrać stąd. Po ściągnięciu i rozpakowaniu wchodzimy do katalogu, a potem w konsoli wpisujemy:

./buildconf 
./configure 
make 
sudo make install

Później pozostaje nam jedynie edycja pliku /etc/php5/cli/php.ini, a mianowicie dopisanie na końcu czegoś takiego:

extension=php_gtk2.so

Hello World

Zawsze wszystko zaczyna się od tego prostego skryptu/programu. Naszym celem będzie wyświetlenie okienka dialogowego z napisem “Hello World”. Podobnie jak innym kursie przedstawię najpierw kod, a potem zajmę się jego tłumaczeniem.

<?php
if (!class_exists('gtk')) {
    die("Please load the php-gtk2 module in your php.ini\r\n");
}
 
$wnd = new GtkWindow();
$wnd->set_title('Hello world');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));
 
$lblHello = new GtkLabel("Just wanted to say\r\n'Hello world!'");
$wnd->add($lblHello);
 
$wnd->show_all();
Gtk::main();
?>

Jeśli pokaże nam się komunikat: Fatal error: Call to undefined function: connect_simple() to oznacza, że prawdopodobnie korzystasz z wersji GTK1. Ten kurs obejmuje jedynie GTK2, także nie masz czego tutaj szukać ;-]

Takiemu plikowi nadajemy dowolną nazwę, ale dla odróżnienia od innych, zwykłych, skryptów PHP nadajmy mu rozszerzenie *.phpw. Ważne jest aby odpalić skrypt spod konsoli poleceniem php {nazwa_pliku}. Otwierając przez przeglądarkie nie zobaczymy żadnych efektów.

Na specjalne życzenie S. wstawiam dodatkowo zrzut efektu działania tego skryptu:

PHP-GTK Hello World Script

Sprawdzanie czy klasa GTK istnieje

if (!class_exists('gtk')) {
    die("Please load the php-gtk2 module in your php.ini\r\n");
}

Te linijki są odpowiedzialne za sprawdzenie, czy rozszerzenie PHP-GTK jest zainstalowane. Jeśli nie jest skrypt się nie wykona, ponieważ nie znajdzie klasy “gtk”. Dawniej w takim wypadku stosowało się polecenie dl(), lecz w PHP 5 to polecenie posiada status “deprecated”, także nie zaleca się jego stosowania.

Tworzenie głównego okna

$wnd = new GtkWindow();

Tworzenie nowego okna jest proste jak tworzenie nowego obiektu. Zmienna $wnd jest właśnie deklarowana jako obiekt.

$wnd->set_title('Hello world');

Metoda set_title sprawia, że okienko będzie miało jakiś tytuł. Wiadomo, że to akurat jest przydatne ;-)

$wnd->connect_simple('destroy', array('gtk', 'main_quit'));

To jest bardzo ważna linijka. Bez niej po wyłączeniu skryptu główna pętla będzie się cały czas wykonywała. W tym wypadku metoda connect_simple sprawia, że po zamknięciu (a dosłownie mówiąc – po zniszczeniu) okna pętla zostanie przerwana.

Metoda connect_simple służy również do podpinania różnych zdarzeń pod odpowiednie funkcje. Przykłado dla kliknięcia buttona, który jest zdefinowany w osobnej zmiennej, skorzystanie z tej metody wyglądałoby tak:

$button->connect_simple("clicked", array($wnd, "zdarzenie"));

Po kliknięciu na ten guzik zostanie wywołana funkcja “zdarzenie”. W następnych częściach postaram się lepiej przedstawić jak z czegoś takiego korzystać.

Tworzenie labela, z napisem “Hello World”

Tworzenie nowego labela (tudzież etykietki) polega na stworzeniu nowego obiektu. W naszym przykładzie jest to po prostu:

$lblHello = new GtkLabel("Just wanted to say\r\n'Hello world!'");

Jak widać nowa etykietka to nowy obiekt, a jej zawartość to paramter, który został podany podczas tworzenia obiektu.

Aby dodać (hmm dokleić) naszą etykietę należy jeszcze dopisać:

$wnd->add($lblHello);

Główne okno sprawia jeden mały problem. Jest nim mianowicie to, że można do niego “wsadzić” tylko jeden widżet. W tej części kursu tylko jeden widżet jest przyczepiany, także nie ma większych problemów, ale w późniejszych częściach widżety trzeba będzie “składować” w jakimś pojemniku. Taki pojemnik dopiero przytwierdzamy do głównego okna. Umożliwi to nam wyświetlenie kilku widżetów w głównym oknie.

Wyświetlenie okna

Póki co naszeg okno nie będzie widoczne. Aby je pokazać, należy skorzystać z metody show_all():

$wnd->show_all();

Ta metoda sprawi, że zostaną pokazane wszystkie widżety. Można również skorzystać z metody show(), ale w tym wypadku należałoby stosować ją dla każdego obiektu, ponieważ inaczej nie zostanie wyświetlony.

Po tych “zabiegach” pozostaje nam odpalenie głównej pętli Gtk::main();. Ta pętla sprawi, że nasze okno będzie się wyświetlało nawet wtedy kiedy skrypt będzie bezczynny. Normalnie (tzn, bez tej pętli) nasz skrypt by się wykonał, a okno prawdopodobnie by tylko mignęło, ponieważ po wykonaniu działania skrypt by się wyłączył, czyli nasze okno by zginęło.

Podsumowanie

W tym (bardzo) krótkim kursie przedstawiłem sposób instalacji rozszerzenia PHP-GTK, oraz bardzo podstawowego sposobu pisania skryptów z wykorzystaniem klasy “gtk”. W następnym kursie postaram się coś więcej już przedstawić. Nie wiem kiedy kolejna część wyjdzie, ale powinna się ukazać.

Gdyby ktoś chciał bardziej poznać PHP-GTK to niech zajrzy sobie na anglojęzyczny kurs.