--- a/ui/winui/window.cpp Wed Jan 31 12:55:11 2024 +0100 +++ b/ui/winui/window.cpp Tue Feb 06 14:17:22 2024 +0100 @@ -28,6 +28,7 @@ #include "pch.h" + #include "window.h" #include "appmenu.h" @@ -52,54 +53,12 @@ using namespace Microsoft::UI::Xaml::Markup; using namespace Windows::UI::Xaml::Interop; using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Storage::Pickers; UiWindow::UiWindow(winrt::Microsoft::UI::Xaml::Window& win) : window(win) {} UiObject* ui_window(const char* title, void* window_data) { - CxMempool* mp = cxBasicMempoolCreate(256); - UiObject* obj = (UiObject*)cxCalloc(mp->allocator, 1, sizeof(UiObject)); - - obj->ctx = uic_context(obj, mp); - obj->window = window_data; - - Window window = Window(); - //Window window = make<winui::implementation::MainWindow>(); - - winrt::Windows::Foundation::Uri resourceLocator{ L"ms-appx:///MainWindow.xaml" }; - Application::LoadComponent(window, resourceLocator, ComponentResourceLocation::Nested); - - window.ExtendsContentIntoTitleBar(true); - - Grid grid = Grid(); - window.Content(grid); - - StackPanel titleBar = StackPanel(); - Thickness titleBarPadding = { 10, 5, 5, 10 }; - titleBar.Padding(titleBarPadding); - titleBar.Orientation(Orientation::Horizontal); - TextBlock titleLabel = TextBlock(); - titleBar.Children().Append(titleLabel); - - if (title) { - wchar_t* wtitle = str2wstr(title, nullptr); - window.Title(wtitle); - titleLabel.Text(hstring(wtitle)); - free(wtitle); - } - - window.SetTitleBar(titleBar); - - obj->wobj = new UiWindow(window); - ui_context_add_window_destructor(obj->ctx, obj->wobj); - - window.Closed([obj](IInspectable const& sender, WindowEventArgs) { - cxMempoolDestroy(obj->ctx->mp); - }); - - obj->container = new UiBoxContainer(grid, UI_BOX_CONTAINER_VBOX, 0, 0); - - titleBar.VerticalAlignment(VerticalAlignment::Top); - obj->container->Add(titleBar, false); + UiObject* obj = ui_simple_window(title, window_data); if (uic_get_menu_list()) { // create/add menubar @@ -171,6 +130,55 @@ obj->container->Add(toolbar_grid, false); } + return obj; +} + +UIEXPORT UiObject* ui_simple_window(const char *title, void *window_data) { + CxMempool* mp = cxBasicMempoolCreate(256); + UiObject* obj = (UiObject*)cxCalloc(mp->allocator, 1, sizeof(UiObject)); + + obj->ctx = uic_context(obj, mp); + obj->window = window_data; + + Window window = Window(); + //Window window = make<winui::implementation::MainWindow>(); + + winrt::Windows::Foundation::Uri resourceLocator{ L"ms-appx:///MainWindow.xaml" }; + Application::LoadComponent(window, resourceLocator, ComponentResourceLocation::Nested); + + window.ExtendsContentIntoTitleBar(true); + + Grid grid = Grid(); + window.Content(grid); + + StackPanel titleBar = StackPanel(); + Thickness titleBarPadding = { 10, 5, 5, 10 }; + titleBar.Padding(titleBarPadding); + titleBar.Orientation(Orientation::Horizontal); + TextBlock titleLabel = TextBlock(); + titleBar.Children().Append(titleLabel); + + if (title) { + wchar_t* wtitle = str2wstr(title, nullptr); + window.Title(wtitle); + titleLabel.Text(hstring(wtitle)); + free(wtitle); + } + + window.SetTitleBar(titleBar); + + obj->wobj = new UiWindow(window); + ui_context_add_window_destructor(obj->ctx, obj->wobj); + + window.Closed([obj](IInspectable const& sender, WindowEventArgs) { + cxMempoolDestroy(obj->ctx->mp); + }); + + obj->container = new UiBoxContainer(grid, UI_BOX_CONTAINER_VBOX, 0, 0); + + titleBar.VerticalAlignment(VerticalAlignment::Top); + obj->container->Add(titleBar, false); + obj->window = window_data; return obj; @@ -185,3 +193,99 @@ win->window.AppWindow().Resize(wsize); } } + +static void filedialog_callback( + UiObject *obj, + ui_callback file_selected_callback, + void *cbdata, + winrt::Windows::Foundation::Collections::IVectorView<winrt::Windows::Storage::StorageFile> result) +{ + UiFileList flist; + flist.nfiles = result.Size(); + flist.files = new char*[flist.nfiles]; + + int i = 0; + for (auto const& file : result) { + winrt::hstring path = file.Path(); + flist.files[i++] = wchar2utf8(path.c_str(), path.size()); + } + + UiEvent evt; + evt.obj = obj; + evt.document = obj->ctx->document; + evt.window = obj->window; + evt.eventdata = &flist; + evt.intval = 0; + file_selected_callback(&evt, cbdata); + + for (int i = 0; i < flist.nfiles;i++) { + free(flist.files[i]); + } + delete[] flist.files; +} + +static Windows::Foundation::IAsyncAction open_filedialog_async(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { + FileOpenPicker openFileDialog = FileOpenPicker(); + auto initializeWithWindow { openFileDialog.as<::IInitializeWithWindow>() + }; + + HWND hwnd{ nullptr }; + winrt::check_hresult(obj->wobj->window.as<IWindowNative>()->get_WindowHandle(&hwnd)); + + initializeWithWindow->Initialize(hwnd); + + openFileDialog.FileTypeFilter().Append(L"*"); + + if ((mode & UI_FILEDIALOG_SELECT_MULTI) == UI_FILEDIALOG_SELECT_MULTI) { + auto files = co_await openFileDialog.PickMultipleFilesAsync(); + filedialog_callback(obj, file_selected_callback, cbdata, files); + } else { + auto file = co_await openFileDialog.PickSingleFileAsync(); + auto files = single_threaded_vector<winrt::Windows::Storage::StorageFile>(); + files.Append(file); + filedialog_callback(obj, file_selected_callback, cbdata, files.GetView()); + } +} + +static Windows::Foundation::IAsyncAction folderdialog_async(UiObject *obj, ui_callback file_selected_callback, void *cbdata) { + FolderPicker folderPicker = FolderPicker(); + auto initializeWithWindow { folderPicker.as<::IInitializeWithWindow>() + }; + + HWND hwnd{ nullptr }; + winrt::check_hresult(obj->wobj->window.as<IWindowNative>()->get_WindowHandle(&hwnd)); + + initializeWithWindow->Initialize(hwnd); + + folderPicker.FileTypeFilter().Append(L"*"); + + auto folder = co_await folderPicker.PickSingleFolderAsync(); + if (folder) { + winrt::hstring hpath = folder.Path(); + char *cpath = wchar2utf8(hpath.c_str(), hpath.size()); + + UiFileList flist; + flist.nfiles = 1; + flist.files = &cpath; + + UiEvent evt; + evt.obj = obj; + evt.document = obj->ctx->document; + evt.window = obj->window; + evt.eventdata = &flist; + evt.intval = 0; + file_selected_callback(&evt, cbdata); + } +} + +UIEXPORT void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { + if ((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { + folderdialog_async(obj, file_selected_callback, cbdata); + } else { + open_filedialog_async(obj, mode, file_selected_callback, cbdata); + } +} + +UIEXPORT void ui_savefiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { + +}