Composite Pattern: Design Frage



  • Hallo,

    ich habe ein Composite Pattern für eine Art GUI System. In Pseudocode in etwa so:

    class GUIElement {
       GUIElement* mParent;
    
       uint2  mTopLeft;
       uint   mWidth, Height;
    
    public:
       virtual void onParentDimensionsChanged();
    };
    
    class GUIPanel : public GUIElement {
       vector<GUIElement*>  mElements;
    public:
       void addElement(GUIElement* element);
    
        virtual void onParentDimensionsChanged() {
           // Eigene Größe anpassen und onParentDimensionsChanged() aller Kinder (mElements) aufrufen
        }
    };
    
    class GUILabel: public GUIElement {
    public:
    
        virtual void onParentDimensionsChanged() {
           // Eigene Größe anpassen
        }
    };
    

    Jedes GUIElement hat einen Parent und wenn sich die Dimensionen des Parent geändert haben, wird onParentDimensionsChanged() aufgerufen. Sagen wir z.B. ich habe ein GUIPanel mit 2 GUILabels drinnen und die Dimensionen des GUIPanels ändern sich, dann wird onParentDimensionsChanged() für die beiden GUILabels im GUIPanel aufgerufen.
    Ich habe eine Klasse Framework, die einen Zeiger auf einen GUIPanels besitzt. Dieses GUIPanel ist quasi das Root Element der Hierarchie. Das Problem: Diesess Root GUIPanel hat natürlich kein Parent (Parent = NULL).

    Sagen wir das Fenster wird resized. Jetz wird Framework::onResize(width, height) aufgerufen und jetzt muss das Root GUIPanel benachrichtigt werden. Das Problem ist nur, in onParentDimensionsChanged() ist für dieses GUIPanel ja mParent NULL und ich weiß nicht, auf was ich resizen soll.
    Ich könnte in Framework::onResize() auch per Hand die Member setzen, quasi so:

    Framework::onResize(width, height) {
       mRootGUIPanel->mWidth = width;
       mRootGUIPanel->mHeight = height;
    
       // Jetzt hier über alle Kinder von mRootGUIPanel iterieren und onParentDimensionsChanged() aufrufen.
       // Geht, aber ist unschön, weil ich auf private Member von GUIPanel zugreife
    
    }
    

    Wie könnte ich das besser lösen?



  • NVI-Idiom:

    class GUIElement
    {
        uint width, height;
    
        virtual void do_resize(uint x, uint y) = 0;
    
    public:
        void resize(uint x, uint y) // nicht virtuell
        {
            width = x;
            height = y;
    
            do_resize(x, y);
        }
    };
    
    class GUIPanel
    {
        virtual void do_resize(uint x, uint y)
        {
            do_your_own_stuff(x, y);
        }
    };
    

Log in to reply