alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2ODisplayEngineLocalMetroDxe/UiLib/UiControl.c

1584 lines
45 KiB
C

/** @file
UI Common Controls
;******************************************************************************
;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "UiControls.h"
HBITMAP mDummyBitmap = NULL; //Dummy module variable used for klocwork misjudgement
STATIC
UI_CONTROL **
GetOrderedItemsByZIndex (
IN UI_CONTROL *This
)
{
UINTN Index;
UINTN CheckIndex;
INT32 ParentZIndex;
INT32 ZIndex;
UI_CONTROL *Control;
UI_CONTROL **OrderedItems;
if (This == NULL || This->Items == NULL || This->ItemCount < 2) {
return NULL;
}
//
// If all items are the same z-index value, no need to allocate memory to return ordered items.
//
for (Index = 1; Index < This->ItemCount; Index++) {
if (This->Items[Index]->ZIndex.Type != This->Items[0]->ZIndex.Type ||
This->Items[Index]->ZIndex.Value != This->Items[0]->ZIndex.Value) {
break;
}
}
if (Index == This->ItemCount) {
return NULL;
}
OrderedItems = AllocateCopyPool (This->ItemCount * sizeof(UI_CONTROL *), This->Items);
if (OrderedItems == NULL) {
return NULL;
}
//
// Get parent z-index value if need.
//
ParentZIndex = 0;
for (Index = 0; Index < This->ItemCount; Index++) {
if (This->Items[Index]->ZIndex.Type != UI_Z_INDEX_TYPE_AUTO) {
continue;
}
for (Control = This; Control != NULL; Control = CONTROL_CLASS_GET_PARENT(Control)) {
if (Control->ZIndex.Type == UI_Z_INDEX_TYPE_NUMBER) {
ParentZIndex = Control->ZIndex.Value;
break;
}
}
break;
}
for (Index = 0; Index < This->ItemCount - 1; Index++) {
Control = OrderedItems[Index];
ZIndex = (Control->ZIndex.Type == UI_Z_INDEX_TYPE_AUTO) ? ParentZIndex : Control->ZIndex.Value;
for (CheckIndex = Index + 1; CheckIndex < This->ItemCount; CheckIndex++) {
if ((OrderedItems[CheckIndex]->ZIndex.Type == UI_Z_INDEX_TYPE_NUMBER && OrderedItems[CheckIndex]->ZIndex.Value < ZIndex) ||
(OrderedItems[CheckIndex]->ZIndex.Type == UI_Z_INDEX_TYPE_AUTO && ParentZIndex < ZIndex)) {
OrderedItems[Index] = OrderedItems[CheckIndex];
OrderedItems[CheckIndex] = Control;
Control = OrderedItems[Index];
ZIndex = (Control->ZIndex.Type == UI_Z_INDEX_TYPE_AUTO) ? ParentZIndex : Control->ZIndex.Value;
}
}
}
return OrderedItems;
}
STATIC
VOID
StrToUiLength (
IN OUT CHAR16 **ValueStr,
OUT UI_LENGTH *UiLength
)
{
UiLength->Type = UI_LENGTH_TYPE_PIXEL;
UiLength->Value = wcstol (*ValueStr, ValueStr, 10);
if ((*ValueStr)[0] == '%') {
(*ValueStr) += 1;
UiLength->Type = UI_LENGTH_TYPE_PERCENTAGE;
} else if (StrnCmp (*ValueStr, L"px", 2) == 0) {
(*ValueStr) += 2;
UiLength->Type = UI_LENGTH_TYPE_PIXEL;
} else if (StrnCmp (*ValueStr, L"em", 2) == 0) {
(*ValueStr) += 2;
UiLength->Type = UI_LENGTH_TYPE_EM;
}
if ((*ValueStr)[0] == ',' || (*ValueStr)[0] == '|') {
(*ValueStr) += 1;
}
}
VOID
UiControlOnUiCreate (
UI_CONTROL *Control,
HWND Wnd,
UI_MANAGER *Manager
)
{
UI_CONTROL *This;
This = (UI_CONTROL *) Control;
This->Wnd = Wnd;
if (Manager != NULL) {
This->Manager = Manager;
}
This = (UI_CONTROL *) Control;
//
// original container
//
This->ItemCount = 0;
This->Items = NULL;
This->ChildPadding = 0;
This->HScrollBar = NULL;
This->VScrollBar = NULL;
This->ScrollPos.x = 0;
This->ScrollPos.y = 0;
This->TouchSlop = 4;
This->IsBeginDraged = FALSE;
This->Dragged = FALSE;
This->BkImageStyle = 0;
This->Filter = 0;
This->TextColor = 0;
This->UserData = NULL;
This->Name = L"";
This->BkColor = 0x00000000;
This->FocusBkColor = 0x00000000;
This->BorderColor = 0;
This->Float = FALSE;
This->GradientVertial = TRUE;
This->NeedUpdateChildPos = TRUE;
This->TabOrder = (UINT32)(-2);
This->Position = UI_POSITION_RELATIVE;
This->ZIndex.Type = UI_Z_INDEX_TYPE_AUTO;
This->ZIndex.Value = 0;
This->BoxSizing = UI_BOX_SIZING_CONTENT_BOX;
SetRectEmpty (&This->Scale9Grid);
//
// no focus
//
SetWindowLongPtr (
This->Wnd,
GWL_EXSTYLE,
GetWindowLongPtr (This->Wnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE
);
SetWindowLongPtr (
This->Wnd,
GWL_EXSTYLE,
GetWindowLongPtr (This->Wnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT
);
}
VOID
UiControlOnDestroy (
UI_CONTROL *Control
)
{
UI_CONTROL *This;
This = (UI_CONTROL *) Control;
/*
if (This->Wnd != This->Manager->MainWnd &&
This->Wnd != This->Manager->Root) {
Parent = ((UI_CONTAINER *)GetUiControl(GetParent (This->Wnd)));
Parent->Remove (Parent, This);
} */
ASSERT (This);
ASSERT (This->Name);
if (StrCmp (This->Name, L"") != 0) {
StringMapRemove (&This->Manager->NameList, This->Name);
FreePool (This->Name);
}
if (This->UserData != NULL) {
FreePool (This->UserData);
}
if (This->BkImage != NULL) {
FreePool (This->BkImage);
}
if (This->BkImageBuf.Bitmap != NULL) {
FreePool (This->BkImageBuf.Bitmap);
}
if (This->HScrollBar != NULL) {
DestroyWindow (((UI_CONTROL *)(This->HScrollBar))->Wnd);
}
if (This->VScrollBar != NULL) {
DestroyWindow (((UI_CONTROL *)(This->VScrollBar))->Wnd);
}
CONTROL_CLASS (This)->RemoveAllChild (This);
FreePool (This);
}
VOID
UiControlSetPosition (
UI_CONTROL *Control,
CONST RECT *Pos
)
{
RECT Rc;
UINTN Index;
UI_CONTROL *Item;
RECT ItemRc;
UI_CONTROL *This;
SIZE Size;
SIZE Available;
POINT LeftTop;
This = (UI_CONTROL *) Control;
ASSERT (Pos->left <= Pos->right);
ASSERT (Pos->top <= Pos->bottom);
ShowSetPositionDbgInfo (Control, Pos);
GetWindowRect(Control->Wnd, &Rc);
MapWindowPoints(HWND_DESKTOP, GetParent(Control->Wnd), (LPPOINT) &Rc, 2);
if (!EqualRect (&Rc, Pos)) {
MoveWindow (Control->Wnd, Pos->left, Pos->top, Pos->right - Pos->left, Pos->bottom - Pos->top, TRUE);
CONTROL_CLASS_INVALIDATE (This);
This->NeedUpdateChildPos = TRUE;
}
if (This->ItemCount == 0) {
return ;
}
if (!This->NeedUpdateChildPos) {
return ;
}
This->NeedUpdateChildPos = FALSE;
CopyRect (&Rc, Pos);
OffsetRect (&Rc, -Rc.left, -Rc.top);
Rc.left += (GetControlPaddingLeft (This) + GetControlBorderLeft (This) );
Rc.top += (GetControlPaddingTop (This) + GetControlBorderTop (This) );
Rc.right -= (GetControlPaddingRight (This) + GetControlBorderRight (This) );
Rc.bottom -= (GetControlPaddingBottom (This) + GetControlBorderBottom (This));
if (Rc.left > Rc.right) {
Rc.left = Rc.right;
}
if (Rc.top > Rc.bottom) {
Rc.top = Rc.bottom;
}
Available.cx = Rc.right - Rc.left;
Available.cy = Rc.bottom - Rc.top;
for (Index = 0; Index < This->ItemCount; Index++) {
Item = This->Items[Index];
if ((GetWindowLongPtr (Item->Wnd, GWL_STYLE) & WS_VISIBLE) == 0) {
continue;
}
Item->Available = Available;
Size = CONTROL_CLASS (Item)->EstimateSize (Item, Available);
if (Size.cx == 0 || Size.cx == MATCH_PARENT) {
Size.cx = Rc.right - Rc.left;
}
if (Size.cy == 0 || Size.cy == MATCH_PARENT) {
Size.cy = Rc.bottom - Rc.top;
}
LeftTop = CalculateControlDisplayXY (Item, &Size, &Available);
LeftTop.x += Rc.left;
LeftTop.y += Rc.top;
SetRect (
&ItemRc,
LeftTop.x,
LeftTop.y,
LeftTop.x + Size.cx,
LeftTop.y + Size.cy
);
mSetPositionLevel++;
CONTROL_CLASS (Item)->SetPosition (Item, &ItemRc);
mSetPositionLevel--;
}
}
VOID
UiControlOnUiPaint (
UI_CONTROL *Control,
WPARAM WParam,
LPARAM LParam
)
{
COLORREF Color;
RECT Rc;
HDC Hdc;
UI_MANAGER *Manager;
HWND Wnd;
RECT ClipRc;
HRGN OldRgn;
HRGN NewRgn;
UINTN Index;
UI_CONTROL *This;
UI_CONTROL *Item;
RECT TmpRc;
RECT ItemRc;
UI_CONTROL **OrderedItems;
SIZE Size;
This = (UI_CONTROL *) Control;
Manager = Control->Manager;
Hdc = Control->Manager->PaintDC;
Manager->GetControlRect (Manager, Control, &Rc);
Wnd = Control->Wnd;
switch (WParam) {
case PAINT_ALL:
CONTROL_CLASS_SET_STATE(Control, 0, UISTATE_INVALIDATED);
Manager->GetControlRect (Manager, This, &Rc);
if (!IntersectRect (&TmpRc, &Rc, (RECT *)LParam)) {
return ;
}
SendMessage (Wnd, UI_NOTIFY_PAINT, PAINT_BKCOLOR, LParam);
SendMessage (Wnd, UI_NOTIFY_PAINT, PAINT_BKIMAGE, LParam);
SendMessage (Wnd, UI_NOTIFY_PAINT, PAINT_STATUSIMAGE, LParam);
SendMessage (Wnd, UI_NOTIFY_PAINT, PAINT_TEXT, LParam);
SendMessage (Wnd, UI_NOTIFY_PAINT, PAINT_BORDER, LParam);
GetClipBox (Manager->PaintDC, &ClipRc);
OldRgn = CreateRectRgnIndirect (&ClipRc);
NewRgn = CreateRectRgnIndirect (&TmpRc);
ExtSelectClipRgn (Manager->PaintDC, NewRgn, RGN_AND);
OrderedItems = GetOrderedItemsByZIndex (This);
if (OrderedItems == NULL) {
OrderedItems = This->Items;
}
for (Index = 0; Index < This->ItemCount; Index++) {
Item = OrderedItems[Index];
if (!IsWindowVisible (Item->Wnd)) {
continue;
}
Manager->GetControlRect (Manager, Item, &ItemRc);
if (IntersectRect (&TmpRc, &ItemRc, (RECT *)LParam)) {
SendMessage (Item->Wnd, UI_NOTIFY_PAINT, PAINT_ALL, (LPARAM)&TmpRc);
}
}
if (OrderedItems != NULL && OrderedItems != This->Items) {
FreePool (OrderedItems);
}
if (This->HScrollBar != NULL) {
Manager->GetControlRect (Manager, (UI_CONTROL *)This->HScrollBar, &ItemRc);
if (IntersectRect (&TmpRc, &ItemRc, (RECT *)LParam)) {
SendMessage (This->HScrollBar->Control.Wnd, UI_NOTIFY_PAINT, PAINT_ALL, (LPARAM)&TmpRc);
}
}
if (This->VScrollBar != NULL) {
Manager->GetControlRect (Manager, (UI_CONTROL *)This->VScrollBar, &ItemRc);
if (IntersectRect (&TmpRc, &ItemRc, (RECT *)LParam)) {
SendMessage (This->VScrollBar->Control.Wnd, UI_NOTIFY_PAINT, PAINT_ALL, (LPARAM)&TmpRc);
}
}
SelectClipRgn(Manager->PaintDC, OldRgn);
if (OldRgn != NULL) {
DeleteObject(OldRgn);
}
if (NewRgn != NULL) {
DeleteObject(NewRgn);
}
break;
case PAINT_BKIMAGE:
if (Control->BkImage != 0) {
ASSERT (Rc.right > Rc.left && Rc.bottom > Rc.top);
if (Control->Border.Left.Value > 0) {Rc.left += GetControlBorderLeft (This); }
if (Control->Border.Top.Value > 0) {Rc.top += GetControlBorderTop (This); }
if (Control->Border.Right.Value > 0) {Rc.right -= GetControlBorderRight (This); }
if (Control->Border.Bottom.Value > 0) {Rc.bottom -= GetControlBorderBottom (This);}
if (IS_UI_LENGTH_VALUE_ASSIGNED(This->BkImageSize.Width)) {
Size.cx = UiLengthToPixel (&This->BkImageSize.Width , Rc.right - Rc.left, GetControlFontSize (This));
if (IS_UI_LENGTH_VALUE_ASSIGNED(This->BkImageSize.Height)) {
Size.cy = UiLengthToPixel (&This->BkImageSize.Height , Rc.bottom - Rc.top, GetControlFontSize (This));
} else {
Size.cy = ((Rc.bottom - Rc.top) * Size.cx) / (Rc.right - Rc.left);
}
} else {
if (IS_UI_LENGTH_VALUE_ASSIGNED(This->BkImageSize.Height)) {
Size.cy = UiLengthToPixel (&This->BkImageSize.Height , Rc.bottom - Rc.top, GetControlFontSize (This));
Size.cx = ((Rc.right - Rc.left) * Size.cy) / (Rc.bottom - Rc.top);
} else {
Size.cy = (Rc.bottom - Rc.top);
Size.cx = (Rc.right - Rc.left);
}
}
Rc.right = Rc.left + Size.cx;
Rc.bottom = Rc.top + Size.cy;
UiShowBitmap (
Control->Wnd,
Manager->PaintDC,
&Rc,
&Control->Scale9Grid,
Control->BkImageBuf.Bitmap != NULL ? &Control->BkImageBuf : GetImageByString (Control->BkImage),
GetControlBkImageStyle (Control),
&Control->HsvDiff
);
}
break;
case PAINT_BKCOLOR:
if ((CONTROL_CLASS_GET_STATE(Control) & UISTATE_FOCUSED) != 0 && Control->FocusBkColor != 0) {
Color = Control->FocusBkColor;
} else {
Color = Control->BkColor;
}
if (Color != 0) {
if (Control->Border.Left.Value > 0) {Rc.left += GetControlBorderLeft (This); }
if (Control->Border.Top.Value > 0) {Rc.top += GetControlBorderTop (This); }
if (Control->Border.Right.Value > 0) {Rc.right -= GetControlBorderRight (This); }
if (Control->Border.Bottom.Value > 0) {Rc.bottom -= GetControlBorderBottom (This);}
if (Color >= 0xFF000000) {
UiFastFillRect (Hdc, &Rc, Color);
} else {
HDC hdcMem;
HBITMAP hbmp, hbmpOrg, hbmpDel;
RECT rc;
GetClientRect (Control->Wnd, &rc);
rc.right -= (GetControlBorderWidth (Control));
rc.bottom -= (GetControlBorderHeight (Control));
/* redirect painting to offscreen dc*/
hdcMem = CreateCompatibleDC(Hdc);
if (hdcMem != NULL) {
mDummyBitmap = CreateCompatibleBitmap(hdcMem, rc.right, rc.bottom);
hbmp = mDummyBitmap;
hbmpOrg = SelectObject(hdcMem, hbmp);
UiFastFillRect (hdcMem, &rc, Color);
/* alpha blend blit offscreen map with physical screen*/
BitBlt(Hdc, Rc.left, Rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMem, 0, 0, MWROP_SRC_OVER); /* FIXME specify constant alpha somewhere!*/
hbmpDel = SelectObject(hdcMem, hbmpOrg);
if (hbmpDel != NULL) {
DeleteObject(hbmpDel);
}
DeleteDC(hdcMem);
}
}
}
break;
case PAINT_STATUSIMAGE:
break;
case PAINT_TEXT:
break;
case PAINT_BORDER:
if (0) {
Color = Control->BorderColor;
if (CONTROL_CLASS_GET_STATE(Control) & UISTATE_FOCUSED) {
Color = 0xFFFF0000;
}
if (Color != 0) {
SelectObject (Hdc, GetStockObject (PS_NULL));
SelectObject (Hdc, GetStockObject (DC_PEN));
SetDCPenColor (Hdc, Color);
Rectangle (Hdc, Rc.left, Rc.top, Rc.right, Rc.bottom);
}
if (CONTROL_CLASS_GET_STATE(Control) & UISTATE_FOCUSED) {
Rectangle (Hdc, Rc.left + 1, Rc.top + 1, Rc.right - 1, Rc.bottom - 1);
}
}
Color = Control->BorderColor;
if (GetControlBorderLeft (Control) > 0) {
CopyRect (&TmpRc, &Rc);
TmpRc.right = TmpRc.left + GetControlBorderLeft (Control);
UiFastFillRect (Hdc, &TmpRc, Color);
}
if (GetControlBorderRight (Control) > 0) {
CopyRect (&TmpRc, &Rc);
TmpRc.left = TmpRc.right - GetControlBorderRight (Control);
UiFastFillRect (Hdc, &TmpRc, Color);
}
if (GetControlBorderTop (Control) > 0) {
CopyRect (&TmpRc, &Rc);
TmpRc.bottom = TmpRc.top + GetControlBorderTop (Control);
UiFastFillRect (Hdc, &TmpRc, Color);
}
if (GetControlBorderBottom (Control) > 0) {
CopyRect (&TmpRc, &Rc);
TmpRc.top = TmpRc.bottom - GetControlBorderBottom (Control);
UiFastFillRect (Hdc, &TmpRc, Color);
}
break;
default:
ASSERT (FALSE);
break;
}
}
UI_STATE
EFIAPI
UiControlGetState (
UI_CONTROL *Control
)
{
return Control->StateFlags;
}
VOID
EFIAPI
UiControlSetState (
UI_CONTROL *Control,
UI_STATE SetState,
UI_STATE ClearState
)
{
UI_STATE OldState;
if (Control->OnSetState) {
Control->OnSetState (Control, SetState, ClearState);
}
OldState = Control->StateFlags;
Control->StateFlags |= SetState;
Control->StateFlags &= ~(ClearState);
if ((Control->StateFlags != OldState) &&
!(ClearState & UISTATE_INVALIDATED) &&
!(Control->StateFlags & UISTATE_INVALIDATED)) {
CONTROL_CLASS_INVALIDATE (Control);
}
}
BOOLEAN
UiControlSetAttribute (
UI_CONTROL *Control,
CHAR16 *Name,
CHAR16 *Value
)
{
EFI_STATUS Status;
CHAR16 *PtrValue;
UI_CONTROL *ScrollBar;
UI_CONTROL *This;
This = (UI_CONTROL *) Control;
PtrValue = Value;
if (StrCmp (Name, L"name") == 0) {
ASSERT (This->Name);
if (StrCmp(This->Name, L"") != 0) {
StringMapRemove (&This->Manager->NameList, Value);
FreePool (This->Name);
}
This->Name = AllocateCopyPool (StrSize(Value), Value);
StringMapAdd (&This->Manager->NameList, Value, This);
} else if (StrCmp (Name, L"width") == 0) {
if (isalpha (Value[0]) || StrCmp (Value, L"-1") == 0 || StrCmp (Value, L"-2") == 0) {
if (StrCmp (Value, L"match_parent") == 0 || StrCmp (Value, L"-1") == 0) {
This->Width.Type = UI_LENGTH_TYPE_MATCH_PARENT;
This->Width.Value = 0;
} else if (StrCmp (Value, L"wrap_content") == 0 || StrCmp (Value, L"-2") == 0) {
This->Width.Type = UI_LENGTH_TYPE_WRAP_CONTENT;
This->Width.Value = 0;
} else {
DEBUG ((EFI_D_ERROR, "width can only use match_parent, wrap_content or const value"));
ASSERT (FALSE);
}
} else {
StrToUiLength (&PtrValue, &This->Width);
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"height") == 0) {
if (isalpha (Value[0]) || StrCmp (Value, L"-1") == 0 || StrCmp (Value, L"-2") == 0) {
if (StrCmp (Value, L"match_parent") == 0 || StrCmp (Value, L"-1") == 0) {
This->Height.Type = UI_LENGTH_TYPE_MATCH_PARENT;
This->Height.Value = 0;
} else if (StrCmp (Value, L"wrap_content") == 0 || StrCmp (Value, L"-2") == 0) {
This->Height.Type = UI_LENGTH_TYPE_WRAP_CONTENT;
This->Height.Value = 0;
} else {
DEBUG ((EFI_D_ERROR, "width can only use match_parent, wrap_content or const value"));
ASSERT (FALSE);
}
} else {
StrToUiLength (&PtrValue, &This->Height);
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"background-image") == 0) {
if (This->BkImage != NULL) {
FreePool (This->BkImage);
}
if (This->BkImageBuf.Bitmap != NULL) {
FreePool (This->BkImageBuf.Bitmap);
}
This->BkImage = AllocateCopyPool (StrSize(Value), Value);
if (This->BkImage == NULL) {
DEBUG ((EFI_D_ERROR, "Allocate This->BkImage fail."));
return TRUE;
}
if (Value[0] != '@') {
EFI_IMAGE_INPUT *Image;
Image = GetImageByString (This->BkImage);
if (Image != NULL && Image->Width != 0 && Image->Height != 0) {
CopyMem (&This->BkImageBuf, Image, sizeof(EFI_IMAGE_INPUT));
This->BkImageBuf.Bitmap = AllocateCopyPool (Image->Width * Image->Height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL), Image->Bitmap);
}
}
} else if (StrCmp (Name, L"background-size") == 0) {
if (isalpha (PtrValue[0])) {
if (StrnCmp (PtrValue, L"auto", 4) == 0) {
This->BkImageSize.Width.Value = 0;
This->BkImageSize.Width.Type = UI_LENGTH_TYPE_UNDEFINED;
PtrValue += 4;
} else {
DEBUG ((EFI_D_ERROR, "background-size can only use auto or const value"));
ASSERT (FALSE);
}
if (*PtrValue == ',') {
PtrValue++;
}
} else {
StrToUiLength (&PtrValue, &This->BkImageSize.Width);
}
if (*PtrValue == 0 || isalpha (PtrValue[0])) {
if (*PtrValue == 0 || StrnCmp (PtrValue, L"auto", 4) == 0) {
This->BkImageSize.Height.Value = 0;
This->BkImageSize.Height.Type = UI_LENGTH_TYPE_UNDEFINED;
} else {
DEBUG ((EFI_D_ERROR, "background-size can only use auto or const value"));
ASSERT (FALSE);
}
} else {
StrToUiLength (&PtrValue, &This->BkImageSize.Height);
}
} else if (StrCmp (Name, L"background-color") == 0) {
This->BkColor = GetColorValue (Value);
} else if (StrCmp (Name, L"focusbkcolor") == 0) {
This->FocusBkColor = GetColorValue (Value);
} else if (StrCmp (Name, L"border-color") == 0) {
This->BorderColor = GetColorValue (Value);
} else if (StrCmp (Name, L"visibility") == 0) {
if (StrCmp (Value, L"true") == 0) {
ShowWindow (This->Wnd, SW_SHOW);
} else {
ShowWindow (This->Wnd, SW_HIDE);
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"font-size") == 0) {
Control->FontSize = (INT32)StrToUInt (Value, 10, &Status);
} else if (StrCmp (Name, L"textcolor") == 0) {
Control->TextColor = GetColorValue (Value);
} else if (StrnCmp (Name, L"padding", 7) == 0) {
Name += 7;
if (*Name == 0) {
StrToUiLength (&PtrValue, &This->Padding.Top);
StrToUiLength (&PtrValue, &This->Padding.Right);
StrToUiLength (&PtrValue, &This->Padding.Bottom);
StrToUiLength (&PtrValue, &This->Padding.Left);
} else if (StrCmp (Name, L"-top") == 0) {
StrToUiLength (&PtrValue, &This->Padding.Top);
} else if (StrCmp (Name, L"-right") == 0) {
StrToUiLength (&PtrValue, &This->Padding.Right);
} else if (StrCmp (Name, L"-bottom") == 0) {
StrToUiLength (&PtrValue, &This->Padding.Bottom);
} else if (StrCmp (Name, L"-left") == 0) {
StrToUiLength (&PtrValue, &This->Padding.Left);
} else {
ASSERT (FALSE);
}
UiNeedUpdatePos (Control);
} else if (StrnCmp (Name, L"border", 6) == 0) {
Name += 6;
if (StrCmp (Name, L"-width") == 0) {
StrToUiLength (&PtrValue, &This->Border.Top);
StrToUiLength (&PtrValue, &This->Border.Right);
StrToUiLength (&PtrValue, &This->Border.Bottom);
StrToUiLength (&PtrValue, &This->Border.Left);
} else if (StrCmp (Name, L"-top") == 0) {
StrToUiLength (&PtrValue, &This->Border.Top);
} else if (StrCmp (Name, L"-right") == 0) {
StrToUiLength (&PtrValue, &This->Border.Right);
} else if (StrCmp (Name, L"-bottom") == 0) {
StrToUiLength (&PtrValue, &This->Border.Bottom);
} else if (StrCmp (Name, L"-left") == 0) {
StrToUiLength (&PtrValue, &This->Border.Left);
} else {
ASSERT (FALSE);
}
UiNeedUpdatePos (Control);
} else if (StrnCmp (Name, L"margin", 6) == 0) {
Name += 6;
if (*Name == 0) {
StrToUiLength (&PtrValue, &This->Margin.Top);
StrToUiLength (&PtrValue, &This->Margin.Right);
StrToUiLength (&PtrValue, &This->Margin.Bottom);
StrToUiLength (&PtrValue, &This->Margin.Left);
} else if (StrCmp (Name, L"-top") == 0) {
StrToUiLength (&PtrValue, &This->Margin.Top);
} else if (StrCmp (Name, L"-right") == 0) {
StrToUiLength (&PtrValue, &This->Margin.Right);
} else if (StrCmp (Name, L"-bottom") == 0) {
StrToUiLength (&PtrValue, &This->Margin.Bottom);
} else if (StrCmp (Name, L"-left") == 0) {
StrToUiLength (&PtrValue, &This->Margin.Left);
} else {
ASSERT (FALSE);
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"left") == 0) {
StrToUiLength (&PtrValue, &Control->Left);
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"right") == 0) {
StrToUiLength (&PtrValue, &Control->Right);
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"top") == 0) {
StrToUiLength (&PtrValue, &Control->Top);
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"bottom") == 0) {
StrToUiLength (&PtrValue, &Control->Bottom);
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"scale9grid") == 0) {
This->Scale9Grid.left = wcstol (Value, &PtrValue, 10);
This->Scale9Grid.top = wcstol (PtrValue + 1, &PtrValue, 10);
This->Scale9Grid.right = wcstol (PtrValue + 1, &PtrValue, 10);
This->Scale9Grid.bottom = wcstol (PtrValue + 1, &PtrValue, 10);
} else if (StrCmp (Name, L"float") == 0) {
if (StrCmp (Value, L"true") == 0) {
This->Float = TRUE;
} else {
This->Float = FALSE;
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"gradient_vertical") == 0) {
if (StrCmp (Value, L"true") == 0) {
This->GradientVertial = TRUE;
} else {
This->GradientVertial = FALSE;
}
} else if (StrCmp (Name, L"user_data") == 0) {
if (This->UserData != NULL) {
FreePool (This->UserData);
}
This->UserData = AllocateCopyPool (StrSize (Value), Value);
} else if (StrCmp (Name, L"background-image-style") == 0) {
This->BkImageStyle = 0;
if (StrStr (Value, L"center") != NULL) {
This->BkImageStyle &= ~ (DT_STRETCH);
This->BkImageStyle |= DT_CENTER | DT_VCENTER;
}
if (StrStr (Value, L"stretch") != NULL) {
SetRectEmpty (&Control->Scale9Grid);
Control->BkImageStyle &= ~ (DT_CENTER | DT_VCENTER);
Control->BkImageStyle |= DT_STRETCH;
}
if (StrStr (Value, L"gray") != NULL) {
Control->BkImageStyle |= DT_GRAY;
}
if (StrStr (Value, L"light") != NULL) {
Control->BkImageStyle |= DT_LIGHT;
}
if (StrCmp (Value, L"") == 0) {
This->BkImageStyle = 0;
}
} else if (StrCmp (Name, L"filter") == 0) {
if (StrCmp (Value, L"gray") == 0) {
Control->Filter |= DT_GRAY;
} else if (StrCmp (Value, L"none") == 0) {
Control->Filter = 0;
} else {
DEBUG ((EFI_D_ERROR, "filter can only use gray or none"));
ASSERT (FALSE);
}
} else if (StrCmp (Name, L"child-padding") == 0) {
This->ChildPadding = (UINT32)StrToUInt (Value, 10, &Status);
} else if (StrCmp (Name, L"vscrollbarpos") == 0) {
if (This->VScrollBar != NULL) {
SCROLLBAR_CLASS(This->VScrollBar)->SetScrollPos (This->VScrollBar, (INT32)StrToUInt (Value, 10, &Status));
}
} else if (StrCmp (Name, L"vscrollbar") == 0) {
if (StrCmp (Value, L"true") == 0 &&
This->VScrollBar == NULL) {
ScrollBar = CreateControl (L"SCROLLBAR", This);
ScrollBar->Class->SetAttribute (ScrollBar, L"hor", L"false");
This->VScrollBar = (UI_SCROLLBAR *) ScrollBar;
((UI_SCROLLBAR *)ScrollBar)->Owner = This;
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"hscrollbar") == 0) {
if ((StrCmp (Value, L"true") == 0) && (This->HScrollBar == NULL)) {
ScrollBar = CreateControl (L"SCROLLBAR", This);
ScrollBar->Class->SetAttribute (ScrollBar, L"hor", L"true");
This->HScrollBar = (UI_SCROLLBAR *) ScrollBar;
}
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"hsvadjust") == 0) {
This->HsvDiff.HueDiff = (INT16) wcstol (Value, &PtrValue, 10);
This->HsvDiff.SaturationDiff = (INT8) wcstol (PtrValue + 1, &PtrValue, 10);
This->HsvDiff.ValueDiff = (INT8) wcstol (PtrValue + 1, &PtrValue, 10);
} else if (StrCmp (Name, L"min-height") == 0) {
This->MinSize.cy = wcstol (Value, &PtrValue, 10);
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"max-width") == 0) {
This->MaxSize.cx = wcstol (Value, &PtrValue, 10);
UiNeedUpdatePos (Control);
} else if (StrCmp (Name, L"taborder") == 0) {
This->TabOrder = wcstol (Value, &PtrValue, 10);
} else if (StrCmp (Name, L"tabstop") == 0) {
if (StrCmp (Value, L"true") == 0) {
SetWindowLongPtr (This->Wnd, GWL_STYLE, GetWindowLongPtr (This->Wnd, GWL_STYLE) | WS_TABSTOP);
} else {
SetWindowLongPtr (This->Wnd, GWL_STYLE, GetWindowLongPtr (This->Wnd, GWL_STYLE) & (~WS_TABSTOP));
}
} else if (StrCmp (Name, L"position") == 0) {
if (StrCmp (Value, L"relative") == 0) {
This->Position = UI_POSITION_RELATIVE;
} else if (StrCmp (Value, L"absolute") == 0) {
This->Position = UI_POSITION_ABSOLUTE;
}
} else if (StrCmp (Name, L"z-index") == 0) {
if (isalpha (Value[0])) {
if (StrCmp (Value, L"auto") == 0) {
This->ZIndex.Type = UI_Z_INDEX_TYPE_AUTO;
} else {
DEBUG ((EFI_D_ERROR, "z-index can only use auto or const value"));
ASSERT (FALSE);
}
} else {
This->ZIndex.Value = wcstol (Value, &PtrValue, 10);
This->ZIndex.Type = UI_Z_INDEX_TYPE_NUMBER;
}
} else if (StrCmp (Name, L"box-sizing") == 0) {
if (StrCmp (Value, L"border-box") == 0) {
This->BoxSizing = UI_BOX_SIZING_BORDER_BOX;
} else if (StrCmp (Value, L"content-box") == 0) {
This->BoxSizing = UI_BOX_SIZING_CONTENT_BOX;
} else {
ASSERT (FALSE);
}
} else {
DEBUG ((EFI_D_ERROR, "Unsupported attribute name/name: %s %s", Name, Value));
ASSERT (0);
return FALSE;
}
CONTROL_CLASS_INVALIDATE (This);
return TRUE;
}
BOOLEAN
EFIAPI
UiControlAddChild (
UI_CONTROL *Control,
UI_CONTROL *Child
)
{
UI_CONTROL *This;
ASSERT (Control != NULL);
This = (UI_CONTROL *) Control;
This->ItemCount++;
This->Items = ReallocatePool (
sizeof (UI_CONTROL *) * (This->ItemCount - 1),
sizeof (UI_CONTROL *) * This->ItemCount,
This->Items
);
if (This->Items == NULL) {
return FALSE;
}
This->Items[This->ItemCount - 1] = Child;
UiNeedUpdatePos (Child);
return TRUE;
}
BOOLEAN
EFIAPI
UiControlRemoveChild (
UI_CONTROL *Control,
UI_CONTROL *Child
)
{
UINTN Index;
UINTN Index2;
UI_CONTROL *This;
ASSERT (Control != NULL);
This = (UI_CONTROL *) Control;
for (Index = 0; Index < This->ItemCount; Index++) {
if (This->Items[Index] == Child) {
for (Index2 = Index; Index < This->ItemCount - 1; Index2++) {
This->Items[Index2] = This->Items[Index2 + 1];
}
This->ItemCount--;
DestroyWindow (Child->Wnd);
break;
}
}
UiNeedUpdatePos (This);
return TRUE;
}
BOOLEAN
EFIAPI
UiControlRemoveAllChild (
UI_CONTROL *Control
)
{
UINTN Index;
if (Control->ItemCount == 0) {
return TRUE;
}
for (Index = 0; Index < Control->ItemCount; Index++) {
DestroyWindow (Control->Items[Index]->Wnd);
}
FreePool (Control->Items);
Control->Items = NULL;
Control->ItemCount = 0;
UiNeedUpdatePos (Control);
return TRUE;
}
UI_CONTROL *
EFIAPI
UiControlFindChildByName (
UI_CONTROL *Control,
CHAR16 *Name,
UI_SEARCH_TYPE SearchType
)
{
UINTN Index;
UI_CONTROL *This;
UI_CONTROL *Child;
This = (UI_CONTROL *) Control;
for (Index = 0; Index < This->ItemCount; Index++) {
if (StrCmp (This->Items[Index]->Name, Name) == 0) {
return This->Items[Index];
}
if (SearchType == UI_SEARCH_TYPE_ONLY_CHILD) {
continue;
}
Child = CONTROL_CLASS (This->Items[Index])->FindChildByName (This->Items[Index], Name, SearchType);
if (Child != NULL) {
return Child;
}
}
return NULL;
}
BOOLEAN
UiControlActivate (
UI_CONTROL *This
)
{
UINT32 Style;
Style = (UINT32) GetWindowLongPtr (This->Wnd, GWL_STYLE);
if ((Style & WS_DISABLED) != 0) {
return FALSE;
}
if ((Style & WS_VISIBLE) == 0) {
return FALSE;
}
return TRUE;
}
SIZE
UiControlEstimateSize (
UI_CONTROL *Control,
SIZE AvailableSize
)
{
SIZE Size;
SIZE ItemSize;
SIZE ItemAvailableSize;
UINTN Index;
UI_CONTROL *Item;
UINTN Count;
INTN MaxWidth;
INTN MaxHeight;
if (((Control->Width.Type != UI_LENGTH_TYPE_WRAP_CONTENT) && (Control->Width.Type != UI_LENGTH_TYPE_MATCH_PARENT)) &&
((Control->Height.Type != UI_LENGTH_TYPE_WRAP_CONTENT) && (Control->Height.Type != UI_LENGTH_TYPE_MATCH_PARENT))) {
return CalculateControlDisplaySize (Control, AvailableSize);
}
Count = Control->ItemCount;
ItemAvailableSize.cx = AvailableSize.cx - GetControlPaddingWidth (Control) - GetControlBorderWidth (Control);
ItemAvailableSize.cy = AvailableSize.cy - GetControlPaddingHeight (Control) - GetControlBorderHeight (Control);
MaxWidth = 0;
MaxHeight = 0;
for (Index = 0; Index < Count; ++Index) {
Item = Control->Items[Index];
if ((GetWindowLongPtr (Item->Wnd, GWL_STYLE) & WS_VISIBLE) == 0) {
continue;
}
if (Item->Float) {
continue;
}
ItemSize = CONTROL_CLASS (Item)->EstimateSize (Item, ItemAvailableSize);
MaxWidth = MAX (MaxWidth, ItemSize.cx);
MaxHeight = MAX (MaxHeight, ItemSize.cy);
}
if (MaxWidth > 0) {
MaxWidth += (GetControlPaddingWidth (Control) + GetControlBorderWidth (Control));
}
if (MaxHeight > 0) {
MaxHeight += (GetControlPaddingHeight (Control) + GetControlBorderHeight (Control));
}
MaxWidth = MAX (MaxWidth, Control->MinSize.cx);
MaxHeight = MAX (MaxHeight, Control->MinSize.cy);
Size = CalculateControlDisplaySize (Control, AvailableSize);
if (Size.cx == WRAP_CONTENT) {
Size.cx = (GDICOORD)MaxWidth;
}
if (Size.cy == WRAP_CONTENT) {
Size.cy = (GDICOORD)MaxHeight;
}
return Size;
}
VOID
UiControlInvalidate (
UI_CONTROL *Control
)
{
RECT Rc;
RECT InvalidateRc;
RECT TmpRc;
RECT ParentRc;
HWND Parent;
if (CONTROL_CLASS_GET_STATE(Control) & UISTATE_INVALIDATED) {
//
// check update region already in invalidate region
//
if (GetUpdateRect (Control->Manager->MainWnd, &InvalidateRc, FALSE)) {
GetWindowRect (Control->Wnd, &Rc);
MapWindowPoints(NULL, Control->Manager->MainWnd, (POINT *)&Rc, 2);
if ((InvalidateRc.left <= Rc.left) && (InvalidateRc.right >= Rc.right) &&
(InvalidateRc.top <= Rc.top) && (InvalidateRc.bottom >= Rc.bottom)){
return ;
}
}
}
CONTROL_CLASS_SET_STATE(Control, UISTATE_INVALIDATED, 0);
GetWindowRect (Control->Wnd, &Rc);
Parent = Control->Wnd;
CopyRect (&InvalidateRc, &Rc);
while ((Parent = Parent->parent) != NULL) {
CopyRect (&TmpRc, &InvalidateRc);
GetWindowRect (Parent, &ParentRc);
if (!IntersectRect (&InvalidateRc, &TmpRc, &ParentRc)) {
return ;
}
if (Parent == Control->Manager->Root) {
break;
}
}
MapWindowPoints(NULL, Control->Manager->MainWnd, (POINT *)&InvalidateRc, 2);
InvalidateRect (Control->Manager->MainWnd, &InvalidateRc, FALSE);
}
UI_CONTROL*
UiControlFindNextFocus (
UI_CONTROL *Control,
UI_CONTROL *Focused,
UINTN Direction
)
{
UI_CONTROL *Root;
UINTN Index;
UI_CONTROL *Item;
RECT ItemRc;
RECT FocusRc;
UI_CONTROL *NextFocus;
UINT32 Distance;
UINT32 BestDistance;
ASSERT (Direction == VK_LEFT || Direction == VK_RIGHT || Direction == VK_UP || Direction == VK_DOWN);
if (!(GetWindowLongPtr (Control->Wnd, GWL_STYLE) & WS_CHILD)) {
return NULL;
}
Root = GetUiControl (GetParent (Control->Wnd));
if (Root == NULL) {
return NULL;
}
GetWindowRect (Focused->Wnd, &FocusRc);
//
// search next focus
//
NextFocus = NULL;
BestDistance = (UINT32)-1;
for (Index = 0; Index < Root->ItemCount; Index++) {
Item = Root->Items[Index];
if (Item == Focused) {
continue;
}
if (!IsWindowVisible (Item->Wnd)) {
continue;
}
if (GetWindowLongPtr (Item->Wnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
continue;
}
GetWindowRect (Item->Wnd, &ItemRc);
if (Direction == VK_LEFT) {
if (ItemRc.left >= FocusRc.left || ((ItemRc.bottom <= FocusRc.top || ItemRc.top >= FocusRc.bottom) && ItemRc.right >= FocusRc.left)) {
continue;
}
} else if (Direction == VK_UP) {
if (ItemRc.top >= FocusRc.top || ((ItemRc.right <= FocusRc.left || ItemRc.left >= FocusRc.right) && ItemRc.bottom >= FocusRc.top)) {
continue;
}
} else if (Direction == VK_RIGHT) {
if (ItemRc.left <= FocusRc.left || ((ItemRc.bottom <= FocusRc.top || ItemRc.top >= FocusRc.bottom) && ItemRc.left <= FocusRc.right)) {
continue;
}
} else if (Direction == VK_DOWN) {
if (ItemRc.top <= FocusRc.top || ((ItemRc.right <= FocusRc.left || ItemRc.left >= FocusRc.right) && ItemRc.top <= FocusRc.bottom)) {
continue;
}
}
Distance = (FocusRc.left - ItemRc.left) * (FocusRc.left - ItemRc.left) +
(FocusRc.top - ItemRc.top) * (FocusRc.top - ItemRc.top);
if (Distance < BestDistance) {
NextFocus = Item;
BestDistance = Distance;
}
}
return NextFocus;
}
UI_CONTROL*
UiControlGetParent (
UI_CONTROL *Control
)
{
HWND Hwnd;
UI_CONTROL *Parent;
Hwnd = GetParent (Control->Wnd);
ASSERT (Hwnd != NULL);
Parent = GetUiControl (Hwnd);
ASSERT (Parent != NULL);
return Parent;
}
BOOLEAN
UiControlShouldDelayChildPressedState (
UI_CONTROL *Control
)
{
if (Control->VScrollBar != NULL || Control->HScrollBar != NULL) {
return TRUE;
}
return FALSE;
}
BOOLEAN
UiControlIsInScrollControl (
UI_CONTROL *This
)
{
UI_CONTROL *Parent;
Parent = CONTROL_CLASS (This)->GetParent (This);
while (Parent != NULL) {
if (CONTROL_CLASS (Parent)->ShouldDelayChildPressedState (Parent)) {
return TRUE;
}
Parent = CONTROL_CLASS (Parent)->GetParent (Parent);
}
return FALSE;
}
LRESULT
UiControlProc (
HWND Wnd,
UINT32 Msg,
WPARAM WParam,
LPARAM LParam
)
{
UI_CONTROL *This;
UI_CONTROL *ParentControl;
UI_CONTROL *NextFocus;
HWND ParentWnd;
RECT Rc;
UI_MANAGER *Manager;
POINT Point;
POINT LastPoint;
INT32 DeltaX;
INT32 DeltaY;
INT32 ScrollPos;
This = NULL;
Manager = NULL;
if (Msg != WM_CREATE && Msg != WM_NCCALCSIZE) {
This = (UI_CONTROL *) GetWindowLongPtr (Wnd, 0);
if (This == NULL) {
ASSERT (FALSE);
return 0;
}
}
if (This != NULL) {
Manager = This->Manager;
}
switch (Msg) {
case WM_CREATE:
if (This == NULL) {
This = (UI_CONTROL *) AllocateZeroPool (sizeof (UI_CONTROL));
} else {
ASSERT (FALSE);
}
if (This != NULL) {
CONTROL_CLASS (This) = (UI_CONTROL_CLASS *) GetClassLongPtr (Wnd, 0);
SetWindowLongPtr (Wnd, 0, (INTN)This);
SendMessage (Wnd, UI_NOTIFY_CREATE, WParam, LParam);
}
break;
case UI_NOTIFY_CREATE:
if (LParam == 0) {
Manager = NULL;
} else {
Manager = (UI_MANAGER *)(((CREATESTRUCT *)(LParam))->lpCreateParams);
}
UiControlOnUiCreate (This, Wnd, Manager);
break;
case UI_NOTIFY_ACTIVATE:
return UiControlActivate (This);
case WM_DESTROY:
UiControlOnDestroy (This);
break;
case WM_WINDOWPOSCHANGED:
break;
case WM_PAINT:
// ValidateRect (Wnd, NULL);
break;
case WM_NCHITTEST:
return HTTRANSPARENT;
case UI_NOTIFY_PAINT:
UiControlOnUiPaint (This, WParam, LParam);
break;
case WM_KEYDOWN:
if (WParam == VK_RETURN) {
if (!IsWindowVisible (Wnd)) {
break;
}
if (!(This->StyleFlags & UISTYLE_CLICKABLE)) {
break;
}
CONTROL_CLASS_SET_STATE (This, UISTATE_PRESSED, 0);
}
//
// we didn't send WM_KEYUP, so continue process WM_KEYUP
//
//
case WM_KEYUP:
if (WParam == VK_LEFT || WParam == VK_RIGHT
|| WParam == VK_UP || WParam == VK_DOWN) {
NextFocus = This->Class->FindNextFocus (This, This, WParam);
if (NextFocus != NULL) {
SetFocus (NextFocus->Wnd);
}
break;
}
if (WParam == VK_RETURN) {
if (!IsWindowVisible (Wnd)) {
break;
}
if (!(This->StyleFlags & UISTYLE_CLICKABLE)) {
break;
}
if (!(CONTROL_CLASS_GET_STATE (This) & UISTATE_PRESSED)) {
break;
}
CONTROL_CLASS_SET_STATE(This, 0, UISTATE_PRESSED);
SendMessage (Wnd, UI_NOTIFY_ACTIVATE, 0, 0);
}
break;
case WM_LBUTTONDOWN:
if ((This->HScrollBar != NULL) || (This->VScrollBar != NULL)) {
//
// orignal Container
//
This->IsBeginDraged = TRUE;
POINTSTOPOINT(Point, LParam);
ClientToScreen (Wnd, &Point);
This->LastMotionX = Point.x;
This->LastMotionY = Point.y;
SetCapture (Wnd);
if ((GetWindowLongPtr (Wnd, GWL_STYLE) & WS_DISABLED) == 0) {
CONTROL_CLASS_SET_STATE(This, UISTATE_PRESSED | UISTATE_CAPTURED, 0);
}
} else {
POINTSTOPOINT(Point, LParam);
ClientToScreen (Wnd, &Point);
if ((GetWindowLongPtr (Wnd, GWL_STYLE) & WS_DISABLED) == 0) {
SetCapture (Wnd);
CONTROL_CLASS_SET_STATE (This, UISTATE_PRESSED | UISTATE_CAPTURED, 0);
}
if (UiControlIsInScrollControl (This)) {
CONTROL_CLASS_SET_STATE(This, UISTATE_PREPRESSED, 0);
This->LastX = Point.x;
This->LastY = Point.y;
}
}
break;
case WM_LBUTTONDBLCLK:
return SendMessage (Wnd, WM_LBUTTONDOWN, WParam, LParam);
case WM_NCMOUSEMOVE:
if (This->IsBeginDraged) {
POINTSTOPOINT(Point, LParam);
DeltaX = This->LastMotionX - Point.x;
DeltaY = This->LastMotionY - Point.y;
if (abs(DeltaY) < This->TouchSlop) {
break;
}
This->LastMotionX = Point.x;
This->LastMotionY = Point.y;
//
// now only process y
//
if (DeltaY < 0) {
if (This->ScrollPos.y <= 0) {
break;
}
} else if (DeltaY > 0) {
// DeltaY =
}
if (This->VScrollBar != NULL) {
ScrollPos = (This->ScrollPos.y + DeltaY) / This->VScrollBar->LineSize;
SCROLLBAR_CLASS(This->VScrollBar)->SetScrollPos (This->VScrollBar, ScrollPos);
This->Dragged = TRUE;
//SCROLLBAR_CLASS(This->VScrollBar)->SetScrollPos (This->VScrollBar, This->ScrollPos.y + DeltaY);
}
} else if (CONTROL_CLASS_GET_STATE (This) & UISTATE_PREPRESSED) {
POINTSTOPOINT(Point, LParam);
GetWindowRect (Wnd, &Rc);
if (!PtInRect (&Rc, Point) || abs(This->LastY - Point.y) > 10) {
//
// change capture to parent
//
CONTROL_CLASS_SET_STATE (This, 0, UISTATE_PRESSED | UISTATE_CAPTURED | UISTATE_PREPRESSED);
ParentControl = This->Class->GetParent (This);
ASSERT (ParentControl != NULL);
ParentWnd = ParentControl->Wnd;
SetCapture (ParentWnd);
LastPoint.x = This->LastX;
LastPoint.y = This->LastY;
ScreenToClient (ParentWnd, &LastPoint);
SendMessage (ParentWnd, WM_LBUTTONDOWN, 0, MAKELONG(LastPoint.x, LastPoint.y));
SendMessage (ParentWnd, WM_NCMOUSEMOVE, 0, MAKELONG(Point.x, Point.y));
}
}
break;
case WM_NCLBUTTONUP:
break;
case WM_MOUSELEAVE:
case WM_LBUTTONUP:
This->Dragged = FALSE;
if (This->IsBeginDraged) {
ReleaseCapture ();
This->IsBeginDraged = FALSE;
} else if (GetCapture () == Wnd) {
CONTROL_CLASS_SET_STATE (This, 0, UISTATE_PRESSED | UISTATE_CAPTURED | UISTATE_PREPRESSED);
ReleaseCapture ();
}
break;
case WM_SETFOCUS:
CONTROL_CLASS_SET_STATE (This, UISTATE_FOCUSED, 0);
break;
case WM_KILLFOCUS:
CONTROL_CLASS_SET_STATE (This, 0, UISTATE_FOCUSED);
break;
case WM_ERASEBKGND:
return 1;
default:
return DefWindowProc (Wnd, Msg, WParam, LParam);
}
return 0;
}
UI_CONTROL_CLASS *
GetControlClass (
VOID
)
{
STATIC UI_CONTROL_CLASS *Class = NULL;
if (Class != NULL) {
return Class;
}
Class = AllocateZeroPool (sizeof (UI_CONTROL_CLASS));
if (Class == NULL) {
return NULL;
}
Class->Parent = NULL;
Class->ClassSize = sizeof (*Class);
Class->ClassName = StrDuplicate (L"Control");
Class->FindChildByName = UiControlFindChildByName;
Class->AddChild = UiControlAddChild;
Class->RemoveChild = UiControlRemoveChild;
Class->RemoveAllChild = UiControlRemoveAllChild;
Class->WndProc = UiControlProc;
Class->SetState = UiControlSetState;
Class->GetState = UiControlGetState;
Class->SetAttribute = UiControlSetAttribute;
Class->SetPosition = UiControlSetPosition;
Class->EstimateSize = UiControlEstimateSize;
Class->Invalidate = UiControlInvalidate;
Class->FindNextFocus = UiControlFindNextFocus;
Class->GetParent = UiControlGetParent;
Class->ShouldDelayChildPressedState = UiControlShouldDelayChildPressedState;
return Class;
}