UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2023 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "pch.h" 30 31 #include "appmenu.h" 32 33 #include <cx/linked_list.h> 34 #include <cx/array_list.h> 35 36 #include "../common/context.h" 37 #include "../common/object.h" 38 39 #include "util.h" 40 41 42 using namespace winrt; 43 using namespace Microsoft::UI::Xaml; 44 using namespace Microsoft::UI::Xaml::Controls; 45 using namespace Microsoft::UI::Xaml::XamlTypeInfo; 46 using namespace Microsoft::UI::Xaml::Markup; 47 using namespace Windows::UI::Xaml::Interop; 48 49 static void add_top_menu_widget(MenuBar &parent, int i, UiMenuItemI* item, UiObject* obj); 50 51 static void add_menu_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); 52 static void add_menuitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); 53 static void add_menuseparator_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); 54 static void add_checkitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); 55 static void add_radioitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); 56 static void add_menuitem_list_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj); 57 58 static ui_menu_add_f createMenuItem[] = { 59 /* UI_MENU */ add_menu_widget, 60 /* UI_MENU_ITEM */ add_menuitem_widget, 61 /* UI_MENU_CHECK_ITEM */ add_checkitem_widget, 62 /* UI_MENU_RADIO_ITEM */ add_radioitem_widget, 63 /* UI_MENU_ITEM_LIST */ add_menuitem_list_widget, 64 /* UI_MENU_CHECKITEM_LIST */ add_menuitem_list_widget, 65 /* UI_MENU_RADIOITEM_LIST */ add_menuitem_list_widget, 66 /* UI_MENU_SEPARATOR */ add_menuseparator_widget 67 }; 68 69 winrt::Microsoft::UI::Xaml::Controls::MenuBar ui_create_menubar(UiObject* obj) { 70 MenuBar mb = MenuBar(); 71 72 UiMenu* menus_begin = uic_get_menu_list(); 73 74 UiMenu* ls = menus_begin; 75 while (ls) { 76 UiMenu* menu = ls; 77 add_top_menu_widget(mb, 0, &menu->item, obj); 78 79 ls = (UiMenu*)ls->item.next; 80 } 81 82 return mb; 83 } 84 85 static void add_top_menu_widget(MenuBar& parent, int i, UiMenuItemI* item, UiObject* obj) { 86 UiMenu* menu = (UiMenu*)item; 87 88 MenuBarItem mi = MenuBarItem(); 89 wchar_t* wlabel = str2wstr(menu->label, NULL); 90 mi.Title(wlabel); 91 free(wlabel); 92 93 UiMenuItemI* it = menu->items_begin; 94 int index = 0; 95 while (it) { 96 createMenuItem[it->type](mi.Items(), index, it, obj); 97 98 it = it->next; 99 index++; 100 } 101 102 parent.Items().Append(mi); 103 } 104 105 static void add_menu_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj) { 106 UiMenu* menu = (UiMenu*)item; 107 108 MenuFlyoutSubItem mi = MenuFlyoutSubItem(); 109 wchar_t* wlabel = str2wstr(menu->label, NULL); 110 mi.Text(wlabel); 111 free(wlabel); 112 113 parent.Append(mi); 114 115 UiMenuItemI* it = menu->items_begin; 116 int index = 0; 117 while (it) { 118 createMenuItem[it->type](mi.Items(), index, it, obj); 119 120 it = it->next; 121 index++; 122 } 123 124 125 } 126 127 static void add_menuitem_widget(winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, int i, UiMenuItemI* item, UiObject* obj) { 128 UiMenuItem* it = (UiMenuItem*)item; 129 130 MenuFlyoutItem mi = MenuFlyoutItem(); 131 wchar_t* wlabel = str2wstr(it->label, NULL); 132 mi.Text(wlabel); 133 free(wlabel); 134 135 parent.Append(mi); 136 } 137 138 static void add_menuseparator_widget( 139 winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, 140 int i, 141 UiMenuItemI* item, 142 UiObject* obj) 143 { 144 145 } 146 147 static void add_checkitem_widget( 148 winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, 149 int i, 150 UiMenuItemI* item, 151 UiObject* obj) 152 { 153 154 } 155 156 static void add_radioitem_widget( 157 winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, 158 int i, 159 UiMenuItemI* item, 160 UiObject* obj) 161 { 162 163 } 164 165 166 class UiMenuList { 167 public: 168 UiObject *obj = nullptr; 169 winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent = { nullptr }; 170 UiMenuItemType type; 171 int prevSize = 0; 172 int insertPos = 0; 173 UiVar* var = nullptr; 174 ui_getvaluefunc getvalue = nullptr; 175 ui_callback callback = nullptr; 176 void* userdata = nullptr; 177 178 UiMenuList() { 179 180 } 181 182 void updateItems() { 183 UiList* list = (UiList*)var->value; 184 185 // delete previous items 186 for (int i = 0; i < prevSize; i++) { 187 parent.RemoveAt(insertPos); 188 } 189 190 // insert new items 191 int count = 0; 192 void* elm = list->first(list); 193 while (elm) { 194 char *menuItemLabel = (char*) (getvalue ? getvalue(elm, 0) : elm); 195 196 MenuFlyoutItem mi = MenuFlyoutItem(); 197 wchar_t* wlabel = str2wstr(menuItemLabel ? menuItemLabel : "", NULL); 198 mi.Text(wlabel); 199 free(wlabel); 200 201 if (callback) { 202 mi.Click([this, elm, count](Windows::Foundation::IInspectable const& sender, RoutedEventArgs const& e) 203 { 204 UiEvent evt; 205 evt.obj = obj; 206 evt.window = obj->window; 207 evt.document = obj->ctx->document; 208 evt.eventdata = elm; 209 evt.intval = count; 210 callback(&evt, userdata); 211 }); 212 } 213 214 parent.InsertAt(insertPos + count, mi); 215 216 elm = list->next(list); 217 count++; 218 } 219 220 prevSize = count; 221 } 222 }; 223 224 extern "C" void destroy_ui_menu_list(void* ptr) { 225 UiMenuList* ls = (UiMenuList*)ptr; 226 delete ls; 227 } 228 229 static void ui_context_add_menu_list_destructor(UiContext* ctx, UiMenuList* list) { 230 cxMempoolRegister(ctx->mp, list, destroy_ui_menu_list); 231 } 232 233 static void ui_menulist_update(UiEvent* event, void* userdata) { 234 UiMenuList* mlist = (UiMenuList*)userdata; 235 mlist->updateItems(); 236 } 237 238 static void add_menuitem_list_widget( 239 winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItemBase> parent, 240 int i, 241 UiMenuItemI* item, 242 UiObject* obj) 243 { 244 UiMenuItemList* it = (UiMenuItemList*)item; 245 if (!it->varname) { 246 return; 247 } 248 249 uint32_t size = parent.Size(); 250 251 UiVar* var = uic_create_var(ui_global_context(), it->varname, UI_VAR_LIST); 252 253 UiMenuList* mlist = new UiMenuList(); 254 mlist->obj = obj; 255 mlist->parent = parent; 256 mlist->getvalue = it->getvalue; 257 mlist->callback = it->callback; 258 mlist->userdata = it->userdata; 259 mlist->prevSize = 0; 260 mlist->insertPos = size; 261 mlist->type = item->type; 262 mlist->var = var; 263 ui_context_add_menu_list_destructor(obj->ctx, mlist); 264 265 UiList* list = (UiList*)var->value; 266 list->observers = ui_add_observer(list->observers, ui_menulist_update, mlist); 267 268 mlist->updateItems(); 269 } 270 271 272 273 274 winrt::Microsoft::UI::Xaml::Controls::MenuFlyout ui_create_menu_flyout(UiObject* obj, UiMenu* menudef) { 275 MenuFlyout flyout = MenuFlyout(); 276 277 UiMenuItemI* it = menudef->items_begin; 278 int index = 0; 279 while (it) { 280 createMenuItem[it->type](flyout.Items(), index, it, obj); 281 282 it = it->next; 283 index++; 284 } 285 286 return flyout; 287 } 288 289 UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget) { 290 return NULL; 291 } 292 293 void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y) { 294 295 } 296