Cross-Platform App != Cross-Platform GUI

W pogoni za idealnym frameworkiem do GUI, zapomniałem o bardzo ważnej rzeczy:

Wielofunkcyjny scyzoryk nie zastąpi zestawu kluczy

Podobnie jest z wieloma innymi wielofunkcyjnymi rzeczami (np. smartfony nie zastąpią nigdy lustrzanek), więc również z frameworkami do GUI. Zarówno Xwt jak i Eto nie mogą w pełni wykorzystywać wszystkich obsługiwanych platform, ponieważ ich celem jest zapewnienie wspólnego API do tworzenia aplikacji na wiele platform. Zamiast tego należy zrobić to co ludzie robili od dawna: oddzielić interfejs użytkownika od logiki i wyodrębnić po jednym projekcie na każdą platformę.

Postawiłem na WPF na Windows oraz na GTK# na Linux/MacOS, aby obok cross-platformowości wspierać natywny wygląd dla platform, w które celuję (Windows i Linux). Postaram się np. korzystać z wbudowanych ikonek do których użytkownicy danej platformy są przyzwyczajeni.

Więc postanowiłem podzielić SharpOffice.Window.Runtime na SharpOffice.Runtime.WPF oraz SharpOffice.Runtime.GTK. Z tego względu postanowiłem usunąć SharpOffice.Window, które było zależne od Xwt. Mając dwa oddzielne (i jak różne) runtime’y, nie mogę mieć odwołań do obiektów używanych frameworków, a odwrócić te zależności.

W ten sposób aplikacje i pluginy będą korzystały z przestrzeni nazw SharpOffice.Core.Window do definiowania klas opartych o zestaw interfejsów, które następnie będą w odpowiedni sposób czytane przez runtime i na ich podstawie będzie generowane okno aplikacji.

Żeby uzyskać automatyczne ładowanie odpowiednich elementów, będę musiał wzbogacić moją klasę ContainerWrapper, której kod można zobaczyć tutaj, o dodatkowe ładowanie klas dotyczących zawartości okna. Np. IMenuComposer, który odwołując się do singletonu IMenuProvider, zawierającego listę menu najwyższego poziomu, dodaje odpowiednie pozycje, populując menu. Jeśli plugin będzie chciał mieć swoją pozycję w menu, wystarczy że zaimplementuje IMenuComposer, w którym utworzy obiekt typu IMenuElement i doda go do odpowiedniego menu.