Zbyt dużo pomysłów na wpisy, zbyt dużo treści do opublikowania. Ale to Was nie powinno martwić 🙂 Gorzej sprawa wygląda z czasem autora, ale powoli, powoli jakoś dam radę.

Dzisiaj mowa będzie o Google Web Toolkit i problemie osadzania obrazka na stronie. Ktoś powie „to żaden problem – ustalając szerokość lub wysokość w arkuszu stylów, przeglądarka sama dostosuje nam obrazek, a dokładniej przeskaluje nam go”. Ja odpowiem – i tak, i nie. W czym tkwi problem? 

Głównym założeniem, które ukazuje nam ten problem jest niemożność przewidzenia rozmiaru obrazka. Ale dlaczego „i nie”? Otóż tutaj należy spojrzeć w kierunku bardzo nielubianych starszych wersji przeglądarek Internet Explorer. To jest zmora programistów, która bądź co bądź powoli zostaje odstawiana do lamusa. Zbyt dużo czasu minęło od nieszczęsnych przeglądarek IE, zbyt mocno rozwinęły się technologie (HTML5, CSS3) aby teraz przywiązywać wagę do narzędzi sprzed ~10 lat. Ale wszystko zależy od wymagań pozafunkcjonalnych tworzonej aplikacji internetowej.

Jeśli nadal myślisz „żadna to przyczyna” wyobraź sobie, że nie chcesz publikować tego obrazka, o którym mowa wcześniej. Wymaganiem, jest pobranie rozmiaru (np. do algorytmu) – szerokości/wysokości i dalsze operacje na nim. I w tym momencie zaczynają się schody. Prosta metoda (jawna) polega na „opublikowaniu” na stronie obrazka w bloku ukrytym i odczytanie jego rozmiaru. Nie można zapomnieć o usunięciu węzła ze struktury strony.

Ale po co sobie komplikować życie, kiedy ktoś kiedyś stworzył bibliotekę rozwiązującą ten problem. Przyjrzyjmy się przykładowi:

ImagePreloader.load(data.getPreview(), new ImageLoadHandler() {

	@Override
	public void imageLoaded(ImageLoadEvent event) {
		if(!event.isLoadFailed()) {
			Image image = new Image(UriUtils.fromTrustedString(data.getPreview()));
			image.setHeight(HEIGHT + "px");
			if(GXT.isIE()) {
				long width = Math.round(((double)HEIGHT / (double)event.getDimensions().getHeight()) * event.getDimensions().getWidth());
				image.setWidth(width + "px");
			}
			panel.add(image);

			double ratio = (double)event.getDimensions().getWidth() / (double)event.getDimensions().getHeight();
			if(!data.getIsOwn()) {
				panel.add(getMark(Markers.EDIT, ratio));
			}
			panel.add(getMark(Markers.REMOVE, ratio));
			if(data.getIsActive()) {
				panel.setStyleName("activityPanel", true);
			}
		}
		else {
			Image image = new Image(icons.noPictureAvailable());
			image.setHeight(HEIGHT + "px");
			if(GXT.isIE()) {
				image.setWidth(HEIGHT + "px");
			}
			panel.add(image);
		}
	}
});

„Skromny” przykładzik pokazuje nam zadanie, jakie postawiono w tym przypadku funkcji load. Mamy tutaj ustaloną wysokość, jaką musi mieć obrazek (linia 7). W związku z tym zadaniem było wyznaczenie szerokości, aby przeskalować „statycznie” zdjęcie. Przez to, że przeładowaliśmy zdjęcie w bibliotece mamy dostęp do jego rozmiarów, co już powoduje, że samo wyliczenie staje się prościutkie – podświetlona linia.

W przypadku błędu ładowania zdjęcia, wyświetlamy domyślny obrazek informujący o tym … i po kłopocie.
Gdy nie potrzebujemy dodawać zdjęcia do RootPanelu, możemy wykorzystać same dane obrazka do dalszych obliczeń.

Aby dodać bibliotekę należy dołączyć ją do build path’a projektu GWT i dodać wpis do *.gwt.xml:

<inherits name="com.reveregroup.gwt.imagepreloader.ImagePreloader" />

Biblioteka znajduje się pod adresem: https://code.google.com/p/gwt-image-loader/
Znajdziecie tam również przykłady zastosowania.

PS. Nie zalecane jest stosowanie biblioteka w przypadku obrazów bardzo dużych rozmiarów (>kilka MB) gdyż wskazany adresem obrazek musi zostać w całości ściągnięty, co generuje opóźnienia i niekiedy frustrację programisty, nie wspominając o użytkownikach aplikacji. Wówczas często korzystam z Webserwisu, który po stronie serwera PHP (tego samego, na którym znajduje się zdjęcie) w błyskawicznym tempie odczyta mi te dane i odeśle 🙂