Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

dpsidebar - programowanie w windows cz.3

Wszystko wskazuje na to, że seria o dpsidebar będzie pierwszą i być może nawet nie ostatnią serią wpisów, które na łamach DP.pl dokończę... Cóż, czas ucieka, więc biorę się do pisania. W poprzedniej części obiecałem, że zajmę się settingsami i flyoutami. Do dzieła!

Settings

Jak już wcześniej wspominałem, settings to osobna strona, która tak naprawdę jest szablonem, który tylko w niewielkim stopniu możemy modyfikować. Za to dużo ciekawiej robi się, gdy popatrzymy na możliwości settingsów. Przede wszystkim obiekt System.Gadget.Settings posiada cztery metody do zapisywania i odczytywania ustawień. Są to read, readString, write, writeString. Metody te jednak zapisują ustawienia tylko tymczasowo, to znaczy na czas działania gadgetu. Innymi słowy - po restarcie ustawienia się stracą. DPSidebar będzie jednak korzystał z pliku z konfiguracją, wobec tego nie będziemy się musieli przejmować ograniczeniami tych metod.

Komunikacja między settingsami (flyoutami także, do czego dojdziemy) może komunikować się z nadrzędnym ciałem gadgetu przez obiekt System.Gadget.document.parentWindow. HTML jest bardzo prosty - zwykła tabelka z dwoma kolumnami i rzędami. Javascript również jest prosty:

function int() { if(System.Gadget.document.parentWindow.cfg.show_avatars == "true") { $("#show_avatars").attr("checked", true); } else { $("#show_avatars").attr("checked", false); } $("#refresh").val(System.Gadget.document.parentWindow.cfg.refresh); } System.Gadget.onSettingsClosing = SettingsClosing; function SettingsClosing(event) { $("#settings").val($("#show_avatars").val()); if (event.closeAction == event.Action.commit) { System.Gadget.document.parentWindow.cfg.loadFile(); if($("#show_avatars").attr("checked") == "checked") { System.Gadget.document.parentWindow.cfg.show_avatars = true; } else { System.Gadget.document.parentWindow.cfg.show_avatars = false; } System.Gadget.document.parentWindow.cfg.refresh = $("#refresh").val(); System.Gadget.document.parentWindow.cfg.saveFile(); System.Gadget.document.parentWindow.init(); } event.cancel = false; }

W kodzie może być nieoczywiste tylko skorzystanie z eventu onSettingsClosing. Odpalany jest on oczywiście w momencie zamykania settingsów. Są tylko trzy znane światu metody na zamknięcie settingsów. Kliknięcie OK, kliknięcie Anuluj i zamknięcie procesu sidebar.exe. Ostatni nie będziemy brać pod uwagę. Pierwsza dwa pozwalają za to zdecydować, czy należy zapisać dane wprowadzone, czy należy je zignorować. Obiekt System.Gadget.Settings.ClosingEvent posiada parametr Action, który przyjmuje dwie wartości: commit i cancel. Weryfikujemy więc czy dostaliśmy commit i zapisujemy w obiekcie nadrzędnym ustawienia korzystając z obiektu cfg. I to wszystko co robimy w settingsach.

Flyout

Flyout to element gadgetu, który "dokleja" się do głównego ciała i pozwala na wyświetlenie dodatkowych danych. Zgodnie z naszymi wymaganiami biznesowymi należy dynamicznie usuwać kolejne artykuły z monitoringu oraz wyświetlanie pełnej wersji komentarza. Oba te wymagania zrealizujemy właśnie przez flyout.

Flyout może być zupełnie osobnym bytem, posiadającym w 100% niezależną strukturę. Jednak dla nas będzie to zupełnie zbędne. Przy pomocy obiektu System.Gadget.Flyout.document będziemy wstrzykiwać do struktury DOM flyouta nasze treści. Utworzyłem sobie dwie proste funkcje by wyświetlić pełnego newsa oraz zarządzać monitorowanymi adresami:

unction getFullComment(comment_id) { if(System.Gadget.Flyout.show) // Flyout juz jest wyswietlony. { System.Gadget.Flyout.document.getElementById("flyout_div").innerHTML = dpsidebar.createFullComment(comments[comment_id]); $(System.Gadget.Flyout.document.body).height($(System.Gadget.Flyout.document.getElementById("wrapper")).height()+45+"px"); } else { System.Gadget.Flyout.show = true; oFlyoutDocument = System.Gadget.Flyout.document; System.Gadget.Flyout.onShow = function() { System.Gadget.Flyout.document.getElementById("flyout_div").innerHTML = dpsidebar.createFullComment(comments[comment_id]); $(System.Gadget.Flyout.document.body).height($(System.Gadget.Flyout.document.getElementById("wrapper")).height()+45+"px"); } } } function manage_urls() { body = dpsidebar.createURLView(cfg.urls); if(System.Gadget.Flyout.show) // Flyout juz jest wyswietlony. { System.Gadget.Flyout.document.getElementById("flyout_div").innerHTML = body; $(System.Gadget.Flyout.document.body).height($(System.Gadget.Flyout.document.getElementById("wrapper")).height()+45+"px"); } else { System.Gadget.Flyout.show = true; oFlyoutDocument = System.Gadget.Flyout.document; System.Gadget.Flyout.onShow = function() { System.Gadget.Flyout.document.getElementById("flyout_div").innerHTML = body; $(System.Gadget.Flyout.document.body).height($(System.Gadget.Flyout.document.getElementById("wrapper")).height()+45+"px"); } System.Gadget.Flyout.onHide = function() { cfg.saveFile(); rotate(); } } }

Obie sprawdzają w pierwszej kolejności czy flyout nie jest już czasem wyświetlony, jeśli nie jest podmienia w divie flyout_div treść. Gdyby jednak nie był wyświetlony- wyświetla go (System.Gadget.Flyout.show = true;) oraz w evencie onShow dodaje treść. Zmienia także dynamicznie jego wysokość (tak by wyglądało to nawet-nawet). Mam nadzieję, że nie ma tu dużo do tłumaczenia...

Wspomniana wcześniej komunikacja Flyoutu z ciałem gadgetu odbywa się przy okazji usuwania wpisów z listy monitorowanych. Po kliknięciu ikonki minusika obok skróconego tytułu uruchamiana jest funkcja, która ukrywa element na liście, odpala funkcję rotate() z ciała gadgetu i w końcu zamyka sam flyout. Proste...

Rotate

Rotate to metoda, która odpalana jest przez funkcje setInterval, dzięki czemu możemy odświeżać kontent ciałą gadgetu bez jego całkowitego przeładowywania oraz możemy respektować czas zdefiniowany przez użytkownika.

function rotate() { var alarm = false; $("#comments").empty(); var now = new Date(); $("#last_update").html(now.toLocaleString()); cfg.loadFile(); if(cfg.refresh == "") { cfg.createFile(); cfg.loadFile(); } for(i in cfg.urls) { dpsidebar.getPage(cfg.urls[ i ].url); commentObj = dpsidebar.getCommentObject(cfg.urls[ i ].url); dpsidebar.putComment(commentObj, cfg.show_avatars); comments[commentObj.comment_id] = commentObj; if(!alarm) { if(commentObj.comment_id > cfg.urls[ i ].last_comment) { alarm = true; } } cfg.urls[ i ].last_comment = commentObj.comment_id; cfg.urls[ i ].title = commentObj.title; dpsidebar.clear(); } cfg.saveFile(); if(alarm) { var oBackground = document.getElementById("imgBackground"); oBackground.src = "url(img/background_n.png)"; } else { var oBackground = document.getElementById("imgBackground"); oBackground.src = "url(img/background.png)"; } $("body").height($("#wrapper").height()+"px"); }

Funkcja ta także weryfikuje, czy komentarz, który właśnie wyświetla nie jest nowy i nie trzeba odpalić informacji (wymaganie biznesowe związane z informacjami o nowym komentarzu).

Realizacja

Mając mnóstwo teorii/praktyki (w zasadzie nie wiem jak to określić...) za sobą czas wrócić do teorii tworzenia aplikacji. Przypomnę, że skończyliśmy w zasadzie na tworzeniu makiet. Po ich utworzeniu zespoły tworzące CSS, JS, HTML (najczęściej to jeden zespół) oraz część backendową (czy to będzie PHP, czy inny język) mogą przystąpić do kodowania. Zespół testerów posiadając informacje o wymaganiach biznesowych może zacząć tworzyć przypadki testowe, a nawet (jeśli jest to w ich kompetencjach) testy jednostkowe przy ścisłej współpracy z zespołami deweloperskimi. W sytuacji idealnej (więc w zasadzie niemożliwej) okaże się, że zespół testerów, który przetestował wersję alfa aplikacji nie zgłosił żadnych błędów, wówczas wersja beta powinna trafić do biznesu celem jej akceptacji. Wersja beta powinna być uruchomiona na środowisku odwzorowującym rzeczywiste środowisko na jakim ostatecznie działać będzie aplikacja. Idąc dalej ścieżką sytuacji idealnych biznes nie zgłosi poprawek i wersja trafi na produkcję.

W rzeczywistości najczęściej jest jednak tak, że biznes zastrzeżenia ma do wszystkiego, od zaakceptowanych pierwotnie makiet, po realizację kodu.

Linkownia

Developing a Gadgets (MSDN)JQueryDPSidebar zipowany Tak tylko, jakby ktoś chciał sobie coś poprawić.DPSidebar gotowy do instalacji

PostScriptum

Być może po skończeniu konkursu z diodą redakcja pozwoli mi opisać jak należałoby zmienić dpsidebar, by monitorował świecenie diody? 

windows programowanie

Komentarze

0 nowych
underface   14 #1 19.09.2012 15:29

czas odświeżania jest określany w sekundach czy minutach?;p

pysiu   13 #2 21.09.2012 10:19

nie wiem co jest grane ale nic nie pokazuje ten gadżet :(

pysiu   13 #3 21.09.2012 10:19

aha windows 7 64 bitowy :)

tfl   8 #4 21.09.2012 10:39

@pysiu

A dodałes jakis adres do monitorowania? Bo wersja bitowa systemu nie ma tu znaczenia...

djfoxer   18 #5 21.09.2012 14:18

Całkiem ciekawe :) Z chęcią przetestuje :)
(planuje coś podobnego, tylko jako wtyczkę do Chroma)

Autor edytował komentarz.
pysiu   13 #6 21.09.2012 20:53

wpisałem adres ale dalej nie mam tak jak na screenie

tfl   8 #7 21.09.2012 21:07

@pysiu,

mozesz mi podeslac plik %appdata%\local\microsoft\windows sidebar\gadgets\dpsidebar.gadget\cfg\settings.ini na conish [maupa] o2 dot pl ?

DjLeo MODERATOR BLOGA  18 #8 22.09.2012 13:06

Bardzo fajny gadżet mam nadzieje, że będziesz nad nim pracował i go rozwijał. Bo jest jeszcze trochę do zrobienia. Ale jeżeli Tak to z miłą chęcią będę jego wiernym użytkownikiem :)

DjLeo MODERATOR BLOGA  18 #9 22.09.2012 15:16

Po niedługim czasie używania przestała działać lista linków (przycisk wyświetlający listę przestał działać). :(

underface   14 #10 22.09.2012 17:34

u siebie też zauważyłem, że komentarze przestały się odświeżać - mimo, że nowe na blogu już zostały zamieszczone

tfl   8 #11 22.09.2012 18:51

@DjLeo

Problem byc moze zwiazany jest z dodaniem linka z # na koncu. Poprawie.

@underface

rozumiem, ze gadget sie juz odswiezyl?

wkrotce dodam wersje z logowaniem, ktora uzywalem przed wrzuceniem trzeciej czesci... musze tylko pogrzebac za nia :)

DjLeo MODERATOR BLOGA  18 #12 22.09.2012 18:52

Jak na razie Page Monitor na Chrome jest niezastąpiony. Tylko jego wadą jest to, iż trzeba dla każdego linku zaznaczyć divy aby nie sprawdzał całej strony tylko komentarze. Marzę o tym aby redakcja wprowadziła a właściwie zmieniła tylko jeden element na stronie aby się za każdym odświeżeniem nie zmieniała treść. Czyli avatary użytkowników i "Ostatnia wizyta" - to mogło by być w profilu użytkownika. Wtedy zmiana dotyczyła by wyłącznie komentarzy.

DjLeo MODERATOR BLOGA  18 #13 22.09.2012 18:53

@tfl

Na obecną chwile nie mogę wyświetlić listy linków. Przycisk nie działa. No i nie sprawdza linków.
Wcześniej ten przycisk z młoteczkiem wyświetlał listę teraz nie działa.

Autor edytował komentarz.
DjLeo MODERATOR BLOGA  18 #14 22.09.2012 18:58

Po jakimś czasie przestaje działać wyświetlanie podglądu po kliknięciu na 3 kropki. I często ucina się dolna część okna tak, że nie widać pola na link. Uważam, że ten gadżet jest świetny i chętnie go będę używać ale trzeba naprawić parę rzeczy. Poza tym mam kilka pomysłów na dodatkowe opcje :) i chętnie Ci je mogę przedstawić na GG.

underface   14 #15 23.09.2012 00:18

@tfl tak usuwałem na 5 min po tym czasie czas ostatniej aktualizacji się zmieścił (zmieniał) ale po kilku refreshach zmiany (nowe komentarze) przestały się pojawiać

tfl   8 #16 23.09.2012 07:45

ok, mam te wersje z logowaniem:

http://s000.tinyupload.com/?file_id=36336773293065897702

Poprawilem tez blad przy podawaniu linka z #komentarze na koncu oraz dodalem mozliwosc scrollowania, gdy wysokosc body przekracza 600px

po instalacji gadgetu w folderze c:\users\username\local\microsoft\windows sidebar\gadgets\dpsidebar.gadget\cfg\ znajduje sie plik dpsidebar.log, ktory loguje wiekszosc akcji. zeby wylaczyc logowanie w pliku c:\users\username\local\microsoft\windows sidebar\gadgets\dpsidebar.gadget\js\logger.js nalezy zmienna log zmienic z true na false i przeladowac gadget

Autor edytował komentarz.
underface   14 #17 23.09.2012 16:53

"To nie jest prawidłowy plik gadżetu" taki monit mi się wyświetla przy próbie instalacji

underface   14 #19 23.09.2012 19:19

ten nowy działa

TusiaX   1 #20 23.09.2012 20:43

bedziesz to rozwijać?

tfl   8 #21 23.09.2012 20:53

Jesli ktos wskaze interesujace funkcje o ktore warto rozwijac to chetnie dopisze


@DjLeo - nie uzywam gg. zapraszam na maila (podany wyzej)

DjLeo MODERATOR BLOGA  18 #22 26.09.2012 21:46

tfl kilka spostrzeżeń i sugestii:

- okienko z dodawaniem linków powinno być cały czas widoczne a nie zwijać się razem ze scrollem również info o aktualizacji (choć to mniej istotne)
- przy kilku artykułach nie wiadomo w którym pojawił się nowy wpis dobrze by było aby na czerwono podświetlał się wyłacznie ten który się zmienił lub co kolwiek co będzie dawać znać, że to chodzi o konkretny artykuł.
- pod tematem artykułu jest login autora ciężko jest trafić tak aby trafić w tytuł a nie w autora wpisu
- za duży wstęp do artykułu przy większej ilości dodanych linków robi się choas
- temat mógłby być w 2 linijkach i wtedy 3 kropki (...) było by czytelniej
- jak dla mnie można by było opcjonalnie zrezygnować ze wstępów.
- wychodzę zbyt daleko w przyszłość ale fajnie by było mieć możliwość zmiany kolejności artykułów :)

Oto moje propozycje :)

Autor edytował komentarz.
webnull   9 #23 26.09.2012 22:00

Drobna uwaga - dlaczego plik "Settings.ini" nie wygląda na plik w formacie ini? Jak dla mnie to jest chyba jakiś json ale mogę się mylić.

webnull   9 #24 26.09.2012 22:15

Może rozważyłbyś umieszczenie kodu w jakimś systemie kontroli wersji? GIT, SVN, Mercurial, Bazaar?

tfl   8 #25 26.09.2012 22:40

@DjLeo

No i to jest konkret. Posiedze w czasie wolnym i poprawie

@webnull

settings.ini wyglada tak, a nie inaczej, bo nie uwazam, zeby uzytkownik mial potrzebe tam zagladac. to, chyba o tym pisalem, alternatywa dla bazy danych, ktora mi sie nie chcialo implementowac (abstrahujac od tego, ze nie do konca widze potrzebe).
a kod lezy na moim prywatnym svn :)

i w ogole...

to nie ma byc aplikacja, ktora konkurowac ma z Twoja lub z jakakolwiek. to raczej proba uswiadomienia jak proste jest stworzenie tego typu rzeczy. no bo powiedzmy sobie to otwarcie - magii w tym nie ma, a dziala.