Od 30 lat naszym chlebem powszednim jest c++. Oczywiście core środowiska GardensAM wraz z kompilatorem języka QLX napisaliśmy w „czystym” standardzie języka c++. Również interfejs użytkownika w aplikacji klienta systemu Gardens ERP oraz całe środowisko rozwoju GamBuilder do wersji 2.6 pod system MS Windows dotychczas budowaliśmy w technologii c++/Win32, korzystając z API pamiętających najstarsze wersje systemów operacyjnych Microsoftu. Kilka lat temu z radością i nadzieją przyjąłem informację o projekcji języka C++17 dla nowych interfejsów API Windows Runtime C++/WinRT opracowanej przez Kennego Kerra. Po wieloletnich doświadczeniach rozbudowy klas XAML w bibliotekach .net WPF (od roku 2006), mamy wreszcie w pełni obiektowe, bogate API w C++ do budowy interfejsów użytkownika aplikacji desktopowych systemów Windows. Trzy lata temu podjęliśmy próbę napisania nowej wersji interfejsu użytkownika klienta systemu GERP w nowym API systemu Win10/11. Dość szybko przekonaliśmy się że „uczłowieczenie” komponentów XAML-owych opartych na podstawie technologii com nie będzie prostym zadaniem. Po naprawdę ciężkiej i mozolnej pracy ta próba kończy się pełnym sukcesem. Mimo że stabilna wersja WinUI3 w c++/WinRT pojawiła się dopiero w lipcu 2024, ostatnie 3 lata spędziłem nad budową GamClienta4.00 w technologii C++/WinRT. Zapraszam do filmików prezentujących nowego klienta systemu GardensERP.
Naszym założeniem było zbudowanie klienta pod Win bez użycia „starego” API poprzednich systemów operacyjnych Windows, ciągle używanego przez developerów na całym świecie ze względu na utrzymywanie i rozwój zdecydowanej większości aplikacji dla Windows pisanych jednak w starych technologiach. Każdy wie, że produkcyjne aplikacje UWP to ciągle rzadkość. Jest nawet taka plotka że jedyne aplikacje jakie istnieją na rynku zostały napisane przez MS 😊. Ale to nie prawda bo jesteśmy tego przykładem. Choć okazuje się, że jesteśmy w tym pionierami i jedną z pierwszych firm na świecie, której udało się wykorzystać C++/WinRT tak rozbudowanej aplikacji UWP, jaką jest pełna platformą systemu ERP. W kolejnych publikacjach chciałbym podzielić się kilkoma doświadczeniami w nowym API Win10/11, opartym na standardzie języka c++ (bez rozszerzeń), które w przyszłości będzie podstawowym narzędziem do tworzenia klasycznych aplikacji systemów operacyjnych Windows Microsoftu.
DataGrid - tabele danych
Najważniejszym elementem interfejsu użytkownika systemu ERP jest tabelaryczne przedstawienie danych.
Najpierw opowiem o trudnościach użycia kontrolek XAML w tym zakresie. Mechanizm C++/WinRT nie dostarcza standardowej kontrolki DataView. Dostępna na GitHabie kontrolka to zaledwie próba, moim zdaniem bardzo prosta i nie nadaje się do zastosowań produkcyjnych przeglądania dużej ilości danych. Szybko okazało się dlaczego nie ma standardowej kontrolki. Otóż po roku walki z wirtualizacją zawartą w komponentach XAML takich jak ListView doszliśmy do prostego wniosku że te mechanizmy nie nadają się do zastosowań produkcyjnych gdzie mamy bardzo duży wolumen danych. Złożone kontrolki XAML takie jak TreeView czy ListView starowane są kolekcjami a cały „kombajn” wirtualizacyjny siedzi w środku i jest niezarządzalny. Jedyne zarządzanie to zarządzanie źródłową kolekcją danych reszta ma się dziać automatycznie. Pomysł fajny, pełen automat, tylko bardzo kosztowny w przypadku wirtualizacji zawartości, w której mamy bardzo dużo powielanych kontrolek. I w przypadku tabel o bardzo dużej ilości wierszy, które chcemy przewijać w dowolny sposób, zawsze będzie problem wydajności. Klasy C++/WinRT udostępniane są przez warstwę comową co oznacza, że nie wszystkie klasy wewnętrzne (pośrednie) mają swoje interfejsy i są udostępnione. Inaczej mówiąc jeżeli chcesz „pogrzebać w bebechach” to w większości przypadków to się tobie nie uda. Więc rozbieranie i usprawnianie mechanizmu wirtualizacji nie jest możliwe. Dlatego zbudowaliśmy i testowaliśmy równolegle 2 komponenty do szybkiego przeglądania danych: pierwszy komponent oparty na Winrt:UI:Xaml:Controls:ListView i wirtualizacji kontrolek i drugi skonstruowany na takich samych zasadach jak grid w wersji GB2.6 tylko bezpośrednio za pomocą grafiki DirectX.
Na chwilę obecną nie dało się uzyskać zadowalającej wydajności kontrolki DataView (zwykłej wydawało by się tabelki do przeglądania danych) opartej na wirtualizacji ListView, która by działała sprawnie. Okazało się że całą wydajność zabija wirtualizacja podstawowej kontrolki ListView. Już podstawowa lista jednokolumnowa z TextBlock i dużą ilością wierszy działa bardzo wolno i nie ma to żadnych szans w konkurencji z bezpośrednim rysowaniem w danej chwili jednego ekranu tabelki, niezależnie ile kolumn i wierszy ona posiada jak to było zrobione w dobrze znanej wersji naszego GamBuildera2.6. Okazało się że poprzeczkę wydajności postawiliśmy sobie wysoko. Więc nie było rady i przepisaliśmy naszą kontrolę grida tak aby rysować ekrany bezpośrednio w DirectX. I tak powstała kontrolka DataGrid, której zawartość (komórki z danymi) są rysowane bezpośrednio na warstwie graficznej bez udziału kontrolek XAML i ich wirtualizacji.
Mimo toporności niektórych mechanizmów takich jak wirtualizacja jest jednak dużo zalet nowego obiektowego API WinRT. Otóż jest ono z natury wielowątkowe i nowe standardy c++ z korutynami dają niezwykłego „kopa” aplikacji. Zastosowaliśmy te możliwości w naszym nowym DataGridzie do kalkulacji pól dynamicznych w wątkach tła.
Dane systemu GardensERP mogą posiadać dodatkowo 2 rodzaje pól dynamicznych-kalkulacyjnych. Mogą to być pola widokowe, które są podzapytaniami i realizuje je serwer bazy danych, lub mogą być procedurami kalkulowanymi za pomocą klienta lub serwer aplikacyjny. Często użytkownik systemu ERP wymaga pola raportującego bardzo złożone zależności danych i kalkulacja takich pól zdecydowanie zwalnia wyświetlanie danych w tabelkach systemu. Dzięki wielowątkowości nowy DataGrid uzbroiliśmy w wątki tła które przeliczają te pola bez blokowania interfejsu użytkownika. Po prostu użytkownik nigdy nie czeka na dane. Jeżeli zatrzymuje się na jakimś ekranie podczas przewijania danych, to po chwili, bez blokowanie GUI, wątki tła odświeżają przeliczone kolumny z polami kalkulowanymi. Ponieważ przelicza się tylko bieżący ekran trwa to ułamek sekundy w innym wątku nie wpływając na działanie użytkownika. Szczerze mówiąc z tego rozwiązania jestem najbardziej zadowolony. Może nie koniecznie dlatego, że nikt na świecie jeszcze tego nie zrobił w grubym kliencie, ale bardziej dlatego że aplikacja klienta 4.0 GardensERP jest super płynna i wydajna podczas bieżącej pracy użytkowników. I warto się tym chwalić bo naprawdę uczłowieczanie WinRT kosztuje nas ocean mozolnej pracy. Efekty zobaczcie sami :
https://gardens-software.com/technologia/gui/