Algierlib: GUI Bibliothek



  • Es ist nun so weit, das ich meine GUI Bibliothek für C++ hier publik mache. Ein paar Forum-Mitglieder kennen mein Projekt vom "Hören sagen", da es für jeden seit ca. 2 Jahren auf Tigris.org die Entwicklung verfolgbar ist.

    Worum geht es?
    1. Eine C++ Bibliothek die GUI Funktionen bereit stellt.
    2. Plattform unabhängiges C++-Interface.
    3. Bisher (leider) nur für MS-Windows implementiert.
    4. Nutzt unter Windows die nativen Controls (Widgets).
    5. Läuft auf GCC MinGW 4.3.0+ und MSVC 2003+.
    6. Umfangreiche Dokumentation.
    7. Name der Bibliothek: Algier GUI Library, kurz Algierlib.
    8. Open Source Lizenz: BSD-Style.

    Das erstmal als Stichworte.

    Heute ist die Version 0.4.0 erschienen und die Nummer zeigt eindeutig: es ist noch ein langer Weg bis zum Ziel! Denn nach der 0.9.0 muß nicht 1.0.0 erscheinen, es kann auch 0.10.0 weiter gehen.

    Ich habe folgende Prioritäten in den zwei Jahren gesetzt:

    1. Ein schönes C++ Design. Damit ist nicht gemeint, zwanghafter Meta-Template-Magic! Sondern alles pragmatisch, z.B. wird tr1::shared_ptr durchgängig genutzt, wo nötig. Die Bibliothek selbst kann zur Zeit noch nicht viel (im Vergleich zu den Mature-Libs). Qualität anstatt Quantität.
    2. MVC (Model View Controller) wird durchgängig genutzt.
    3. Eine Doku, mit der auch Anfänger was anfangen können. Wobei das gar nicht so einfach ist. Hier ist auf jeden Fall Feedback von GUI- und C++-Anfängern gefragt!
    4. Support von MinGW und MSVC.
    5. Unit- und Integrations-Tests.

    Wie sieht die Zukunft aus?
    Es ist ein Port auf X11-Systeme nötig, spricht X-Window. Somit UNIX-artige Systeme.

    Ich würde mich freuen, wenn viele Menschen diese Bibliothek ausprobieren würden. Zur Zeit bin ich der einzige Anwender, so das wahrscheinlich noch viele Fehler und Unstimmigkeiten vorhanden sind. Rückmeldungen sind sowohl von Anfängern, Fortgeschrittene und Profis gefragt. Falls jemand sogar aktiv mitarbeiten will (z.B. Patches, Doku etc.), kann das gerne tun. Für eine Person ist das alles nicht zu schaffen.

    Hier die Projektseite: http://algierlib.tigris.org
    Dort kann man die Distribution runter laden, die auch ein paar Beispiele als EXE-Dateien drin haben, aber natürlich auch die Doku, Libs und Sourcen.

    Schöne Grüße
    Artchi

    PS: Eine deutsche Einsteiger-Dokumentation ist in Arbeit.



  • Tip: setz den Link auf die Doku (http://www.kharchi.eu/algierlib/) ganz dick irgendwo auf die Homepage.
    Schonmal super dass es eine Doku gibt, die man sich ansehen kann ohne dass man irgendwas runterladen muss. Bringt allerdings nix, wenn man sie nicht findet. Und oft genug guck ich nicht in die "Documents & Files" Sektion, wenn ich nach einer Online-Doku suche.

    Ich halte das deswegen für wichtig, da die Online-Doku normalerweise das erste ist, was ich mir bei einer Library ansehe, die ich "evaluiere" (für welche Zwecke auch immer - seis nun privat oder beruflich). Einfach mal gucken wie das Ding so aufgebaut ist, ob ich mich mit dem Design anfreunden kann, ob vielleicht Dinge fehlen die ich unbedingt brauche etc. Und wenn ich die Doku dann nicht halbwegs schnell finde, suche ich meist nicht weiter, sondern streiche die Library meist gleich.

    BTW: wieso heisst das Projekt "algierlib", das .lib File aber "libalgier"? Ich persönlich würde beides gleich nennen.

    Nochwas: darf ich fragen, was der Grund dafür war, dass deine "Views" ihre "Models" per Referenz halten, und nicht per shared_ptr/weak_ptr? Ich gebe zu dass ich nicht wirklich wahnsinnig viel Erfahrung mit C++ GUI Code habe, aber es erscheint mir ... fragwürdig 🙂



  • hustbaer schrieb:

    Tip: setz den Link auf die Doku (http://www.kharchi.eu/algierlib/) ganz dick irgendwo auf die Homepage.
    Schonmal super dass es eine Doku gibt, die man sich ansehen kann ohne dass man irgendwas runterladen muss. Bringt allerdings nix, wenn man sie nicht findet. Und oft genug guck ich nicht in die "Documents & Files" Sektion, wenn ich nach einer Online-Doku suche.

    Ja, die Betriebsblindheit! 😉 Habe jetzt einen sogenannten Quick Link auf die Startseite gesetzt. Danke für den Hinweis.

    hustbaer schrieb:

    BTW: wieso heisst das Projekt "algierlib", das .lib File aber "libalgier"? Ich persönlich würde beides gleich nennen.

    Das .lib File heißt eigentlich algier.lib . Du meinst die gcc-Datei? Die heißt tatsächlich libalgier.a . Aber um ganz ehrlich zu sein, dachte ich, der gcc will das die Libs mit lib anfangen. Ich erstelle gcc-Libs aus zwei Gründen:
    1. um zu testen, ob alles auch mit gcc funktioniert.
    2. um den Usern den Build zu ersparen.

    Ich selber kenne mich mit gcc nur rudimentär aus. Arbeiten tu ich täglich mit MSVC. Aber eigentlich sollte die Lib einfach algier.lib bzw. algier.a heißen. Für das nächste Release werde ich die Dateinamen nochmal überdenken.

    hustbaer schrieb:

    Nochwas: darf ich fragen, was der Grund dafür war, dass deine "Views" ihre "Models" per Referenz halten, und nicht per shared_ptr/weak_ptr? Ich gebe zu dass ich nicht wirklich wahnsinnig viel Erfahrung mit C++ GUI Code habe, aber es erscheint mir ... fragwürdig 🙂

    Zum Verständnis: die Models sind Datenobjekte, die man (auch) ohne View-Objekte nutzen kann. D.h. Models stehen erstmal für sich alleine. Eine View selbst hat keine "Macht" über Models, es kennt sie nur.

    Ich hatte vorher tatsächlich die Model per weak_ptr referenziert (nicht shared_ptr!). Nur hat das leider einen Nachteil: der User wird gezwungen, die Models mit new anzulegen und in einen shared_ptr zu verwalten. Die Views sind ein sehr spezieller Anwendungsfall, da kann ich vom User verlangen, sie in shared_ptr zu verwalten.

    Die Models sind aber normalerweise sehr Abhängig von der Applikationslogik, wo sich Programmierer ungern reinreden lassen. Stell dir vor, jemand sagt dir, du mußt std::string-Objekte immer mit new anlegen. Dabei würde es ein lokales Objekt (Stack) auch tun. Und die Models sind auf gleicher Ebene wie das besagte std::string-Objekt. Einfach nur Daten. Die Model Klassen kennen übrigens die algierlib überhaupt nicht.

    Es gibt deshalb den Mechanismus, das ein Model sich selber beim Observer (View) abmeldet. Der Observer hat dafür die Methode subject_killed() . Dann weiß er wann das Model nicht mehr existiert. Es gibt dafür im Projekt auch Unit-Tests, da kann man sich das nochmal zum Verständnis anschauen. 🙂 Im Prinzip erfüllt ja das von mir genutzte Observer-Pattern in einem Abwasch den weak_ptr-Mechanismus mit. Mit dem weak_ptr wäre das eigentlich nur doppelt gemoppelt.

    Trotz allem bleibt aber dem User die Freiheit, die Model trotzdem mit new anzulegen. 🙂

    Das erstmal als Erklärung, warum ich das so umgesetzt habe.



  • OK, das mit dem Models verstehe ich.
    Ich hatte nicht gesehen dass es eine Funktion gibt, mit dem das Model sich von der View abmeldet.

    Aber nochwas: inwiefern ist eine Listbox bzw. eine Combo-Box eine View für ein "stringlist" Model?
    Ich nehme an die Listbox/Combo-Box bezieht die Auswahlliste aus dem Model. Zumindest sieht dein Programm so aus.

    Und das fände ich etwas komisch, denn das Datum das man mit einer Listbox/Combo-Box editieren kann, ist ja nicht die Liste der Möglichkeiten, sondern das ausgewählte Element (bzw. die ausgewählten Elemente).

    Oder habe ich da was falsch verstanden?



  • Die Views stellen erstmal nur dar, was in dem Model drin steht. Wenn du ein Element aus der Liste auswählst, berührt es das Model nicht. Die Auswahl/Selektion aus der Liste ist erstmal nur eine rein grafische Angelegenheit (View). Naiv gesagt: es wird nur die Darstellung der Zeile invertiert. 😉

    Natürlich interessiert das Programm aber auch die Selektion (Zeile 1? Zeile 2?). Und das kann man in der View abfragen, bzw. da bekommt man einen Event, der einen über eine Selektion informiert.

    Für die Zukunft sollte es aber ein Selektions-Model geben. Weil nämlich eine Umsortierung einer Liste sich nur in der View auswirken würde und soll. D.h. das Model (in dem Fall die Liste) würde man nicht umsortieren. Weil ich z.B. als Anwender in zwei Views zwei verschiedene Sortierungen wählen könnte. Aber das ist noch Zukunft.

    Konkret: Wenn du also eine Zeile editierst, editierst du nur einen Eintrag aus dem List-Model. Und dafür muß natürlich das Interface des Models mit dem der View-Forderung kompatibel sein. Dafür wäre dann die at()-Methode da bzw. eine dafür zuständige Methode, die das Ändern erlauben würde. 😉

    Die List-Views kann man zur Zeit nicht editieren. Die sind Read-Only. Für die Zukunft ist das aber geplant. Man kann das aktuell umgehen, in dem man eine zus. Textbox dem User anbietet. Fehlt halt noch sehr viel, bis v1.0.
    Beantwortet das in etwa deine Frage?

    Man muß beim MVC Pattern wirklich zwischen Daten und Darstellung unterscheiden. Ein Beispie, das ich demnächst noch einbauen werde für ein besseres Verständnis, ist folgendes:

    Im List-Model stehen die Strings: Kreis, Quadrat, Dreieck.
    Diese kann man sowohl als Text in einer listbox darstellen.
    Aber man kann auch eine 2D-View implementieren, die die Daten mit geometrischen Formen darstellt. Also echte Kreise, Quadrate und Dreiecke.



  • Hallo Artchi,

    das Design gefällt mir schon ganz gut, insbesondere die strikte Trennung zwischen GUI-Elementen und Daten.

    Einige Fragen habe ich aber zur Windows-Klasse: kann man einzelne Elemente auch wieder aus einem Fenster entfernen, da ich nur eine attach()-Funktion, aber keine detach()-Funktion gesehen habe? Und kann man über alle Elemente iterieren?

    Und zum Abschluß noch die Frage: soll auch irgendwann die Möglichkeit bestehen die Darstellung einzelner GUI-Elemente (Farbe, Farbverläufe, Hintergrundgrafiken etc.) anpassbar zu machen oder soll nur jeweils die native Darstellung benutzt werden können?



  • Th69 schrieb:

    Einige Fragen habe ich aber zur Windows-Klasse: kann man einzelne Elemente auch wieder aus einem Fenster entfernen, da ich nur eine attach()-Funktion, aber keine detach()-Funktion gesehen habe? Und kann man über alle Elemente iterieren?

    Entfernen geht leider noch nicht, da ich das noch nicht in Angriff genommen habe. Ich muß ehrlich gesagt auch erstmal in der MSDN nach schauen, wie man HWND-Objekte löscht. Das fehlt noch im Dtor.

    Aber danke für den Hinweis, habe mal Issues angelegt:
    http://algierlib.tigris.org/issues/show_bug.cgi?id=59
    http://algierlib.tigris.org/issues/show_bug.cgi?id=60

    Th69 schrieb:

    Und zum Abschluß noch die Frage: soll auch irgendwann die Möglichkeit bestehen die Darstellung einzelner GUI-Elemente (Farbe, Farbverläufe, Hintergrundgrafiken etc.) anpassbar zu machen oder soll nur jeweils die native Darstellung benutzt werden können?

    Die nativen Win32-Controls kann man so gar nicht ändern. Müsste man aufwändig mit nem Owner Draw lösen. Da kenne ich mich aber nicht mit aus.

    Ich kann mir aber vorstellen, das man später separate Klassen implementiert, die keine nativen Widgets nutzen (so wie es Gtk und Qt machen). So das man explizit als Programmierer die Klassen wählt. Aber daran denke ich zur Zeit nicht, da der Aufwand hier sehr hoch wäre. Oder es findet sich jemand, der das macht. 😉



  • Lust hätte ich schon dazu, weiß jedoch nicht, woher ich die Zeit nehmen sollte.
    Ich habe für das Spiel "Sacred 2" auch schon die 2D-GUI-Lib mitentwickelt (mit konsequenter Kapselung von Funktionalität und Design/Layout - die Windows konnten per XML serialisiert werden, so daß ich sogar einen (einfachen) InGame-WindowEditor entwickeln konnte). Diese beruhten zwar auf einem Renderer (inkl. Shaderprogrammierung), jedoch sollte das auch auf andere "Grafikengines" übertragbar sein (insbesondere wenn du nach X11 portieren willst, wirst du ja auch dann evtl. verschiedene Window-Layouts (Motif, Gnome, KDE (QT)) unterstützen wollen, oder)?

    Zur Zeit programmiere ich beruflich auch überwiegend in C#, aber C++ läßt mich einfach nicht los -)
    Wenn man etwas WPF ähnliches in C++ schaffen könnte, wäre das schon super...



  • Ich finde das Projekt nett, die WinAPI ist im Gegensatz zu den meisten GUI Libs eben sehr "leicht" 😉

    Weiter so.



  • @th69! WPF-artiges wäre für Algierlib keine Prio. WPF-artiges könnte für die Zukunft ein Thema sein. Es fehlen zu viele Basisfunktionen, wie du ja selber schon fest gestellt hast (detach, Iteration, editierbare Listen, Trees fehlen uvm.). Das Projekt hat auch keine Manpower, ich bin zur Zeit der einzige, der alles macht. Die Doku zu schreiben ist alleine schon sehr aufwändig.

    Erstmal Danke an alle für das bisherige Feedback!



  • Auf den ersten Blick gefaellts mir gut, bis auf die "_h" Suffixe fuer Handles. Ist zwar ein furchtbar subjektiver Punkt, aber fuer mich persoenlich sehr haesslich 😉

    Artchi schrieb:

    Wie sieht die Zukunft aus?
    Es ist ein Port auf X11-Systeme nötig, spricht X-Window. Somit UNIX-artige Systeme.

    Aber wrap bitte GTK oder Qt, nicht Xlib direkt!



  • "_h" ist mir auch komisch vorgekommen.
    Persönlich hätte ich eher "_handle" oder "_ptr" geschrieben. Ist aber nicht wichtig denke ich.

    Was mich mehr verwirrt ist die ganze MVC Sache. Ich denke einzelne Buttons/... sind "zu klein", um damit vernünftig MVC zu machen. Ich denke dass es Dinge eher verkompliziert als vereinfacht. Andrerseits hab' ich auch noch nie mit so einem System gearbeitet, kann also auch nicht sicher sein ob es nicht in der Praxis total praktisch ist.



  • Blue-Tiger schrieb:

    Auf den ersten Blick gefaellts mir gut, bis auf die "_h" Suffixe fuer Handles. Ist zwar ein furchtbar subjektiver Punkt, aber fuer mich persoenlich sehr haesslich 😉

    Ja, aber was wäre denn das schönere? Ich fand es kurz zu schreiben und durch den Unterstrich hebt sich das "h" auch hervor. Wenn ich z.B. windowh (also ohne Unterstrich) machen würde, würde das "h" untergehen. Ist halt schwierig.

    Aber solange es nur solche Kritikpunkte sind, kann ich mich also nicht beklagen. 😉

    Blue-Tiger schrieb:

    Aber wrap bitte GTK oder Qt, nicht Xlib direkt!

    Xlib sicherlich nicht. Ich habe da noch keine endgültige Entscheidung getroffen. Ich habe aber erstmal OpenMotif für einen Prototyp-Port vorgesehen. So kann ich sowohl die Gnome- als auch KDE-Fraktion nicht verärgern. OpenMotif ist eine stabile API. Das Look&Feel ist auch nicht mehr ganz so altbacken, da seit dem letzten Release UTF-8, PNG und Anti Aliasing Fonts unterstützt wird.



  • hustbaer schrieb:

    "_h" ist mir auch komisch vorgekommen.
    Persönlich hätte ich eher "_handle" oder "_ptr" geschrieben. Ist aber nicht wichtig denke ich.

    _handle ist definitiv zu lang. _ptr wäre OK.

    `view_h

    viewh

    view_handle

    view_ptr`

    _h gefällt mir immer noch am besten. Wenn es genug User geben würde, könnte man bis Release 1.0 darüber abstimmen lassen (aber nicht hier im Forum, wenn dann nur auf der offiziellen Projektseite).

    hustbaer schrieb:

    Was mich mehr verwirrt ist die ganze MVC Sache. Ich denke einzelne Buttons/... sind "zu klein", um damit vernünftig MVC zu machen. Ich denke dass es Dinge eher verkompliziert als vereinfacht. Andrerseits hab' ich auch noch nie mit so einem System gearbeitet, kann also auch nicht sicher sein ob es nicht in der Praxis total praktisch ist.

    Na, nur weil es ein Button ist? An so was würde ich nicht über solche wichtigen Dinge entscheiden. Wenn du wirklich eine Anwendung im MVC-Stil aufziehst, wirst du froh darüber sein. Ein Beispiel:

    Du hast einen 3D-Game-Level-Editor. Der User kann entscheiden, ob Lichtquellen ein oder aus sein sollen, in dem Level. Wenn du in MVC-Manier denkst, wirst du nicht an Buttons (konkret Checkboxen) denken. Du wirst an Daten (Models) denken:

    struct level
    {
       bool sonne;
    };
    

    Das nur als Denkanstoß. Du wirst doch sicher nicht das daraus machen:

    struct level
    {
       checkbox sonne;
    };
    

    Weil du auf die GUI-Objekte festgenagelt bist, in dem Fall auf ein einziges Objekt und noch dazu auf einen speziellen Typ. Deshalb wirst du das erste Beispiel so umsetzen:

    struct level
    {
       oran::binary sonne;
    };
    

    Es ist somit völlig egal wie die Lichtquellen in dem Level verfügbar gemacht werden. Du kannst jetzt die GUI frei gestalten. Du kannst nämlich die Lichtquellen über Checkboxen ein- und ausblenden lassen. Du kannst aber auch (zusätzlich) eine Checkbox in ein Pulldown-Menü einbauen. D.h. der User hat mittlerweile zwei Möglichkeiten. Du kannst aber auch einen Adapter bauen, und eine Dropdown-List an das Model anklemmen, in der "An" und "Aus" drin steht. Du könntest aber auch anstatt eines Checkbox einfach einen Toggle-Button anklemmen. Deine Datentypen bleiben aber immer gleich. Du kannst beliebig die GUI gestalten (lassen).

    Selbst der OpenGL-3D-Objekt-Renderer könnte dafür einfach das Binary-Objekt abfragen. Warum sollte er die Checkbox nach dem Status abfragen? 😃 Da fällt mir gerade auf, das ich noch einen Operator implementieren muß, damit man einfach if(level.sonne) abfragen könnte. 😉

    Auch in "ernsthaften" Anwendungen, die Formulare haben, lohnen sich Models.

    Es kostet ja nichts, Models zu nutzen. Wer absolut keine Models nutzen will, kann ja die Default-Models nutzen. Denn die bietet komfortabler weise jedes View-Objekt an. Vor allem in sehr kleinen Tools macht das sicherlich Sinn.

    Ich arbeite beruflich sehr viel mit Models. Habe auch schon oft Java-Code von Kollegen umgebaut, die keine Models nutzen, weil wir in einer Sackgasse gelandet sind. Deshalb sind solche Dinge wirklich nie "zu viel". Wenn du vielleicht irgendwann mal ein Projekt damit umsetzt, wirst du bestimmt den Vorteil erkennen können. 🙂



  • Also das _h stört mich da auch. Fände da es besser, wenn sowas in einem Namespace handle liegen würde.
    Du schreibst ja auch nich vor jede klasse algier:: 😉

    Ansonsten, sieht gut aus. Du machst wohl das, wofür ich keine Zeit habe 😃



  • phlox81 schrieb:

    Also das _h stört mich da auch. Fände da es besser, wenn sowas in einem Namespace handle liegen würde.
    Du schreibst ja auch nich vor jede klasse algier:: 😉

    Über den letzten Satz mußte ich erstmal ne Nacht drüber schlafen. Verstehe jetzt was du damit meinst.
    Das aber _h so weit auf Ablehnung stösst, hätte ich jetzt nicht gedacht. 🙄 Vielleicht solltet ihr es einfach nur mal eine Zeit auf euch wirken lassen? 😉
    Wie oben bereits gesagt, bis Version 1.0 kann man sowas noch ändern, da es ja nur ein Rename ist. Also noch ein Kandidat:

    `

    view_h

    viewh

    view_handle

    view_ptr

    handle::view`

    phlox81 schrieb:

    Ansonsten, sieht gut aus. Du machst wohl das, wofür ich keine Zeit habe 😃

    Danke! 🙂



  • Ich muss zugeben, mich hatte das _h anfangs auch gestört, aber inzwischen bin ich der Meinung, dass es okay ist 🙂

    Aber auch mit handle::view könnte ich leben. Die anderen Varianten gefallen mir aber absolut gar nicht mehr 🙂



  • handle::view ist doch designmäßig Quatsch. Das wäre ja fast wie alle Klassen in einen Namespace class zu packen. Ich hatte keine Zeit zu schauen, aber ist denn für den Benutzer überhaupt wichtig, dass es ein handle ist? Wenn nein, dann würde ich einfach view nehmen. Im Zweifelsfalle finde ich aber auch _h angenehmer als _handle oder _ptr.



  • Was meint ihr mit WPF-artig? Genauso langsam? *g*
    Nein im Ernst, die GUI von VS 2010 ist bei mir sehr viel langsamer als die unmanaged GUI von VS 2008. Kein Ziel, das ich anstreben würde. Interessant wäre allerdings, einen XML-artigen Parser für eine Markup-Language zu bauen, im DOM-Style (Document Object Model von JavaScript), was am Ende ein waschechtes Binary erzeugt.



  • Dummie schrieb:

    Ich muss zugeben, mich hatte das _h anfangs auch gestört, aber inzwischen bin ich der Meinung, dass es okay ist 🙂

    Sag ich ja, einfach mal auf sich wirken lassen.


Log in to reply