#include "pch.h"
#include "button.h"
#include "util.h"
#include "container.h"
#include "icons.h"
#include "../common/object.h"
#include "../common/context.h"
using namespace winrt;
using namespace Microsoft::
UI::Xaml;
using namespace Microsoft::
UI::Xaml::Controls;
using namespace Windows::
UI::Xaml::Interop;
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::
UI::Xaml::Controls::Primitives;
void ui_set_button_label(ButtonBase button,
const char* label,
const char* stockid,
const char *icon, UiLabelType type) {
if (type ==
UI_LABEL_ICON) {
label =
NULL;
}
else if (type ==
UI_LABEL_TEXT) {
icon =
NULL;
}
IconElement icon_elm = { nullptr };
if (icon) {
icon_elm = ui_get_icon(icon);
}
if (label && icon_elm) {
StackPanel panel = StackPanel();
panel.Orientation(Orientation::Horizontal);
panel.Spacing(
5);
panel.Children().Append(icon_elm);
wchar_t* wlabel = str2wstr(label, nullptr);
TextBlock label = TextBlock();
label.Text(wlabel);
panel.Children().Append(label);
free(wlabel);
button.Content(panel);
}
else if (label) {
wchar_t* wlabel = str2wstr(label, nullptr);
button.Content(box_value(wlabel));
free(wlabel);
}
else if (icon_elm) {
button.Content(ui_get_icon(icon));
}
}
UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) {
UiObject* current = uic_current_obj(obj);
Button button = Button();
ui_set_button_label(button, args.label, args.stockid, args.icon, args.labeltype);
UIElement elm = button;
UiWidget* widget = new UiWidget(elm);
ui_context_add_widget_destructor(current->ctx, widget);
ui_set_widget_groups(current->ctx, widget, args.groups);
if (args.onclick) {
ui_callback cbfunc = args.onclick;
void* cbdata = args.onclickdata;
button.Click([cbfunc, cbdata, obj](IInspectable
const& sender, RoutedEventArgs) {
UiEvent evt;
evt.obj = obj;
evt.window = obj->window;
evt.document = obj->ctx->document;
evt.eventdata = nullptr;
evt.intval =
0;
cbfunc(&evt, cbdata);
});
}
UI_APPLY_LAYOUT1(current, args);
current->container->Add(button, false);
return widget;
}
void togglebutton_register_checked_observers(ToggleButton button, UiObject* obj, UiVar* var) {
button.Checked([button, obj, var](IInspectable
const& sender, RoutedEventArgs) {
UiInteger* i = (UiInteger*)var->value;
UiEvent evt = ui_create_int_event(obj, i->get(i));
ui_notify_evt(i->observers, &evt);
});
}
void togglebutton_register_unchecked_observers(ToggleButton button, UiObject* obj, UiVar* var) {
button.Unchecked([button, obj, var](IInspectable
const& sender, RoutedEventArgs) {
UiInteger* i = (UiInteger*)var->value;
UiEvent evt = ui_create_int_event(obj, i->get(i));
ui_notify_evt(i->observers, &evt);
});
}
void togglebutton_register_callback(ToggleButton button, UiObject *obj, UiToggleArgs& args) {
ui_callback callback = args.onchange;
void* cbdata = args.onchangedata;
if (callback) {
button.Checked([button, obj, callback, cbdata](IInspectable
const& sender, RoutedEventArgs) {
UiEvent evt = ui_create_int_event(obj, true);
callback(&evt, cbdata);
});
button.Unchecked([button, obj, callback, cbdata](IInspectable
const& sender, RoutedEventArgs) {
UiEvent evt = ui_create_int_event(obj, false);
callback(&evt, cbdata);
});
}
}
static void switch_register_observers(ToggleSwitch button, UiObject* obj, UiVar* var) {
button.Toggled([button, obj, var](IInspectable
const& sender, RoutedEventArgs) {
UiInteger* i = (UiInteger*)var->value;
UiEvent evt = ui_create_int_event(obj, i->get(i));
ui_notify_evt(i->observers, &evt);
});
}
static void switch_register_callback(ToggleSwitch button, UiObject* obj, UiToggleArgs& args) {
ui_callback callback = args.onchange;
void* cbdata = args.onchangedata;
if (callback) {
button.Toggled([button, obj, callback, cbdata](IInspectable
const& sender, RoutedEventArgs) {
UiEvent evt = ui_create_int_event(obj, button.IsOn());
callback(&evt, cbdata);
});
}
}
static void togglebutton_changed(UiObject *obj, bool checked, ui_callback onchange,
void *onchangedata,
int enable_state) {
if (onchange) {
UiEvent evt;
evt.obj = obj;
evt.window = obj->window;
evt.document = obj->ctx->document;
evt.eventdata = nullptr;
evt.intval = checked;
onchange(&evt, onchangedata);
}
if (enable_state >
0) {
if (checked) {
ui_set_group(obj->ctx, enable_state);
}
else {
ui_unset_group(obj->ctx, enable_state);
}
}
}
static UIWIDGET create_togglebutton(UiObject *obj, ToggleButton button, UiToggleArgs args) {
UiObject* current = uic_current_obj(obj);
ui_set_button_label(button, args.label, args.stockid, args.icon, args.labeltype);
togglebutton_register_callback(button, obj, args);
UIElement elm = button;
UiWidget* widget = new UiWidget(elm);
ui_context_add_widget_destructor(current->ctx, widget);
ui_set_widget_groups(current->ctx, widget, args.groups);
UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_INTEGER);
if (var) {
UiInteger* value = (UiInteger*)var->value;
value->obj = widget;
value->get = ui_toggle_button_get;
value->set = ui_toggle_button_set;
togglebutton_register_checked_observers(button, obj, var);
togglebutton_register_unchecked_observers(button, obj, var);
}
if (args.enable_group >
0 || args.onchange) {
button.Checked([obj, args](IInspectable
const& sender, RoutedEventArgs) {
togglebutton_changed(obj, true, args.onchange, args.onchangedata, args.enable_group);
});
button.Unchecked([obj, args](IInspectable
const& sender, RoutedEventArgs) {
togglebutton_changed(obj, false, args.onchange, args.onchangedata, args.enable_group);
});
}
UI_APPLY_LAYOUT1(current, args);
current->container->Add(button, false);
return widget;
}
UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) {
ToggleButton button = ToggleButton();
return create_togglebutton(obj, button, args);
}
UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) {
CheckBox button = CheckBox();
return create_togglebutton(obj, button, args);
}
UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) {
ToggleSwitch button = ToggleSwitch();
if (args.label) {
wchar_t* wlabel = str2wstr(args.label, nullptr);
button.Header(box_value(wlabel));
free(wlabel);
}
switch_register_callback(button, obj, args);
UiObject* current = uic_current_obj(obj);
UIElement elm = button;
UiWidget* widget = new UiWidget(elm);
ui_context_add_widget_destructor(current->ctx, widget);
ui_set_widget_groups(current->ctx, widget, args.groups);
UiVar* var = nullptr;
if (args.value) {
var = uic_create_value_var(current->ctx, args.value);
}
else if (args.varname) {
var = uic_create_var(obj->ctx, args.varname,
UI_VAR_INTEGER);
}
if (var) {
UiInteger* value = (UiInteger*)var->value;
value->obj = widget;
value->get = ui_toggle_button_get;
value->set = ui_toggle_button_set;
switch_register_observers(button, obj, var);
}
UI_APPLY_LAYOUT1(current, args);
current->container->Add(button, false);
return widget;
}
UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args) {
RadioButton button = RadioButton();
UiObject* current = uic_current_obj(obj);
ui_set_button_label(button, args.label, args.stockid, args.icon, args.labeltype);
togglebutton_register_callback(button, obj, args);
UIElement elm = button;
UiWidget* widget = new UiWidget(elm);
ui_context_add_widget_destructor(current->ctx, widget);
ui_set_widget_groups(current->ctx, widget, args.groups);
UiVar* var = nullptr;
if (args.value) {
var = uic_create_value_var(current->ctx, args.value);
}
else if (args.varname) {
var = uic_create_var(obj->ctx, args.varname,
UI_VAR_INTEGER);
}
if (var) {
UiInteger* value = (UiInteger*)var->value;
CxList* radioButtons = (CxList*) (value->obj ? value->obj : cxLinkedListCreate(current->ctx->allocator,
NULL,
CX_STORE_POINTERS));
static int groupCount =
0;
winrt::hstring groupName;
if (cxListSize(radioButtons) ==
0) {
groupName = winrt::to_hstring(groupCount++);
}
else {
UiWidget* firstButtonWidget = (UiWidget*)cxListAt(radioButtons,
0);
RadioButton firstRadioButton = firstButtonWidget->uielement.as<RadioButton>();
groupName = firstRadioButton.GroupName();
}
cxListAdd(radioButtons, widget);
button.GroupName(groupName);
value->obj = radioButtons;
value->get = ui_radio_button_get;
value->set = ui_radio_button_set;
togglebutton_register_checked_observers(button, obj, var);
}
UI_APPLY_LAYOUT1(current, args);
current->container->Add(button, false);
return widget;
}
int64_t ui_toggle_button_get(UiInteger* integer) {
UiWidget* widget = (UiWidget*)integer->obj;
ToggleButton toggleButton = widget->uielement.as<ToggleButton>();
int val = toggleButton.IsChecked().GetBoolean();
integer->value = val;
return val;
}
void ui_toggle_button_set(UiInteger* integer,
int64_t value) {
UiWidget* widget = (UiWidget*)integer->obj;
ToggleButton toggleButton = widget->uielement.as<ToggleButton>();
toggleButton.IsChecked((bool)value);
integer->value = value;
}
int64_t ui_switch_get(UiInteger * integer) {
UiWidget* widget = (UiWidget*)integer->obj;
ToggleSwitch toggleButton = widget->uielement.as<ToggleSwitch>();
int val = toggleButton.IsOn();
integer->value = val;
return val;
}
void ui_switch_set(UiInteger * integer,
int64_t value) {
UiWidget* widget = (UiWidget*)integer->obj;
ToggleSwitch toggleButton = widget->uielement.as<ToggleSwitch>();
toggleButton.IsOn((bool)value);
integer->value = value;
}
int64_t ui_radio_button_get(UiInteger * integer) {
CxList* list = (CxList*)integer->obj;
CxIterator i = cxListIterator(list);
int selection = -
1;
cx_foreach(UiWidget*, widget, i) {
ToggleButton button = widget->uielement.as<ToggleButton>();
if (button.IsChecked().GetBoolean()) {
selection = i.index;
break;
}
}
integer->value = selection;
return selection;
}
void ui_radio_button_set(UiInteger * integer,
int64_t value) {
CxList* list = (CxList*)integer->obj;
UiWidget* widget = (UiWidget*)cxListAt(list, value);
if (widget) {
ToggleButton button = widget->uielement.as<ToggleButton>();
button.IsChecked(true);
integer->value = value;
}
}