Difference between revisions of "Wyszukiwanie obiektów w drzewie"

From MorphOS Library

(Polish translation started.)
 
(Translation finished.)
 
Line 4: Line 4:
  
  
After the complete object tree is created, there is no direct access to any object except the main ''Application'' object. A way to access other objects is needed. There are a few ways to do this:
+
Po stworzeniu kompletnego drzewa obiektów, nie ma bezpośredniego dostępu do żadnego z nich, oprócz obiektu głównego, klasy ''Application''. Jakiś dostęp jednak jest potrzebny, można go uzyskać na trzy sposoby:
* Storing pointers to objects in global variables. This is the simplest way and may work well in simple projects. The disadvantage is it breaks object oriented design principles (like data encapsulation) and creates a mess when the number of global variables reaches 50, 100 or more.  
+
* Wskaźniki do obiektów jako zmienne globalne. To najprostszy sposób, może się sprawdzać w małych projektach. Jego wadą jest naruszanie zasad projektowania obiektowego (np. zasady enkapsulacji danych) i bałagan jaki się tworzy gdy liczba zmiennych globalnych osiąga 50, 100 i więcej.
* Store pointers in fields of some subclass instance data (for example the ''Application'' instance). A good idea, but a bit tedious to implement. An object's instance data area does not exist until the object is fully created and the ''Application'' object is created as the last one. Then pointers to subobjects have to be stored in some temporary variables. This technique also requires that a parent object of the cached one is an instance of a custom (subclassed) class and the parent creates its subobjects inside the constructor, which is not always true.
+
* Przechowywanie wskaźników do obiektów w polach obszaru danych jakiegoś obiektu (na przykład obiektu aplikacji). To dobry pomysł, ale problematyczny w implementacji. Obszar danych obiektu istnieje dopiero po jego stworzeniu (dokładniej - po wykonaniu konstruktora w klasie ''rootclass''), a obiekt aplikacji jest tworzony jako ostatni. Wskaźniki do obiektów potomnych musiałyby być przechowywane w jakichś zmiennych tymczasowych. Ta technika zakłada również, że obiekt nadrzędny wobec tego, do którego potrzebny jest dostęp, jest obiektem jakiejś klasy niestandardowej (z przeciążonym konstruktorem). Oprócz tego zakłada, że obiekt nadrzędny tworzy nasz poszukiwany w tymże konstruktorze, co nie zawsze musi być prawdą.
* Use the ''MUIA_UserData'' attribute and the ''MUIM_FindUData()'' method to find objects dynamically. This is the best solution when objects are accessed rarely (for example once, just to set notifications). For frequently accessed objects (let's say several times a second) it may be combined with caching objects' pointers in an instance data of some subclassed object.
+
* Użycie atrybutu ''MUIA_UserData'' i metody ''MUIM_FindUData()'' w celu dynamicznego wyszukiwania obiektów. To najlepsze rozwiązanie, gdy dostęp do obiektów potrzebny jest nie za często (na przkład tylko raz, w celu ustawienia [[Programowanie sterowane zdarzeniami, notyfikacje#Notyfikacje w MUI|notyfikacji]]). Jeżeli dostęp zachodzi często (powiedzmy kilka razy na sekundę i częściej) można tę technikę połączyć z przechowywaniem wskaźników w obiekcie nadrzędnym.
The last approach works as follows: every object to be searched has the ''MUIA_UserData'' attribute set to some predefined unique value. Then at any time the object may be found by this value using the ''MUIM_FindUData()'' method on a direct or indirect parent object, for example on the master ''Application'' object.
+
Wyszukiwanie dynamiczne działa następująco: każdy obiekt, jaki będzie później wyszukiwany, ma atrybut ''MUIA_UserData'' ustawiony na określoną, unikalną wartość. Następnie w dowolnym momencie można uzyskać wskaźnik do tego obiektu wywołując metodę ''MUIM_FindUData()'' na jego obiekcie (bezpośrednio lub pośrednio) nadrzędnym, na przykład na obiekcie aplikacji, który jest nadrzędny dla wszystkich innych.
  
  #define OBJ_SOME_BUTTON 36
+
  #define OBJ_JAKIS_PRZYCISK 36
 
   
 
   
  /* Somewhere in the initial tags for the button */
+
  /* Gdzieś w wartościach początkowych dla atrybutów obiektu */
  MUIA_UserData, OBJ_SOME_BUTTON,
+
  MUIA_UserData, OBJ_JAKIS_PRZYCISK,
 
  /* ... */
 
  /* ... */
 
   
 
   
  /* Let's get the pointer to the button now */
+
  /* Chcemy uzyskać wskaźnik do obiektu */
 
   
 
   
  Object *some_button;
+
  Object *jakis_przycisk;
 
   
 
   
  some_button = (Object*)DoMethod(App, MUIM_FindUData, OBJ_SOME_BUTTON);
+
  jakis_przycisk = (Object*)DoMethod(App, MUIM_FindUData, OBJ_JAKIS_PRZYCISK);
  
This operation is so common that it is usually encapsulated in a macro:
+
Ponieważ to bardzo często wykonywana operacja, wygodnie jest opakować ją w makro:
  
 
  #define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)
 
  #define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)
 
   
 
   
  some_button = findobj(OBJ_SOME_BUTTON, App);
+
  jakis_przycisk = findobj(OBJ_JAKIS_PRZYCISK, App);
  
The macro may of course be used directly in other functions, like in this example changing the button label:
+
Makro można oczywiście bezpośrednio wywoływać w innych funkcjach, na przykład przy zmianie atrybutów, albo w notyfikacjach. Oto przykład zmieniający tekst przycisku:
  
  set(findobj(OBJ_SOME_BUTTON, App), MUIA_Text_Contents, "Press Me");
+
  set(findobj(OBJ_JAKIS_PRZYCISK, App), MUIA_Text_Contents, "Kliknij");
  
Note that the ''findobj()'' macro is not defined in the system MUI headers, so it should be defined in the application code.
+
Trzeba zauważyć, że makro ''findobj()'' nie jest zdefiniowane w systemowych plikach nagłówkowych MUI, trzeba je zdefiniować samodzielnie w kodzie programu.

Latest revision as of 14:54, 29 January 2011

Grzegorz Kraszewski


Ten artykuł w innych językach: angielski


Po stworzeniu kompletnego drzewa obiektów, nie ma bezpośredniego dostępu do żadnego z nich, oprócz obiektu głównego, klasy Application. Jakiś dostęp jednak jest potrzebny, można go uzyskać na trzy sposoby:

  • Wskaźniki do obiektów jako zmienne globalne. To najprostszy sposób, może się sprawdzać w małych projektach. Jego wadą jest naruszanie zasad projektowania obiektowego (np. zasady enkapsulacji danych) i bałagan jaki się tworzy gdy liczba zmiennych globalnych osiąga 50, 100 i więcej.
  • Przechowywanie wskaźników do obiektów w polach obszaru danych jakiegoś obiektu (na przykład obiektu aplikacji). To dobry pomysł, ale problematyczny w implementacji. Obszar danych obiektu istnieje dopiero po jego stworzeniu (dokładniej - po wykonaniu konstruktora w klasie rootclass), a obiekt aplikacji jest tworzony jako ostatni. Wskaźniki do obiektów potomnych musiałyby być przechowywane w jakichś zmiennych tymczasowych. Ta technika zakłada również, że obiekt nadrzędny wobec tego, do którego potrzebny jest dostęp, jest obiektem jakiejś klasy niestandardowej (z przeciążonym konstruktorem). Oprócz tego zakłada, że obiekt nadrzędny tworzy nasz poszukiwany w tymże konstruktorze, co nie zawsze musi być prawdą.
  • Użycie atrybutu MUIA_UserData i metody MUIM_FindUData() w celu dynamicznego wyszukiwania obiektów. To najlepsze rozwiązanie, gdy dostęp do obiektów potrzebny jest nie za często (na przkład tylko raz, w celu ustawienia notyfikacji). Jeżeli dostęp zachodzi często (powiedzmy kilka razy na sekundę i częściej) można tę technikę połączyć z przechowywaniem wskaźników w obiekcie nadrzędnym.

Wyszukiwanie dynamiczne działa następująco: każdy obiekt, jaki będzie później wyszukiwany, ma atrybut MUIA_UserData ustawiony na określoną, unikalną wartość. Następnie w dowolnym momencie można uzyskać wskaźnik do tego obiektu wywołując metodę MUIM_FindUData() na jego obiekcie (bezpośrednio lub pośrednio) nadrzędnym, na przykład na obiekcie aplikacji, który jest nadrzędny dla wszystkich innych.

#define OBJ_JAKIS_PRZYCISK 36

/* Gdzieś w wartościach początkowych dla atrybutów obiektu */
MUIA_UserData, OBJ_JAKIS_PRZYCISK,
/* ... */

/* Chcemy uzyskać wskaźnik do obiektu */

Object *jakis_przycisk;

jakis_przycisk = (Object*)DoMethod(App, MUIM_FindUData, OBJ_JAKIS_PRZYCISK);

Ponieważ to bardzo często wykonywana operacja, wygodnie jest opakować ją w makro:

#define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)

jakis_przycisk = findobj(OBJ_JAKIS_PRZYCISK, App);

Makro można oczywiście bezpośrednio wywoływać w innych funkcjach, na przykład przy zmianie atrybutów, albo w notyfikacjach. Oto przykład zmieniający tekst przycisku:

set(findobj(OBJ_JAKIS_PRZYCISK, App), MUIA_Text_Contents, "Kliknij");

Trzeba zauważyć, że makro findobj() nie jest zdefiniowane w systemowych plikach nagłówkowych MUI, trzeba je zdefiniować samodzielnie w kodzie programu.