Tabsheets sind schon mal blöd, denn ab ca. 7 Funktionen wird das schnell unübersichtlich. Besser ist hier eine TreeView (auf der linken Seite) und Frames auf der rechten Seite. Pro Knoten ein Frame. Nun kannst Du deine Funktionen auch gruppieren, d.h. die Übersichtlichkeit erhöhen.
Die einzelnen Frames kannst du dann individuell programmieren, was die Übersichtlichkeit erhöht.
Ich würde allerdings noch einen Schritt weiter gehen, und jedem Funktionsgenerator eine Klasse spendieren, wobei jede Klasse eine Liste von Parametern exportiert. Die Parameter sind z.B. vom Typ 'Schalter/Boolean' und 'Wert/Double'. Vielleicht noch zusätzlich ein Auswahlfeld (Funktion 'A', 'B', 'C', 'D'). Ein einziges Frame übernimmt die Darstellung der Parameterliste, z.B. als untereinanderliegende Controls (CheckBox, Combo/Radiogroup und Slider/Eingabefeld). Da jeder Parameter auch Eigenschaften wie Min, Max, Caption, Default etc. exportiert, kannst Du das sehr elegant und vor allen Dingen uniform darstellen. Bei der individuellen Programmierung in Frames passiert es hingegen schnell, das sich das Layout der einzelnen Regler doch unterscheidet (weil man irgendwo eine Verbesserung vornimmt und die dann nicht auf alle Frames ausweitet z.B.)
Das Schöne an so einem Entwurf ist, das die Klasse selbst seine Position innerhalb des Treeviews angeben könnte. Weiterhin kannst Du jede Klasse in eine
DLL packen und so deine Applikation beliebig -auch nachträglich- erweitern.
Statt mit abstrakten Klassen würde ich das mit Interfaces realisieren, dann könnte man weitere Funktionen auch mit anderen Programmiersprachen zur Verfügung stellen, so etwa:
Delphi-Quellcode:
Type
IParameter = interface
Property Caption : String;
Property Value : OleVariant read get_Value write set_Value;
end;
IBooleanParameter = interface (IParameter)
end;
ISelectionParameter = interface (IParameter)
Property SelectionList : IList read get_SelectionList;
end;
IDoubleParameter = interface (IParameter)
Property Min : Double read...;
Property Max : Double read ...;
Property Default : Double read...;
end;
IFunction = interface
property Name : String;
property Parameter : IParameterList;
function Value (X : Double) : Double;
end;
Syntaktisch 100% ist das nicht, weil ich lange nichts mit Delphi gemacht habe. Als abstrakte Klasse geht es auch, nur dann bist Du an Delphi gebunden (was ja nicht per se schlecht ist).
Warum sollte das Projekt mit Frames aufgebläht werden?
Weil man doch nicht alles in eine Form schmeißen soll. SRP, OCP. Frames sind das visuelle Pendant zu einer Klasse. Pro Funktion eine Klasse => pro Funktion ein Frame. Stringentes Design, finde ich.
Ich sehe das eher als Übung, denn als ausgewachsenens Projekt. Die von mir vorgeschlagene Architektur ist etwas überkandidelt für diese Aufgabe, aber das Pattern eines erweiterbaren Pluginsystems sowie das Pattern eines Parameterlistenrenderers (der, der die Controls bastelt) ist für viele Aufgabenstellungen geeignet.
Ebenso wie das stringente Arbeiten mit Frames (Frame <-> Klasse).
Finde ich.