Seite 6 von 6

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:08
von dot
Siehe oben. Irgendwelche Prüfungen oder dynamic_casts brauchst du da nirgendwo. Ein und das selbe Objekt kann verschiedenste Interfaces implementieren. In C++ kann diese Tatsache durch private Ableitungen sogar nach außen völlig transparent gemacht werden.

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:10
von BeRsErKeR
Und wie? Per Mehrfachvererbung?

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:11
von dot
BeRsErKeR hat geschrieben:Und wie? Per Mehrfachvererbung?
Exakt. Mehrfachvererbung ist hier ein sehr mächtiger Verbündeter.

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:16
von BeRsErKeR
Ich halte generell sehr wenig von Mehrfachvererbung und kam bislang glaub ich in über 13 Jahren nur ein einziges Mal in die Verlegenheit es zu benötigen. Aber naja es ist sicherlich auch ein Weg, allerdings nicht meiner.

Es löst allerdings nicht das Problem. Deine Knoten im Baum müssen ja dennoch vom selben Grundtyp sein, z.B. Component oder Widget. Selbst wenn ein Button da z.B. von KeyInputFoo und MouseInputFoo erbt, muss vorm Aufruf von MouseUp oder einer ähnlichen Methode ja erstmal klar sein, dass dieser Knoten auch davon erbt. Und das stell ich mir ohne dynamic_cast oder eine Art Flag doch recht knifflig vor.

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:37
von dot
Mit dem richtigen Design ergibt sich das alles vollkommen natürlich und von selbst. Nehmen wir als Beispiel ein einfaches Slider-Control:

Code: Alles auswählen

  class Slider : public virtual Control, private Visual, private WidgetBase, private Dragable
  {
  private:
    Slider(const Slider&);
    Slider& operator =(const Slider&);

    ...

    // Mouseinput, Defaultimplementierung kommt aus WidgetBase
    void mouseEnter(const float2& p);
    void mouseLeave(const float2& p);

    Dragable* beginDrag(Button button, const float2& p);

    // Drag&Drop
    void drag(const float2& p, const float2& dp);

    // Grafik
    void draw(ID3D11DeviceContext* context, Drawing::Context& drawing_context, const Theme& theme, const float2x3& transform = float2x3::identity()) const;

  public:
    Slider(...);
    ~Slider();

    // fürs Layoutsystem
    float2 position() const { return box.position(); }
    size2f size() const { return box.size(); }
    rectf resize(const Theme& theme, const rectf& avail);
    void arrange(const Theme& theme, const rectf& pos);

    // Hier setzt das Inputhandling an
    Widget* hitTest(const float2& p);

    void insert(LayoutContainer* layout);
    void insert(VisualContainer* visual);
  };
Nach außen ist der Slider einfach nur ein Control. Wenn der Slider nun in das GUI eingefügt wird, rufen die jeweiligen Container die beiden insert() Methoden auf, worauf der Slider sich einmal als Control im layout anmeldet und einmal als Visual im Renderingsystem. Ein Steuerelement, das keine visuelle Repräsentation hat (z.B. irgendein Layout-Container), würde sich z.B. einfach von vornherein gar nicht beim Renderingsystem eintragen und daher auch nie darum gebeten werden, sich zu zeichnen.
Wenn die Maus bewegt wird, dann kann das GUI über hitTest() checken, ob die Events an den Slider gehen sollen. Für den Fall, dass die Koordinaten den Knob des Slider treffen, gibt der Slider dort sein Widget-Interface zurück, über das dann die eigentliche Mausinteraktion (in dem Fall Drag&Drop des Knob) abläuft.
Verschiedene Dinge werden über jeweils verschiedene, schlanke Interfaces abgehandelt, was das ganze System extrem flexibel macht. Der Slider müsste die ganzen Interfaces nicht selbst implementieren, sondern könnte die Arbeit völlig transparent für das restliche System auch an andere Objekte delegieren (so könnte z.B. der Knob des Slider durch ein eigenes Objekt implementiert sein, das GUI-System kümmert das nicht). In diesem Fall bietet es sich eben an, die Interfaces direkt zu implementieren.
Nirgendwo werden hier irgendwelche dynamic_casts oder sonstige Abfragen benötigt.

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:44
von BeRsErKeR
Und wie teilst du einem Button mit, dass die Return-Taste gedrückt wurde oder einem Entry, dass eine Eingabe erfolgt ist?

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 02:47
von dot
Das Beispiel zeigt eben nur Mausinteraktion. Mit der Tastatur funktioniert das aber komplett analog dazu. Da gäbe es dann ein separates Interface, das Tastaturinput abhandelt und eben in einer entsprechenden Datenstruktur registriert wird. Tastaturinput funktioniert ja auch rein logisch anders als Mausinput. Hier wird man keine Baumstrukturen benötigen, denn es gibt zu jedem Zeitpunkt sowieso nur ein Objekt, das den Keyboard-Fokus haben kann...

EDIT: Man bräuchte nur dem Control-Interface eine setFocus() Methode zu geben, die eben ein Keyboard-Interface mit den entsprechenden keyDown() und keyUp() Methoden returned, oder 0, falls das Steuerelement keinen Keyboard-Input verarbeitet. Das GUI hält einfach einen Zeiger auf das Keyboard-Interface, das momentan den Fokus hat und fertig. Wenn der Benutzer irgendwo hin klickt, kann das GUI das dort befindliche Control fragen, ob es den Fokus haben will und wenn es von diesem Control ein Keyboard-Interface bekommt, dann wandert der Fokus dort hin, ansonsten bleibt er unverändert.

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 03:12
von dot
Bezüglich Flexibilität sei vielleicht noch angemerkt, dass dieses System von Haus aus mit beliebig vielen Mäusen und Tastaturen zurechtkommt, sodass die GUI z.B. auch von mehreren Benutzern gleichzeitig bedient werden kann. Lediglich das GUI-Objekt an der Wurzel muss natürlich alle Mäuse und Tastaturen kennen, da es dann eben mehr als einen Keyboard-Fokus gibt etc. Aber den Rest des Systems kümmert das nicht, sämtliche Controls würden in so einem Umfeld ohne die Änderung von auch nur einer einzigen Zeile Code völlig natürlich funktionieren. Der Input könnte überhaupt auch z.B. von einem anderen Computer übers Netzwerk kommen...
Mit so einem Event-System, wie von dir beschrieben, dürfte sich das als schwierig erweisen, denk ich.

Re: [C++] Speicherfreigabe bei statischem Singleton

Verfasst: 01.11.2011, 16:58
von BeRsErKeR
dot hat geschrieben:... Mit so einem Event-System, wie von dir beschrieben, dürfte sich das als schwierig erweisen, denk ich.
Nö wieso sollte das schwieriger sein? Deine Baumstruktur kann ich in meinem System auch nutzen und wer die Events generiert bzw. woher sie kommen ist den Controls völlig egal. Es ändert sich doch nur die Art der Übertragung und nicht die Quelle oder die Ziele. Die sind völlig unabhängig in beiden Systemen. Bei mir müsste das Wurzelobjekt jedoch nicht mal die Mäuse und Tastaturen kennen. Prinzipiell könnten Eingaben auch einfach irgendwo simuliert werden. Und man könnte theoretisch sogar problemlos Joysticks nutzen ohne da noch irgendwelche Interfaces zu entwerfen.

Ich sehe eigentlich keine Nachteile des Event-Systems gegenüber deinem System. Es sind halt zwei Varianten. Welche davon "besser" ist liegt im Auge des Betrachters bzw. hängt von der Umgebung beim Entwickeln ab. Ein Event-System ist beispielsweise mit kleinen Anpassungen auch unter C realisierbar.