Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:miw:miw08_ruleruntimeo:mvceditor [2008/05/31 22:35] miw |
pl:miw:miw08_ruleruntimeo:mvceditor [2008/06/01 00:13] miw |
====== Edytor tekstu oparty o MVC ====== | |
| |
==== Cel ==== | |
| |
W ramach realizacji tego przykładu konieczne było takie zmodyfikowanie gotowej aplikacji napisanej w J2SE i będącej bardzo prostą, tutorialową demonstracją wykorzystania modelu MVC, aby zastąpić implementacje Modelu z obiektów Javy na Logtalk oraz aby zmodyfikować w jak najmniejszym stopniu pozostałą część aplikacji. | |
| |
==== Stan wejściowy ==== | |
Wejściowa aplikacja jest prostym edytorem tekstu zawierącym, jak widać na poniższym diagramie : | |
| |
{{:pl:miw:miw08_ruleruntimeo:figure2.gif|:pl:miw:miw08_ruleruntimeo:figure2.gif}} | |
| |
**Widok (View)** - a dokładnie dwa widoki : | |
- Wyświetlający wprowadzony tekst, klasa DisplayViewPanel | |
- Umożliwiający wprowadzanie tekstu oraz modyfikowanie jego właściwości takich jak czcionka, rozmiar czcionki, przeźroczystość tekstu, obrót tekstu wokół osi itp, zaimplementowany jako klasa PropertiesViewPanel | |
| |
**Model** - służy do przechowywania wprowadzonego tekstu oraz wartości tych właściwości. Klasy modelu w projekcie to : | |
- TextElementModel - przechowuje stan tekstu wyświetlanego w dokumencie, takie jak wartość tekstu, czcionka itp | |
- DocumentModel - zawiera stan całego dokumentu tekstowego, czyli nazwę, wysokość, szerokość | |
| |
| |
**Kontroler (Controller)** - służy do przekazywania do Modelu odpowiednich zmian właściwości na podstawie komunikatów nadsyłanych z Widoku, czyli generalnie odpowiada za mapowanie zmian dokonanych przez użytkownika na odpowiednie zmiany w Modelu. Kontroler został zaimplementowany w klasie DefaultController. | |
| |
Będąc bardziej szczegółowym projekt ten używa lekko zmodyfikowanej wersji wzorca MVC, w której zmiany stanu Modelu nie są bezpośrednio propagowane do Widoku, ale są przekazywane poprzez Kontroler. Czyli projekt używa poniższej architektury : | |
{{:pl:miw:miw08_ruleruntimeo:figure4.gif|:pl:miw:miw08_ruleruntimeo:figure4.gif}} | |
| |
Czyli zmiany wykonane przez użytkownika w jednym z widoków, powodują wywołanie odpowiedniej metody w Kontrolerze. Kontroler ma dostęp do odpowiedniego modelu i jest w stanie odpowiednio zmodyfikować stan Modelu. Model wykrywając zmianę jednej z swoich właściwości, wywołuje odpowiednie zdarzenie zmiany stanu. Zdarzenie to jest obsługiwane przez Kontrolera, który w właściwy sposób modyfikuje Widok. Jak widać główną różnicą jest fakt pośredniczenia Kontrolera w każdej komunikacji pomiędzy Widokiem a Modelem co okazało się bardzo korzystne w trakcie przechodzenia na implementacje Modelu w Logtalk'u. | |
| |
| |
Dokładny opis oraz źródła wejściowej aplikacji można znaleźć w [[pl:miw:miw08_ruleruntimeo#materialy|Materiałach]]. | |
| |
==== Dokonane modyfikacje ==== | |
Jak widać architektura tego projektu sprzyjała procesowi implementacji części klas w Logtalk'u ze względu na silne odseparowanie modułów, oraz posługiwanie się referencjami do klas abstrakcyjnych takich jak AbstractController, AbstractView czy AbstractModel co bardzo ułatwiało podmianę docelowej implementacji tych obiektów. | |
| |
Klasy Modelu tak naprawdę służą tylko do przechowywania wartości kilku właściwości i cała ich implementacja polega na polach klasy oraz getter'ach i setter'ach. Jesteśmy zatem w stanie bez większego problemu wymienić klasy modelu napisane w Javie na obiekty Logtalk, na zasadzie 1:1. Czyli tworzymy: | |
- **documentModel** w pliku documentModel.lgt | |
- **textElementModel** w pliku textElementModel.lgt | |
| |
| |
Aby powtórzyć tą samą funkcjonalność w Logtalku wystarczy zatem napisać prostą Kategorie, którą potem zaimportujemy do każdego z obiektów Modelu : | |
| |
<code prolog> | |
| |
:- public(set_property/2). | |
:- mode(set_property(+nonvar, +nonvar), one). | |
| |
:- public(get_property/2). | |
:- mode(get_property(?nonvar, ?nonvar), zero_or_more). | |
| |
:- private(property_/2). | |
:- mode(property_(?nonvar, ?nonvar), zero_or_more). | |
:- dynamic(property_/2). | |
| |
set_property(Property, Value):- | |
write('Property test : ' + OldValue),nl, | |
::retractall(property_(Property, OldValue)), | |
| |
::assertz(property_(Property, Value)), | |
::firePropertyChange(Property, OldValue, Value). | |
| |
get_property(Property, Value):- | |
::property_(Property, Value), | |
write(Value). | |
| |
| |
:- end_category. | |
| |
</code> | |
| |
Tak dzięki tym predykatom jesteśmy w stanie dokonywać dynamiczego zapisu wartości odpowiednich właściwości Modelu do Bazy wiedzy Prologa. Kod obiektu documentModel wygląda następująco : | |
| |
<code prolog> | |
:-object(documentModel, imports(properties)). | |
:-public(firePropertyChange/3). | |
| |
firePropertyChange(PropertyName, OldValue, NewValue):- | |
write('Document: PropertyName ' + PropertyName),nl, | |
write('Document: NewValue ' + NewValue),nl | |
. | |
:-end_object. | |
</code> | |
| |
Tak naprawdę w tym przypadku kod modelu ograniczy się do importowania tej kategorii, jeden predykat służy tylko do wypisania na konsole zmiany stanu modelu. | |
Niestety jako, że problematyczne okazało się wywoływanie zdarzeń Javowych bezpośrednio z kodu Prologa, niestety wymagałoby to przechowania referencji do Obiektu Kontrolera wewnątrz obiektu Logtalk, co niestety okazało się niemożliwe przy użyciu JPL, który dość dobrze radzi sobie z przechowywaniem referencji do obiektów Javy tworzonych przy użyciu JPL, natomiast niekoniecznie takich istniejących już wcześniej. | |
Konieczne było zastosowanie pewnych obejść żeby zachować istniejącą architekturę aplikacji, ale generlanie rzecz biorąc próba realizacji takiej podmiany udała się. | |
| |
Widać, że podmiana klas modelu na obiekty Logtalku może się odbyć tylko poprzez modyfikacje Kontrolera (Controller) na taki, który wykorzystując JPL będzie komunikował się z Logtalk'iem i przekazywał komunikaty do Widoku (View). Zatem klasy modelu napisane w Javie de facto mogą zostać podmienione przez obiekty Logtalk na zasadzie 1:1. | |
| |
| |
==== Docelowe rozwiązanie ==== | |
| |