Skip to content

Instantly share code, notes, and snippets.

@OhmPopy
Created August 28, 2021 13:22
Show Gist options
  • Save OhmPopy/e25b1bcac1f93fdcec5582e12367a483 to your computer and use it in GitHub Desktop.
Save OhmPopy/e25b1bcac1f93fdcec5582e12367a483 to your computer and use it in GitHub Desktop.
ButtonSplit Control
#include <Controls/ControlHelper.h>
#include <Controls/IThemeControl.h>
#include <Controls/ButtonSvg/ButtonSplit.h>
#include <Shareds/SharedXamlStore.h>
#include <System/Input/KeyboardNavigation.h>
#include <System/Input/MouseDevice.h>
#include <System/Tools/EventHelper.h>
#include <System/Tools/HwndHelper.h>
#include <System/Tools/VisualTreeHelper.h>
namespace Controls
{
ImplementTypeOfClass(ButtonSplit, Selector)
ImplementTypeOfClass(ButtonSplitItem, ListBoxItem)
RoutedEvent* ButtonSplit::ClickEvent;
DependencyProperty* ButtonSplit::BorderBrushDropDownProperty;
DependencyProperty* ButtonSplit::TextProperty;
DependencyProperty* ButtonSplit::IsReadOnlyTextProperty;
DependencyProperty* ButtonSplit::AutoHeightPopupProperty;
DependencyProperty* ButtonSplit::IsDropDownOpenProperty;
DependencyProperty* ButtonSplit::MaxDropDownHeightProperty;
DependencyProperty* ButtonSplit::SelectionBoxItemProperty;
DependencyProperty* ButtonSplit::SelectionBoxItemTemplateProperty;
DependencyProperty* ButtonSplit::TooltipEx;
DependencyProperty* ButtonSplit::TooltipPostion;
DependencyProperty* ButtonSplit::TooltipHotkeyIndex;
void ButtonSplitItem::OnMouseMove(MouseEventArgs* e)
{
ListBoxItem::OnMouseMove(e);
ButtonSplit* pParent = TypeCast<ButtonSplit>(GetParent());
if (pParent)
{
if (MouseDevice::GetLeftButton() == MousePress)
{
pParent->SetCaptureMouse();
}
}
}
void ButtonSplitItem::OnMouseLeftButtonUp(MouseButtonEventArgs* e)
{
ListBoxItem::OnMouseLeftButtonUp(e);
ButtonSplit* pParent = TypeCast<ButtonSplit>(GetParent());
if (pParent)
{
pParent->OnMouseLeftButtonUp(e);
}
if (Get_IsEnabled()/*!GetItemEntry()->HasFlag(ItemEntry::fDisabled)*/)
{
SetSelectedFlag(sfFromMouse, true);
SetValue(IsSelectedProperty, Boolean::True);
if (IsLoaded())
pParent->OnClick(this);
SetSelectedFlag(sfFromMouse, false);
HwndHelper::CloseWindow(this, true);
}
}
DropDownButtonSplitEventArgs::DropDownButtonSplitEventArgs(PopupPtr popup) : _popup(popup)
{
}
PopupPtr DropDownButtonSplitEventArgs::GetPopup() const
{
return _popup;
}
ButtonSplit::ButtonSplit() : _dropDownPopup(NULL), _selectButton(NULL), _isChangeTheme(false)
{
StaticInit();
IThemeControl::LoadResourceForControl(SharedXamlStore::CreteaResourceControl("BinTrade/Controls/ButtonSplit.xml"), this);
}
ButtonSplit::~ButtonSplit()
{
}
void ButtonSplit::OnIsDropDownOpenChanged(DependencyObject* d, DependencyPropertyChangedEventArgs* e)
{
ButtonSplit* box = TypeCast<ButtonSplit>(d);
const bool bIsOpen = e->GetNewValue()->ToBool();
if (NULL != box && box->_dropDownPopup)
{
if (box->GetScrollHost())
{
Object* selItem = box->GetSelectedItem();
if (NULL == DependencyProperty::UnsetValue())
{
box->GetScrollHost()->SetVerticalOffset(0);
}
else
{
ItemNavigateArg ex(MouseDevice::Current(), (int)ModifierKey::None);
box->NavigateToItem(selItem, -1, 0, &ex, true);
}
}
if (bIsOpen)
{
if (box->HasItems()) //chắc chắn có phần tử thì hãy thực hiện việc mở popup nếu không có thì không thực hiện mở
{
const int iMinWidth = SystemParameters::TransformXFromDevice(box->GetRenderSize().cx) + 0.5;
//box->_dropDownPopup->GetPopupRoot()->Visibilities = Hidden;
box->_dropDownPopup->SetMinWidth(iMinWidth);
//phân tích và xử lý để có chiều cao ổn định nhất
//luôn lớn hơn hoặc bằng chiều cao min. mặc kệ min lớn hơn max
//đếm số lượng item để tính chiều cao của popup
if (box->GetValue(AutoHeightPopupProperty)->ToBool())
{
int heightCalc = 6; //margin scroll tma thoi là lay 6 nhung thuc chat tuy thuoc vào việc ta set ở xaml
for (int i = 0; i < box->GetCount(); ++i)
{
Object* objectItem = box->GetItem(i);
ButtonSplitItem* item = TypeCast<ButtonSplitItem>(objectItem);
if (item != NULL) //loai ButtonSplit item
{
const int h = item->GetActualHeight();
if (h != 0)
heightCalc += h;
else
heightCalc += item->GetMinHeight();
}
else
{
//content vo dinh nhu string. dang nay khong co control de tinh chieu cao vi the ta se lay chieu cao cua ButtonSplit de tinh
//ta có thể dùng GetContainerForItemOverride để tạo ra ButtonSplitItem sau đó tính chiều cao và chiều cao tối thiểu nhưng nó lại không có style chính xác nên không lấy được chiều cao
//Ta sẽ dùng chiều cao cua ButtonSplit để tính chiều cao của item nó sẽ không thực sự chính xác khi mà chiều cao của ButtonSplit và item style khác nhau nhưng có còn hơn không. đã test là không tuong thich nhung dung tam
const int h = box->GetActualHeight();
if (h != 0)
heightCalc += h;
else
heightCalc += box->GetMinHeight();
}
}
const Size sizeClient = Environment::GetScreenClient();
Point point = box->FindLocationOfControlInWindow();
const Point positionThis = box->PointToScreen(Point());
point += positionThis;
//kiểm tra kích thước của popup và vị trí so với kích htuowcs màn hình
if (point.Y + box->GetActualHeight() + heightCalc < sizeClient.Height) //down popup
{
box->_dropDownPopup->SetMinHeight(heightCalc);
}
else
{
if (point.Y - box->GetActualHeight() - heightCalc > 0) //top popup
{
box->_dropDownPopup->SetMinHeight(heightCalc);
}
else
{
int down = sizeClient.Height - point.Y + box->GetActualHeight();
int up = point.Y - box->GetActualHeight();
box->_dropDownPopup->SetMinHeight(down > up ? down : up);
}
}
}
box->_dropDownPopup->SetMaxHeight(box->GetDropDownHeight());
Dispatcher::Current()->PushTrackPopup(box->_dropDownPopup);
box->GetAssigner()->GetTopAssignerFrame()->RegisterHook(box, MessageHook(box, &ButtonSplit::OnMessageFilter));
DropDownButtonSplitEventArgs eo(box->_dropDownPopup);
box->OnDropDownOpened(&eo);
box->UpdateVisualState(false);
}
else
{
box->SetIsDropDownOpen(false);
//box->_dropDownPopup->GetPopupRoot()->Visibilities = Collapsed;
//box->_dropDownPopup->GetPopupRoot()->SetDesiredSize(Size(0,0));
//chặn show khi được gọi bởi 2 event ở xaml nên dùng cách này để không hiển thị khi gọi bởi xaml
}
}
else
{
box->GetAssigner()->GetTopAssignerFrame()->RemoveHookFromObject(box);
Dispatcher::Current()->RemoveTrackPopup(box->_dropDownPopup);
DropDownButtonSplitEventArgs eo(box->_dropDownPopup);
box->OnDropDownClosed(&eo);
}
}
}
void ButtonSplit::OnTextPropChanged(DependencyObject* d, DependencyPropertyChangedEventArgs* e)
{
ButtonSplit* box = TypeCast<ButtonSplit>(d);
if (NULL != box)
{
OString* pText = TypeCast<OString>(e->GetNewValue());
if (NULL != pText)
{
pText->SetString(e->GetOldValue()->ToString());
}
}
}
void ButtonSplit::StaticInit()
{
if (NULL == TextProperty)
{
Selector::StaticInit();
ButtonSplitItem::StaticInit();
ClickEvent = EventHelper::RegisterRoutedEvent(_U("Click"), RoutingStrategy::Bubble, typeof(RoutedEventHandler), typeof(ButtonSplit));
IsMouseOverProperty->OverrideMetadata(InfoType(), DependencyPropertyMemory::GetPropMeta(Boolean::False, 0, &OnVisualStatePropChanged));
BorderBrushDropDownProperty = DependencyProperty::Register(_U("BorderBrushDropDown"), InfoType(), Brush::InfoType(), DependencyPropertyMemory::GetPropMeta(NULL, AffectsNone));
TextProperty = DependencyProperty::Register(_T("Text"), InfoType(), OString::InfoType(), DependencyPropertyMemory::GetPropMeta(OString::EmptyString, AffectsArrange, &ButtonSplit::OnTextPropChanged));
IsReadOnlyTextProperty = DependencyProperty::Register(_T("IsReadOnlyText"), InfoType(), Boolean::InfoType(), DependencyPropertyMemory::GetPropMeta(Boolean::False, AffectsArrange));
AutoHeightPopupProperty = DependencyProperty::Register(_T("AutoHeightPopup"), InfoType(), Boolean::InfoType(), DependencyPropertyMemory::GetPropMeta(Boolean::True, AffectsNone));
IsDropDownOpenProperty = DependencyProperty::Register(_T("IsDropDownOpen"), InfoType(), Boolean::InfoType(), DependencyPropertyMemory::GetPropMeta(Boolean::False, AffectsNone, &ButtonSplit::OnIsDropDownOpenChanged));
MaxDropDownHeightProperty = DependencyProperty::Register(_T("MaxDropDownHeight"), InfoType(), Integer::InfoType(), DependencyPropertyMemory::GetPropMeta(new Integer(80), AffectsNone));
SelectionBoxItemProperty = DependencyProperty::Register(_T("SelectionBoxItem"), InfoType(), Object::InfoType(), DependencyPropertyMemory::GetPropMeta(NULL, AffectsParentArrange));
SelectionBoxItemTemplateProperty = DependencyProperty::Register(_T("SelectionBoxItemTemplate"), InfoType(), DataTemplate::InfoType(), DependencyPropertyMemory::GetPropMeta(NULL, AffectsParentArrange));
TooltipEx = DependencyProperty::Register(_T("TooltipEx"), InfoType(), OString::InfoType(), DependencyPropertyMemory::GetPropMeta(OString::EmptyString, AffectsRender, TextTooltipExPropertyChange));
TooltipPostion = DependencyProperty::Register(_T("TooltipPostion"), InfoType(), Integer::InfoType(), DependencyPropertyMemory::GetPropMeta(Integer::ZeroInteger, AffectsRender, TooltipPostionPropertyChange));
TooltipPostion->SetConvertValueCb(ArrowPostionConvert::Convert);
TooltipHotkeyIndex = DependencyProperty::Register(_T("TooltipHotkeyIndex"), InfoType(), Integer::InfoType(), DependencyPropertyMemory::GetPropMeta(Integer::ZeroInteger, AffectsRender, TooltipHotkeyIndexPropertyChange));
TooltipHotkeyIndex->SetConvertValueCb(HotkeyIndexConvert::Convert);
KeyboardNavigation::TabNavigationProperty->OverrideMetadata(InfoType(), DependencyPropertyMemory::GetPropMeta(Integer::GetPosInt((int)KeyboardNavigationMode::Local)));
KeyboardNavigation::ControlTabNavigationProperty->OverrideMetadata(InfoType(), DependencyPropertyMemory::GetPropMeta(Integer::GetPosInt((int)KeyboardNavigationMode::None)));
KeyboardNavigation::DirectionalNavigationProperty->OverrideMetadata(InfoType(), DependencyPropertyMemory::GetPropMeta(Integer::GetPosInt((int)KeyboardNavigationMode::None)));
}
}
bool ButtonSplit::OnMessageFilter(Object* sender, MessageParam* mp, bool& interrupt)
{
ButtonSplit* cmb = TypeCast<ButtonSplit>(_dropDownPopup->GetTemplatedParent());
if (NULL == cmb)
{
return false;
}
if (_dropDownPopup->GetPopupRoot() != sender)
{
if (mp->message == WM_MOUSEMOVE && !PointTransform::PointInElement(cmb, NULL))
{
return true;
}
}
else
{
interrupt = true;
return false;
}
if (mp->message == WM_KEYDOWN)
{
bool bInterrupt = true;
int index = GetSelectedIndex();
if (index < 0)
{
index = -1;
}
switch ((int)mp->wp)
{
case Key::Up:
if (index > 0)
{
SetSelectedIndex(--index);
_dropDownPopup->UpdateLayout();
}
break;
case Key::Down:
if (index < GetCount() - 1)
{
SetSelectedIndex(++index);
_dropDownPopup->UpdateLayout();
}
break;
case Key::Escape:
_dropDownPopup->AsyncClose();
break;
case Key::Return:
_dropDownPopup->AsyncClose();
break;
default:
bInterrupt = false;
}
interrupt = bInterrupt;
if (bInterrupt)
{
return bInterrupt;
}
}
return _dropDownPopup->OnSysFilterMessage(sender, mp, interrupt);
}
void ButtonSplit::Dispose()
{
if (_dropDownPopup)
{
_dropDownPopup->unref();
_dropDownPopup = NULL;
}
Selector::Dispose();
}
bool ButtonSplit::IsItemItsOwnContainer(Object* item)
{
return (ButtonSplitItem::InfoType() == item->GetInfoType());
}
UIElement* ButtonSplit::GetContainerForItemOverride()
{
return new ButtonSplitItem();
}
int ButtonSplit::FindIndex(const String& text) const
{
for (int i = 0; i < GetCount(); ++i)
{
String strItem = GetItem(i)->ToString();
if (strItem.Equals(text))
{
return i;
}
}
return -1;
}
int ButtonSplit::FindIndex(Object* item) const
{
for (int i = 0; i < GetCount(); ++i)
{
Object* cmbItem = GetItem(i);
if (item->Equals(cmbItem))
{
return i;
}
}
return -1;
}
bool ButtonSplit::IsDropDownOpen()
{
return GetValue(IsDropDownOpenProperty)->ToBool();
}
void ButtonSplit::SetIsDropDownOpen(bool val)
{
SetValue(IsDropDownOpenProperty, BOOLTOBOOLEAN(val));
InvalidateForce();
UpdateLayout();
}
void ButtonSplit::SetDropDownHeight(int height)
{
SetValue(MaxDropDownHeightProperty, new Integer(height));
InvalidateForce();
UpdateLayout();
}
void ButtonSplit::SelectItemByName(const String& name)
{
ItemCollection* itemsColl = GetItemsSource();
if (itemsColl != NULL)
{
for (int i = 0; i < itemsColl->GetCount(); ++i)
{
ButtonSplitItem* item = (ButtonSplitItem*)itemsColl->GetItem(i);
if (item != NULL && item->Name == name)
{
item->SetIsSelected(true);
break;
}
}
}
}
void ButtonSplit::Update(bool bFocus)
{
Object* selectedItem = GetSelectedItem();
DataTemplate* itemTemplate = GetItemTemplate();
ContentControl* control = TypeCast<ContentControl>(selectedItem);
if (control != NULL)
{
selectedItem = control->GetContent();
itemTemplate = control->GetContentTemplate();
}
if (selectedItem == NULL || selectedItem == DependencyProperty::UnsetValue())
{
selectedItem = OString::EmptyString;
}
SetSelectionBoxItem(selectedItem);
SetSelectionBoxItemTemplate(itemTemplate);
UpdateLayout();
}
String ButtonSplit::GetText()
{
String strText = GetValue(TextProperty)->ToString();
return strText;
}
void ButtonSplit::SetText(const String& text)
{
SetValue(TextProperty, new OString(text));
}
bool ButtonSplit::StaysOpenOnEdit() const
{
return _dropDownPopup->IsOpen();
}
void ButtonSplit::OnPreInvalidateResourceReference(bool onlySelf)
{
if (_dropDownPopup != NULL)
_dropDownPopup->InvalidateResourceReference(onlySelf);
if (!onlySelf && GetItemsSource() != NULL)
{
for (int i = 0; i < GetItemsSource()->GetCount(); ++i)
{
Object* object = GetItemsSource()->GetItem(i);
ButtonSplitItem* item = TypeCast<ButtonSplitItem>(object);
if (item != NULL)
{
if (item->Parent == NULL)
{
/*
* Nếu có scoll sẽ chỉ hiển thị được 1 số item ở scroll và các ButtonSplit item khác
* Sẽ không có parent nên sẽ không tìm được res gây ra lỗi
* Vì vậy ta sẽ cần thực hiện tùy chỉnh lại để ButtonSplitItem có thể tìm được res
*/
item->OnNewParent(this);
item->InvalidateResourceReference(false);
}
else
{
item->InvalidateResourceReference(false);
}
}
}
}
}
void ButtonSplit::OnApplyTemplate()
{
Selector::OnApplyTemplate();
_dropDownPopup = TypeCast<Popup>(GetTemplateChild("PART_Popup"));
if (_dropDownPopup)
{
_dropDownPopup->SetPlacementTarget(this);
_dropDownPopup->Opened += EventHandler(this, &ButtonSplit::OnPopupOpened);
_dropDownPopup->Closed += EventHandler(this, &ButtonSplit::OnPopupClosed);
_dropDownPopup->Opening += EventHandler(this, &ButtonSplit::OnPopupOpening);
_dropDownPopup->Closing += EventHandler(this, &ButtonSplit::OnPopupClosing);
}
_selectButton = TypeCast<Button>(GetTemplateChild("PART_Button"));
if (_selectButton)
{
_selectButton->AddHandler(Button::ClickEvent, new RoutedEventHandler(this, &ButtonSplit::PART_ButtonClick));
}
Update(false);
}
bool ButtonSplit::BlockRouteEvent()
{
return true;
}
void ButtonSplit::OnClick(ButtonSplitItem* selItem)
{
ButtonSplitEventArgs button_split_event_args(GetValue(IsReadOnlyTextProperty)->ToBool(), selItem);
button_split_event_args.Set_RoutedEventAndSource(ClickEvent, this);
RaiseEvent(&button_split_event_args);
//if (selItem != NULL)
//{
// ToastEx::Show("Click:" + selItem->ToString());
//}
//else
// ToastEx::Show("Click Normal");
}
void ButtonSplit::PART_ButtonClick(DependencyObject* d, RoutedEventArgs* e)
{
Focus();
if (NULL == _dropDownPopup)
return;
if (IsDropDownOpen())
SetIsDropDownOpen(false);
else
{
if (GetValue(IsReadOnlyTextProperty)->ToBool())
{
OnClick(NULL);
}
else
OnClick((ButtonSplitItem*)GetSelectedItem());
}
}
void ButtonSplit::OnPopupOpened(Object* sender, EventArgs* e)
{
RoutedEventArgs eventX(ContextMenuOpenedEvent, sender);
RaiseEvent(&eventX);
//for test
//if (GetItemsSource() != NULL)
//{
// for (int i = 0; i < GetItemsSource()->GetCount(); ++i)
// {
// Object* object = GetItemsSource()->GetItem(i);
// ButtonSplitItem* item = TypeCast<ButtonSplitItem>(object);
// if (item != NULL&& item->GetContent()!=NULL)
// {
// Debug::WriteLine(item->GetContent()->ToString());
// Debug::WriteLine(String(item->Location));
// }
// }
//}
}
void ButtonSplit::OnPopupClosed(Object* sender, EventArgs* e)
{
RoutedEventArgs eventX(ContextMenuClosedEvent, sender);
RaiseEvent(&eventX);
}
void ButtonSplit::OnPopupOpening(Object* sender, EventArgs* e)
{
RoutedEventArgs eventX(ContextMenuOpeningEvent, sender);
RaiseEvent(&eventX);
}
void ButtonSplit::OnPopupClosing(Object* sender, EventArgs* e)
{
RoutedEventArgs eventX(ContextMenuClosingEvent, sender);
RaiseEvent(&eventX);
}
void ButtonSplit::OnPostInvalidateResourceReference(bool onlySelf)
{
_isChangeTheme = true;
if (Get_IsEnabled())
{
SetValue(IsMouseOverProperty, Boolean::True); // multi trigger
SetValue(IsMouseOverProperty, Boolean::False); //reset
SetValue(IsEnabledProperty, Boolean::False);
SetValue(IsEnabledProperty, Boolean::True);
}
else
{
SetValue(IsMouseOverProperty, Boolean::True);
SetValue(IsMouseOverProperty, Boolean::False);
SetValue(IsEnabledProperty, Boolean::True);
SetValue(IsEnabledProperty, Boolean::False);
}
_isChangeTheme = false;
}
void ButtonSplit::OnIsEnabledChanged(IsEnabledChangedEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnIsEnabledChanged(e);
}
void ButtonSplit::OnMouseEnter(MouseEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnMouseEnter(e);
}
void ButtonSplit::OnMouseLeave(MouseEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnMouseLeave(e);
}
void ButtonSplit::OnMouseMove(MouseEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnMouseMove(e);
}
void ButtonSplit::OnMouseDown(MouseButtonEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnMouseDown(e);
}
void ButtonSplit::OnMouseUp(MouseButtonEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnMouseUp(e);
}
void ButtonSplit::OnMouseWheel(MouseWheelEventArgs* e)
{
if (!_isChangeTheme)
Selector::OnMouseWheel(e);
}
// ButtonSplit
void ButtonSplit::OnKeyDown(KeyEventArgs* e)
{
if (e->KeyValue == Key::Return)
{
}
else if (e->KeyValue == Key::Down)
{
if (_dropDownPopup != NULL)
{
SetIsDropDownOpen(true);
}
}
else if ((e->KeyValue == Key::Escape || e->KeyValue == Key::F4 && bin::KeyEventArgs::GetModifierKey() == ModifierKey::Alt) && _dropDownPopup)
{
_dropDownPopup->Close();
e->Set_Handled(true);
}
}
void ButtonSplit::OnSelectionChanged(SelectionChangedEventArgs* e)
{
Selector::OnSelectionChanged(e);
Object* selItem = GetSelectedItem();
if (!GetValue(IsReadOnlyTextProperty)->ToBool())
{
SetText(selItem->ToString());
Update(true);
}
}
void ButtonSplit::OnDropDownClosed(DropDownButtonSplitEventArgs* e)
{
if (DropDownClosed)
{
DropDownClosed(this, e);
}
Focus();
}
void ButtonSplit::OnDropDownOpened(DropDownButtonSplitEventArgs* e)
{
if (DropDownOpened)
{
DropDownOpened(this, e);
}
}
void ButtonSplit::OnPreviewMouseLeftButtonDown(MouseButtonEventArgs* e)
{
Selector::OnPreviewMouseLeftButtonDown(e);
}
void ButtonSplit::OnMouseLeftButtonUp(MouseButtonEventArgs* e)
{
Selector::OnMouseLeftButtonUp(e);
e->Set_Handled(true);
InvalidateVisual();
}
void ButtonSplit::OnPreviewMouseMove(MouseButtonEventArgs* e)
{
if (MouseDevice::GetLeftButton() == MousePress)
{
}
}
void ButtonSplit::OnPreApplyTemplate()
{
}
ButtonSplitItem::ButtonSplitItem()
{
}
ButtonSplitItem::~ButtonSplitItem()
{
}
void ButtonSplitItem::StaticInit()
{
static bool s_init = false;
if (!s_init)
{
s_init = true;
IsMouseOverProperty->OverrideMetadata(InfoType(), DependencyPropertyMemory::GetPropMeta(Boolean::False, AffectsNone, &OnVisualStatePropChanged));
}
}
void ButtonSplitItem::OnPreInvalidateResourceReference(bool onlySelf)
{
UpdateLayout(); //Sẽ dùng vì có thể có các int về kích thước nên cập nhập luôn giao diện đối tượng để đảm bảo các int có thể thực hiện chính xác thay về cơ bản
//InvalidateForce();
}
}
#pragma once
#ifndef _ButtonSplit_H_
#define _ButtonSplit_H_
#include <Controls/ContainerSlide/ISliderItem.h>
#include <Controls/TooltipEx/TooltipExForUI.h>
#include <Extend/Controls/ListBoxItem.h>
#include <Framework/Controls/Button.h>
#include <Framework/Controls/Popup.h>
#include <Framework/Controls/Selector.h>
#include <Framework/Controls/Svg.h>
#include <Framework/Controls/TextEditor.h>
namespace Controls
{
class ButtonSplitItem;
class ButtonSplitEventArgs : public RoutedEventArgs
{
public:
ButtonSplitEventArgs(bool isNormalClick, ButtonSplitItem* sender)
{
_isNormalClick = isNormalClick;
_sender = sender;
}
bool GetIsNormalClick() const
{
return _isNormalClick;
}
ButtonSplitItem* GetSender() const
{
return _sender;
}
private:
bool _isNormalClick;
ButtonSplitItem* _sender;
};
class DropDownButtonSplitEventArgs : public EventArgs
{
public:
DropDownButtonSplitEventArgs(PopupPtr popup);
PopupPtr GetPopup() const;
protected:
PopupPtr _popup;
};
class ButtonSplit : public Selector, public TooltipExForUI, public ISliderItem
{
public:
EventHandler DropDownClosed;
EventHandler DropDownOpened;
static RoutedEvent* ClickEvent;
static DependencyProperty* BorderBrushDropDownProperty;
static DependencyProperty* TextProperty;
static DependencyProperty* IsReadOnlyTextProperty; //cho phép change text khi change click hay không
static DependencyProperty* AutoHeightPopupProperty;
static DependencyProperty* IsDropDownOpenProperty;
static DependencyProperty* MaxDropDownHeightProperty;
static DependencyProperty* SelectionBoxItemProperty;
static DependencyProperty* SelectionBoxItemTemplateProperty;
static DependencyProperty* TooltipEx;
static DependencyProperty* TooltipPostion;
static DependencyProperty* TooltipHotkeyIndex;
static void OnTextPropChanged(DependencyObject* d, DependencyPropertyChangedEventArgs* e);
static void OnIsDropDownOpenChanged(DependencyObject* d, DependencyPropertyChangedEventArgs* e);
static void StaticInit();
TypeOfClass(ButtonSplit)
ButtonSplit();
virtual ~ButtonSplit();
void Dispose() override;
int FindIndex(const String& text) const;
int FindIndex(Object* item) const;
bool IsDropDownOpen();
void SetIsDropDownOpen(bool val);
void SetDropDownHeight(int height);
int GetDropDownHeight();
void SelectItemByName(const String& name) override;
Object* GetSelectionBoxItem();
void SetSelectionBoxItemTemplate(DataTemplate* temp);
DataTemplate* GetSelectionBoxItemTemplate();
__declspec(property (get = GetText, put = SetText)) String Text;
String GetText();
void SetText(const String& text);
bool StaysOpenOnEdit() const;
protected:
bool IsItemItsOwnContainer(Object* item) override;
UIElement* GetContainerForItemOverride() override;
void OnSelectionChanged(SelectionChangedEventArgs* e) override;
void OnPreInvalidateResourceReference(bool onlySelf) override;
void OnKeyDown(KeyEventArgs* e) override;
void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs* e) override;
void OnMouseLeftButtonUp(MouseButtonEventArgs* e) override;
static void OnPreviewMouseMove(MouseButtonEventArgs* e);
bool OnMessageFilter(Object* sender, MessageParam* mp, bool& interrupt);
virtual void OnDropDownClosed(DropDownButtonSplitEventArgs* e);
virtual void OnDropDownOpened(DropDownButtonSplitEventArgs* e);
void OnPreApplyTemplate() override;
void OnApplyTemplate() override;
void Update(bool bFocus);
bool BlockRouteEvent() override;
void SetSelectionBoxItem(Object* temp);
friend class ButtonSplitItem;
Popup* _dropDownPopup;
Button* _selectButton;
private:
void OnClick(ButtonSplitItem* selItem);
void PART_ButtonClick(DependencyObject* d, RoutedEventArgs* e);
void OnPopupOpened(Object* sender, EventArgs* e);
void OnPopupClosed(Object* sender, EventArgs* e);
void OnPopupOpening(Object* sender, EventArgs* e);
void OnPopupClosing(Object* sender, EventArgs* e);
bool _isChangeTheme; //block event, override Mouse Event when change theme InvalidateResourceReference
protected:
void OnPostInvalidateResourceReference(bool onlySelf) override;
void OnIsEnabledChanged(IsEnabledChangedEventArgs* e) override;
void OnMouseEnter(MouseEventArgs* e) override;
void OnMouseLeave(MouseEventArgs* e) override;
void OnMouseMove(MouseEventArgs* e) override;
void OnMouseDown(MouseButtonEventArgs* e) override;
void OnMouseUp(MouseButtonEventArgs* e) override;
void OnMouseWheel(MouseWheelEventArgs* e) override;
};
typedef shared<ButtonSplit> ButtonSplitPtr;
inline int ButtonSplit::GetDropDownHeight()
{
return GetValue(MaxDropDownHeightProperty)->ToInt();
}
inline void ButtonSplit::SetSelectionBoxItem(Object* item)
{
SetValue(SelectionBoxItemProperty, item);
}
inline Object* ButtonSplit::GetSelectionBoxItem()
{
return GetValue(SelectionBoxItemProperty);
}
inline void ButtonSplit::SetSelectionBoxItemTemplate(DataTemplate* temp)
{
SetValue(SelectionBoxItemTemplateProperty, temp);
}
inline DataTemplate* ButtonSplit::GetSelectionBoxItemTemplate()
{
return TypeCast<DataTemplate>(GetValue(SelectionBoxItemTemplateProperty));
}
class ButtonSplitItem : public ListBoxItem
{
public:
ButtonSplitItem();
virtual ~ButtonSplitItem();
TypeOfClass(ButtonSplitItem)
static void StaticInit();
protected:
void OnMouseMove(MouseEventArgs* e) override;
void OnMouseLeftButtonUp(MouseButtonEventArgs* e) override;
void OnPreInvalidateResourceReference(bool onlySelf) override;
friend class ButtonSplit;
};
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment