diff --git a/uppsrc/CtrlLib/LabelBase.cpp b/uppsrc/CtrlLib/LabelBase.cpp index 5eb76344f..d6ed2d71a 100644 --- a/uppsrc/CtrlLib/LabelBase.cpp +++ b/uppsrc/CtrlLib/LabelBase.cpp @@ -120,7 +120,7 @@ int ExtractAccessKey(const char *s, String& label) while(*s) if((*s == '&' && !qtf || *s == '\b') && s[1] && s[1] != '&') { akey = ToAscii(ToUpper(s[1])); - pos = s - start + 1; + pos = text.GetLength() + 1; s++; } else @@ -130,12 +130,12 @@ int ExtractAccessKey(const char *s, String& label) return MAKELONG(akey, pos); } -byte ChooseAccessKey(const char *text, dword used) +int ChooseAccessKey(const char *text, dword used) { for(const char *s = text; *s; s++) { byte ac = ToAscii(*s); if(ac >= 'A' && ac <= 'Z' && (Ctrl::AccessKeyBit(ac) & used) == 0) - return ac; + return MAKELONG(ac, s - text + 1); } for(const char *s = text; *s; s++) { byte ac = ToUpper(ToAscii(*s)); diff --git a/uppsrc/CtrlLib/LabelBase.h b/uppsrc/CtrlLib/LabelBase.h index 036ab690f..820e2fa9c 100644 --- a/uppsrc/CtrlLib/LabelBase.h +++ b/uppsrc/CtrlLib/LabelBase.h @@ -25,7 +25,7 @@ void DrawSmartText(Draw& w, int x, int y, int cx, const char *text, int ExtractAccessKey(const char *s, String& label); bool CompareAccessKey(int accesskey, dword key); -byte ChooseAccessKey(const char *s, dword used); +int ChooseAccessKey(const char *s, dword used); void DrawFocus(Draw& w, int x, int y, int cx, int cy, Color c = SColorText()); void DrawFocus(Draw& w, const Rect& r, Color c = SColorText()); diff --git a/uppsrc/CtrlLib/MenuItem.cpp b/uppsrc/CtrlLib/MenuItem.cpp index 1921394ad..cf8d7ed3c 100644 --- a/uppsrc/CtrlLib/MenuItem.cpp +++ b/uppsrc/CtrlLib/MenuItem.cpp @@ -1,611 +1,618 @@ -#include "MenuImp.h" - -#ifdef PLATFORM_WIN32 -#include -#endif - -NAMESPACE_UPP - -#define LLOG(x) // LOG(x) -#define LTIMING(x) // RTIMING(x) - -MenuItemBase::MenuItemBase() -{ - accel = 0; - state = 0; - isenabled = true; - type = 0; - font = StdFont(); - leftgap = 16; - textgap = 6; - accesskey = 0; - NoWantFocus(); - style = &MenuBar::StyleDefault(); - Transparent(); - maxiconsize = Size(INT_MAX, INT_MAX); -} - -Bar::Item& MenuItemBase::Text(const char *s) -{ - accesskey = ExtractAccessKey(s, text); - Refresh(); - return *this; -} - -Bar::Item& MenuItemBase::Key(dword key) -{ - if(key) { - accel = key; - Refresh(); - } - return *this; -} - -Bar::Item& MenuItemBase::Image(const UPP::Image& img) -{ - return *this; -} - -Bar::Item& MenuItemBase::Check(bool check) -{ - type = CHECK0 + check; - return *this; -} - -Bar::Item& MenuItemBase::Radio(bool check) -{ - type = RADIO0 + check; - return *this; -} - -Bar::Item& MenuItemBase::Tip(const char *s) -{ - return *this; -} - -Bar::Item& MenuItemBase::Help(const char *s) -{ - HelpLine(s); - return *this; -} - -Bar::Item& MenuItemBase::Description(const char *s) -{ - Ctrl::Description(s); - return *this; -} - -Bar::Item& MenuItemBase::Topic(const char *s) -{ - HelpTopic(s); - return *this; -} - -Bar::Item& MenuItemBase::Enable(bool en) -{ - isenabled = en; - Refresh(); - return *this; -} - -String MenuItemBase::GetDesc() const -{ - return text; -} - -dword MenuItemBase::GetAccessKeys() const -{ - return AccessKeyBit(accesskey); -} - -void MenuItemBase::AssignAccessKeys(dword used) -{ - if(!accesskey) { - accesskey = ChooseAccessKey(text, used); - used |= AccessKeyBit(accesskey); - } - Ctrl::AssignAccessKeys(used); -} - -void DrawMnemonicText(Draw& w, int x, int y, const String& s, Font font, Color color, - int mnemonic) -{ - int q = s.Find(ToUpper(mnemonic)); - int e = s.Find(ToLower(mnemonic)); - if(q < 0 || e >= 0 && e < q) q = e; - w.DrawText(x, y, s, font, color); - if(q < 0) return; - FontInfo f = font.Info(); - w.DrawRect(x + GetTextSize(~s, font, q).cx, y + f.GetAscent() + 1, f[s[q]], 1, - SColorMark()); -} - -void DrawMenuText(Draw& w, int x, int y, const String& s, Font f, bool enabled, - bool hl, int mnemonic, Color color, Color hlcolor) -{ - if(enabled) - DrawMnemonicText(w, x, y, s, f, hl ? hlcolor : color, mnemonic); - else { - if(GUI_GlobalStyle() >= GUISTYLE_XP) - DrawMnemonicText(w, x, y, s, f, SColorDisabled, 0); - else { - DrawMnemonicText(w, x + 1, y + 1, s, f, SColorPaper, 0); - DrawMnemonicText(w, x, y, s, f, SColorDisabled, 0); - } - } -} - -void MenuItemBase::DrawMenuText(Draw& w, int x, int y, const String& s, Font f, bool enabled, - bool hl, Color color, Color hlcolor) -{ - UPP::DrawMenuText(w, x, y, s, f, enabled, hl, VisibleAccessKeys() ? accesskey : 0, - color, hlcolor); -} - -void MenuItemBase::PaintTopItem(Draw& w, int state) { - Size sz = GetSize(); - if(GUI_GlobalStyle() >= GUISTYLE_XP) { - ChPaint(w, 0, 0, sz.cx, sz.cy, style->topitem[state]); - String text = GetText(); - Size isz = GetTextSize(text, StdFont()); - DrawMenuText(w, 6, (sz.cy - isz.cy) / 2, text, GetFont(), IsItemEnabled(), state, - style->topitemtext[0], style->topitemtext[state]); - } - else { - w.DrawRect(sz, SColorFace); - static const ColorF b0[] = { (ColorF)1, SColorLight, SColorLight, SColorShadow, SColorShadow, }; - static const ColorF b1[] = { (ColorF)1, SColorShadow, SColorShadow, SColorLight, SColorLight, }; - String text = GetText(); - Size isz = GetTextSize(text, StdFont()); - DrawMenuText(w, 6, (sz.cy - isz.cy) / 2, text, GetFont(), IsItemEnabled(), false, - SColorMenuText, SColorHighlightText); - if(state) - DrawBorder(w, 0, 0, sz.cx, sz.cy, state == 2 ? b1 : b0); - } -} - -// ------------------------------------- - -Bar::Item& MenuItem::Image(const UPP::Image& img) -{ - licon = img; - Refresh(); - return *this; -} - -MenuItem& MenuItem::RightImage(const UPP::Image& img) -{ - ricon = img; - Refresh(); - return *this; -} - -void MenuItem::SendHelpLine() -{ - BarCtrl::SendHelpLine(this); -} - -void MenuItem::ClearHelpLine() -{ - BarCtrl::ClearHelpLine(this); -} - -void MenuItem::MouseEnter(Point, dword) -{ - SetFocus(); - Refresh(); - SendHelpLine(); -} - -void MenuItem::MouseLeave() -{ - ClearHelpLine(); -} - -void MenuItem::GotFocus() -{ - Refresh(); - SendHelpLine(); -} - -void MenuItem::LostFocus() -{ - Refresh(); - ClearHelpLine(); -} - -int MenuItem::GetVisualState() -{ - return HasFocus() ? - (HasMouse() && GetMouseLeft() || GetMouseRight()) ? PUSH : HIGHLIGHT : NORMAL; -} - -void MenuItem::SyncState() -{ - int s = GetVisualState(); - if(s != state) { - state = s; - Refresh(); - } -} - -void MenuItem::Paint(Draw& w) -{ - int q = text.Find('\t'); - String txt, keydesc; - if(accel) - keydesc = GetKeyDesc(accel); - if(q >= 0) { - keydesc = text.Mid(q + 1); - txt = text.Mid(0, q); - } - else - txt = text; - state = GetVisualState(); - bool hl = state != NORMAL; - Size sz = GetSize(); - - if(hl) - if(GUI_GlobalStyle() >= GUISTYLE_XP) - ChPaint(w, 0, 0, sz.cx, sz.cy, style->item); - else - w.DrawRect(sz, SColorHighlight); - UPP::Image li = licon; - if(li.IsEmpty()) { - switch(type) { - case CHECK0: li = CtrlImg::MenuCheck0(); break; - case CHECK1: li = CtrlImg::MenuCheck1(); break; - case RADIO0: li = CtrlImg::MenuRadio0(); break; - case RADIO1: li = CtrlImg::MenuRadio1(); break; - } - } - Size imsz = li.GetSize(); - Size isz = min(maxiconsize, imsz); - if(isz != imsz) - li = CachedRescale(li, isz); - int iy = (sz.cy - isz.cy) / 2; - bool chk = false; - int x = (max(isz.cx, leftgap - 2) - isz.cx) / 2; - if(!licon.IsEmpty() && type) { - chk = type == CHECK1 || type == RADIO1; - x = 2; - if(GUI_GlobalStyle() >= GUISTYLE_XP) { - if(chk && !hl) { - DrawXPButton(w, RectC(0, iy - 2, isz.cx + 4, isz.cy + 4), BUTTON_EDGE|BUTTON_CHECKED); - } - } - else { - w.DrawRect(1, iy - 1, isz.cx + 2, isz.cy + 2, chk ? Blend(SColorFace, SColorLight) - : SColorFace); - DrawBorder(w, 0, iy - 2, isz.cx + 4, isz.cy + 4, chk ? ThinInsetBorder : ThinOutsetBorder); - } - } - if(isenabled) - DrawHighlightImage(w, x, iy, li, hl || chk, true); - else - w.DrawImage(x, iy, DisabledImage(li)); - x = max(isz.cx, leftgap) + textgap; - isz = GetTextSize(text, StdFont()); - DrawMenuText(w, x, (sz.cy - isz.cy) / 2, txt, font, isenabled, hl, SColorMenuText, - style->itemtext); - isz = ricon.GetSize(); - if(isenabled) - DrawHighlightImage(w, sz.cx - isz.cx, (sz.cy - isz.cy) / 2, ricon, hl, true); - else - w.DrawImage(sz.cx - isz.cx, (sz.cy - isz.cy) / 2, DisabledImage(ricon)); - x = sz.cx - max(isz.cx, 16) - 1; - if(!IsEmpty(keydesc)) { - isz = GetTextSize(keydesc, StdFont()); - UPP::DrawMenuText(w, x - isz.cx - 2, (sz.cy - isz.cy) / 2, keydesc, font, isenabled, hl, - 0, SColorMark(), style->itemtext); - } -} - -Size MenuItem::GetMinSize() const -{ - Size sz1 = GetTextSize(text, font); - Size sz2(0, 0); - if(accel) { - sz2 = GetTextSize(GetKeyDesc(accel), font); - sz2.cx += 12; - } - Size lsz = min(maxiconsize, licon.GetSize()); - Size rsz = ricon.GetSize(); - return AddFrameSize(Size(max(lsz.cx, leftgap) + sz1.cx + max(sz2.cx, (rsz.cx ? 16 : 0)) - + max(rsz.cx, 16) + textgap + 10, - max(max(lsz.cy, rsz.cy) + 4, sz1.cy + 6))); -} - -void MenuItem::LeftUp(Point, dword) -{ - if(!isenabled) return; -#ifdef PLATFORM_WIN32 -#ifdef PLATFORM_WINCE - PlaySound(L"MenuCommand", NULL, SND_ASYNC|SND_NODEFAULT); //TODO? -#else - PlaySound("MenuCommand", NULL, SND_ASYNC|SND_NODEFAULT); -#endif -#endif - LLOG("Menu Item pre Action"); - WhenAction(); - LLOG("Menu Item post Action"); -} - -void MenuItem::RightUp(Point p, dword w) -{ - LeftUp(p, w); -} - -bool MenuItem::HotKey(dword key) -{ - if(isenabled && (key == accel || CompareAccessKey(accesskey, key) - || key < 256 && IsAlNum((char)key) && CompareAccessKey(accesskey, ToUpper((char)key) + K_DELTA + K_ALT))) { - LLOG("MenuItem::HotKey(" << key << ") -> SetFocus"); - SetFocus(); - Sync(); - Sleep(50); - WhenAction(); - return true; - } - return false; -} - -bool MenuItem::Key(dword key, int count) -{ - if(key == K_ENTER && isenabled) { - WhenAction(); - return true; - } - return false; -} - -// ---------------------------------------------------- - -void SubMenuBase::Pull(Ctrl *item, Point p, Size sz) -{ - if(!item->IsOpen() || menu.IsOpen()) return; - menu.Clear(); - if(parentmenu) - menu.SetStyle(*parentmenu->style); - proc(menu); - if(parentmenu) { - parentmenu->SetActiveSubmenu(&menu, item); - menu.SetParentMenu(parentmenu); - } - menu.PopUp(parentmenu, p, sz); - if(parentmenu) - parentmenu->doeffect = false; -} - -// ---------------------------------------------------- - -SubMenuItem::SubMenuItem() -{ - RightImage(CtrlImg::right_arrow()); -} - -void SubMenuItem::GotFocus() -{ - Refresh(); -} - -void SubMenuItem::Pull() -{ - Rect r = GetScreenRect(); - Point p = r.TopRight(); - p.x -= 3; - p.y -= 2; - SubMenuBase::Pull(this, p, Size(-r.Width(), 0)); - if(parentmenu) - parentmenu->SyncState(); -} - -void SubMenuItem::MouseEnter(Point, dword) -{ - SetFocus(); - Refresh(); - if(!menu.IsOpen() && isenabled) - SetTimeCallback(400, THISBACK(Pull), TIMEID_PULL); -} - -void SubMenuItem::MouseLeave() -{ - if(HasFocus() && GetParent()) - GetParent()->SetFocus(); - KillTimeCallback(TIMEID_PULL); -} - -int SubMenuItem::GetVisualState() -{ - if(menu.IsOpen() && !GetParent()->HasFocusDeep()) - return PUSH; - return MenuItem::GetVisualState(); -} - -bool SubMenuItem::Key(dword key, int count) -{ - if(key == K_RIGHT || key == K_ENTER) { - Pull(); - return true; - } - return MenuItem::Key(key, count); -} - -bool SubMenuItem::HotKey(dword key) -{ - if(isenabled && (key == accel || CompareAccessKey(accesskey, key))) { - Pull(); - return true; - } - return false; -} - - -// ---------------------------------------------------- - -Size TopSubMenuItem::GetMinSize() const -{ - return AddFrameSize(GetTextSize(text, font) + Size(12, 7)); -} - -int TopSubMenuItem::GetState() -{ - if(parentmenu && parentmenu->GetActiveSubmenu() == &menu) return PUSH; - if(HasMouse() && GetParent() && !GetParent()->HasFocusDeep() && - (!parentmenu || !parentmenu->GetActiveSubmenu() || parentmenu->GetActiveSubmenu() == &menu) - || HasFocus()) - return HIGHLIGHT; - return NORMAL; -} - -void TopSubMenuItem::Paint(Draw& w) -{ - PaintTopItem(w, state = GetState()); -} - -void TopSubMenuItem::Pull() -{ - Rect r = GetScreenRect(); - if(parentmenu && parentmenu->IsChild() && !parentmenu->submenu) - parentmenu->SetupRestoreFocus(); - Point p = r.BottomLeft(); - if(GUI_GlobalStyle() >= GUISTYLE_XP) - p += style->pullshift; - SubMenuBase::Pull(this, p, Size(r.Width(), -r.Height())); - if(parentmenu) - parentmenu->SyncState(); -} - -void TopSubMenuItem::MouseEnter(Point p, dword) -{ - Refresh(); - if(isenabled && parentmenu->GetActiveSubmenu()) - Pull(); -} - -bool TopSubMenuItem::Key(dword key, int) { - if(isenabled && (key == K_ENTER || key == K_DOWN)) { - Pull(); - return true; - } - return false; -} - -void TopSubMenuItem::GotFocus() -{ - Refresh(); -} - -void TopSubMenuItem::LostFocus() -{ - Refresh(); -} - -bool TopSubMenuItem::HotKey(dword key) -{ - if(BarCtrl::Scan(proc, key)) - return true; - if(isenabled && (key == accel || CompareAccessKey(accesskey, key))) { - Pull(); - return true; - } - return false; -} - -void TopSubMenuItem::MouseLeave() -{ - Refresh(); -} - -void TopSubMenuItem::LeftDown(Point, dword) -{ - if(isenabled && !menu.IsOpen()) { - Pull(); - Refresh(); - } -} - -void TopSubMenuItem::SyncState() -{ - int q = GetState(); - if(q != state) { - state = q; - Refresh(); - } -} - -// ---------------------------------------------------- - -int TopMenuItem::GetState() -{ - if(!IsEnabled()) return NORMAL; - if(HasMouse() && GetMouseLeft() || GetMouseRight()) return PUSH; - if(HasFocus() || HasMouse()) return HIGHLIGHT; - return NORMAL; -} - -void TopMenuItem::Paint(Draw& w) -{ - PaintTopItem(w, state = GetState()); -} - -void TopMenuItem::MouseEnter(Point, dword) -{ - Refresh(); -} - -void TopMenuItem::MouseLeave() -{ - Refresh(); -} - -void TopMenuItem::LeftUp(Point, dword) -{ - if(!isenabled) return; - WhenAction(); - Refresh(); -} - -void TopMenuItem::LeftDown(Point, dword) -{ - Refresh(); -} - -void TopMenuItem::GotFocus() -{ - Refresh(); -} - -void TopMenuItem::LostFocus() -{ - Refresh(); -} - -bool TopMenuItem::Key(dword key, int count) -{ - if(isenabled && key == K_ENTER) { - WhenAction(); - return true; - } - return false; -} - -Size TopMenuItem::GetMinSize() const -{ - return AddFrameSize(GetTextSize(text, StdFont()) + Size(12, 7)); -} - -int TopMenuItem::GetStdHeight(Font font) -{ - return font.Info().GetHeight() + 7; -} - -void TopMenuItem::SyncState() -{ - if(state != GetState()) { - state = GetState(); - Refresh(); - } -} - -END_UPP_NAMESPACE +#include "MenuImp.h" + +#ifdef PLATFORM_WIN32 +#include +#endif + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LTIMING(x) // RTIMING(x) + +MenuItemBase::MenuItemBase() +{ + accel = 0; + state = 0; + isenabled = true; + type = 0; + font = StdFont(); + leftgap = 16; + textgap = 6; + accesskey = 0; + NoWantFocus(); + style = &MenuBar::StyleDefault(); + Transparent(); + maxiconsize = Size(INT_MAX, INT_MAX); +} + +Bar::Item& MenuItemBase::Text(const char *s) +{ + accesskey = ExtractAccessKey(s, text); + Refresh(); + return *this; +} + +Bar::Item& MenuItemBase::Key(dword key) +{ + if(key) { + accel = key; + Refresh(); + } + return *this; +} + +Bar::Item& MenuItemBase::Image(const UPP::Image& img) +{ + return *this; +} + +Bar::Item& MenuItemBase::Check(bool check) +{ + type = CHECK0 + check; + return *this; +} + +Bar::Item& MenuItemBase::Radio(bool check) +{ + type = RADIO0 + check; + return *this; +} + +Bar::Item& MenuItemBase::Tip(const char *s) +{ + return *this; +} + +Bar::Item& MenuItemBase::Help(const char *s) +{ + HelpLine(s); + return *this; +} + +Bar::Item& MenuItemBase::Description(const char *s) +{ + Ctrl::Description(s); + return *this; +} + +Bar::Item& MenuItemBase::Topic(const char *s) +{ + HelpTopic(s); + return *this; +} + +Bar::Item& MenuItemBase::Enable(bool en) +{ + isenabled = en; + Refresh(); + return *this; +} + +String MenuItemBase::GetDesc() const +{ + return text; +} + +dword MenuItemBase::GetAccessKeys() const +{ + return AccessKeyBit(accesskey); +} + +void MenuItemBase::AssignAccessKeys(dword used) +{ + if(!accesskey) { + accesskey = ChooseAccessKey(text, used); + used |= AccessKeyBit(accesskey); + } + Ctrl::AssignAccessKeys(used); +} + +void DrawMnemonicText(Draw& w, int x, int y, const String& s, Font font, Color color, + int mnemonic) +{ + int apos = HIWORD(mnemonic); + int akey = LOWORD(mnemonic); + int q; + if(apos && apos < s.GetLength()) + q = apos - 1; + else { + q = s.Find(ToUpper(mnemonic)); + if(q < 0) + q = s.Find(ToLower(mnemonic)); + } + w.DrawText(x, y, s, font, color); + if(q < 0) return; + FontInfo f = font.Info(); + w.DrawRect(x + GetTextSize(~s, font, q).cx, y + f.GetAscent() + 1, f[s[q]], 1, + SColorMark()); +} + +void DrawMenuText(Draw& w, int x, int y, const String& s, Font f, bool enabled, + bool hl, int mnemonic, Color color, Color hlcolor) +{ + if(enabled) + DrawMnemonicText(w, x, y, s, f, hl ? hlcolor : color, mnemonic); + else { + if(GUI_GlobalStyle() >= GUISTYLE_XP) + DrawMnemonicText(w, x, y, s, f, SColorDisabled, 0); + else { + DrawMnemonicText(w, x + 1, y + 1, s, f, SColorPaper, 0); + DrawMnemonicText(w, x, y, s, f, SColorDisabled, 0); + } + } +} + +void MenuItemBase::DrawMenuText(Draw& w, int x, int y, const String& s, Font f, bool enabled, + bool hl, Color color, Color hlcolor) +{ + UPP::DrawMenuText(w, x, y, s, f, enabled, hl, VisibleAccessKeys() ? accesskey : 0, + color, hlcolor); +} + +void MenuItemBase::PaintTopItem(Draw& w, int state) { + Size sz = GetSize(); + if(GUI_GlobalStyle() >= GUISTYLE_XP) { + ChPaint(w, 0, 0, sz.cx, sz.cy, style->topitem[state]); + String text = GetText(); + Size isz = GetTextSize(text, StdFont()); + DrawMenuText(w, 6, (sz.cy - isz.cy) / 2, text, GetFont(), IsItemEnabled(), state, + style->topitemtext[0], style->topitemtext[state]); + } + else { + w.DrawRect(sz, SColorFace); + static const ColorF b0[] = { (ColorF)1, SColorLight, SColorLight, SColorShadow, SColorShadow, }; + static const ColorF b1[] = { (ColorF)1, SColorShadow, SColorShadow, SColorLight, SColorLight, }; + String text = GetText(); + Size isz = GetTextSize(text, StdFont()); + DrawMenuText(w, 6, (sz.cy - isz.cy) / 2, text, GetFont(), IsItemEnabled(), false, + SColorMenuText, SColorHighlightText); + if(state) + DrawBorder(w, 0, 0, sz.cx, sz.cy, state == 2 ? b1 : b0); + } +} + +// ------------------------------------- + +Bar::Item& MenuItem::Image(const UPP::Image& img) +{ + licon = img; + Refresh(); + return *this; +} + +MenuItem& MenuItem::RightImage(const UPP::Image& img) +{ + ricon = img; + Refresh(); + return *this; +} + +void MenuItem::SendHelpLine() +{ + BarCtrl::SendHelpLine(this); +} + +void MenuItem::ClearHelpLine() +{ + BarCtrl::ClearHelpLine(this); +} + +void MenuItem::MouseEnter(Point, dword) +{ + SetFocus(); + Refresh(); + SendHelpLine(); +} + +void MenuItem::MouseLeave() +{ + ClearHelpLine(); +} + +void MenuItem::GotFocus() +{ + Refresh(); + SendHelpLine(); +} + +void MenuItem::LostFocus() +{ + Refresh(); + ClearHelpLine(); +} + +int MenuItem::GetVisualState() +{ + return HasFocus() ? + (HasMouse() && GetMouseLeft() || GetMouseRight()) ? PUSH : HIGHLIGHT : NORMAL; +} + +void MenuItem::SyncState() +{ + int s = GetVisualState(); + if(s != state) { + state = s; + Refresh(); + } +} + +void MenuItem::Paint(Draw& w) +{ + int q = text.Find('\t'); + String txt, keydesc; + if(accel) + keydesc = GetKeyDesc(accel); + if(q >= 0) { + keydesc = text.Mid(q + 1); + txt = text.Mid(0, q); + } + else + txt = text; + state = GetVisualState(); + bool hl = state != NORMAL; + Size sz = GetSize(); + + if(hl) + if(GUI_GlobalStyle() >= GUISTYLE_XP) + ChPaint(w, 0, 0, sz.cx, sz.cy, style->item); + else + w.DrawRect(sz, SColorHighlight); + UPP::Image li = licon; + if(li.IsEmpty()) { + switch(type) { + case CHECK0: li = CtrlImg::MenuCheck0(); break; + case CHECK1: li = CtrlImg::MenuCheck1(); break; + case RADIO0: li = CtrlImg::MenuRadio0(); break; + case RADIO1: li = CtrlImg::MenuRadio1(); break; + } + } + Size imsz = li.GetSize(); + Size isz = min(maxiconsize, imsz); + if(isz != imsz) + li = CachedRescale(li, isz); + int iy = (sz.cy - isz.cy) / 2; + bool chk = false; + int x = (max(isz.cx, leftgap - 2) - isz.cx) / 2; + if(!licon.IsEmpty() && type) { + chk = type == CHECK1 || type == RADIO1; + x = 2; + if(GUI_GlobalStyle() >= GUISTYLE_XP) { + if(chk && !hl) { + DrawXPButton(w, RectC(0, iy - 2, isz.cx + 4, isz.cy + 4), BUTTON_EDGE|BUTTON_CHECKED); + } + } + else { + w.DrawRect(1, iy - 1, isz.cx + 2, isz.cy + 2, chk ? Blend(SColorFace, SColorLight) + : SColorFace); + DrawBorder(w, 0, iy - 2, isz.cx + 4, isz.cy + 4, chk ? ThinInsetBorder : ThinOutsetBorder); + } + } + if(isenabled) + DrawHighlightImage(w, x, iy, li, hl || chk, true); + else + w.DrawImage(x, iy, DisabledImage(li)); + x = max(isz.cx, leftgap) + textgap; + isz = GetTextSize(text, StdFont()); + DrawMenuText(w, x, (sz.cy - isz.cy) / 2, txt, font, isenabled, hl, SColorMenuText, + style->itemtext); + isz = ricon.GetSize(); + if(isenabled) + DrawHighlightImage(w, sz.cx - isz.cx, (sz.cy - isz.cy) / 2, ricon, hl, true); + else + w.DrawImage(sz.cx - isz.cx, (sz.cy - isz.cy) / 2, DisabledImage(ricon)); + x = sz.cx - max(isz.cx, 16) - 1; + if(!IsEmpty(keydesc)) { + isz = GetTextSize(keydesc, StdFont()); + UPP::DrawMenuText(w, x - isz.cx - 2, (sz.cy - isz.cy) / 2, keydesc, font, isenabled, hl, + 0, SColorMark(), style->itemtext); + } +} + +Size MenuItem::GetMinSize() const +{ + Size sz1 = GetTextSize(text, font); + Size sz2(0, 0); + if(accel) { + sz2 = GetTextSize(GetKeyDesc(accel), font); + sz2.cx += 12; + } + Size lsz = min(maxiconsize, licon.GetSize()); + Size rsz = ricon.GetSize(); + return AddFrameSize(Size(max(lsz.cx, leftgap) + sz1.cx + max(sz2.cx, (rsz.cx ? 16 : 0)) + + max(rsz.cx, 16) + textgap + 10, + max(max(lsz.cy, rsz.cy) + 4, sz1.cy + 6))); +} + +void MenuItem::LeftUp(Point, dword) +{ + if(!isenabled) return; +#ifdef PLATFORM_WIN32 +#ifdef PLATFORM_WINCE + PlaySound(L"MenuCommand", NULL, SND_ASYNC|SND_NODEFAULT); //TODO? +#else + PlaySound("MenuCommand", NULL, SND_ASYNC|SND_NODEFAULT); +#endif +#endif + LLOG("Menu Item pre Action"); + WhenAction(); + LLOG("Menu Item post Action"); +} + +void MenuItem::RightUp(Point p, dword w) +{ + LeftUp(p, w); +} + +bool MenuItem::HotKey(dword key) +{ + if(isenabled && (key == accel || CompareAccessKey(accesskey, key) + || key < 256 && IsAlNum((char)key) && CompareAccessKey(accesskey, ToUpper((char)key) + K_DELTA + K_ALT))) { + LLOG("MenuItem::HotKey(" << key << ") -> SetFocus"); + SetFocus(); + Sync(); + Sleep(50); + WhenAction(); + return true; + } + return false; +} + +bool MenuItem::Key(dword key, int count) +{ + if(key == K_ENTER && isenabled) { + WhenAction(); + return true; + } + return false; +} + +// ---------------------------------------------------- + +void SubMenuBase::Pull(Ctrl *item, Point p, Size sz) +{ + if(!item->IsOpen() || menu.IsOpen()) return; + menu.Clear(); + if(parentmenu) + menu.SetStyle(*parentmenu->style); + proc(menu); + if(parentmenu) { + parentmenu->SetActiveSubmenu(&menu, item); + menu.SetParentMenu(parentmenu); + } + menu.PopUp(parentmenu, p, sz); + if(parentmenu) + parentmenu->doeffect = false; +} + +// ---------------------------------------------------- + +SubMenuItem::SubMenuItem() +{ + RightImage(CtrlImg::right_arrow()); +} + +void SubMenuItem::GotFocus() +{ + Refresh(); +} + +void SubMenuItem::Pull() +{ + Rect r = GetScreenRect(); + Point p = r.TopRight(); + p.x -= 3; + p.y -= 2; + SubMenuBase::Pull(this, p, Size(-r.Width(), 0)); + if(parentmenu) + parentmenu->SyncState(); +} + +void SubMenuItem::MouseEnter(Point, dword) +{ + SetFocus(); + Refresh(); + if(!menu.IsOpen() && isenabled) + SetTimeCallback(400, THISBACK(Pull), TIMEID_PULL); +} + +void SubMenuItem::MouseLeave() +{ + if(HasFocus() && GetParent()) + GetParent()->SetFocus(); + KillTimeCallback(TIMEID_PULL); +} + +int SubMenuItem::GetVisualState() +{ + if(menu.IsOpen() && !GetParent()->HasFocusDeep()) + return PUSH; + return MenuItem::GetVisualState(); +} + +bool SubMenuItem::Key(dword key, int count) +{ + if(key == K_RIGHT || key == K_ENTER) { + Pull(); + return true; + } + return MenuItem::Key(key, count); +} + +bool SubMenuItem::HotKey(dword key) +{ + if(isenabled && (key == accel || CompareAccessKey(accesskey, key))) { + Pull(); + return true; + } + return false; +} + + +// ---------------------------------------------------- + +Size TopSubMenuItem::GetMinSize() const +{ + return AddFrameSize(GetTextSize(text, font) + Size(12, 7)); +} + +int TopSubMenuItem::GetState() +{ + if(parentmenu && parentmenu->GetActiveSubmenu() == &menu) return PUSH; + if(HasMouse() && GetParent() && !GetParent()->HasFocusDeep() && + (!parentmenu || !parentmenu->GetActiveSubmenu() || parentmenu->GetActiveSubmenu() == &menu) + || HasFocus()) + return HIGHLIGHT; + return NORMAL; +} + +void TopSubMenuItem::Paint(Draw& w) +{ + PaintTopItem(w, state = GetState()); +} + +void TopSubMenuItem::Pull() +{ + Rect r = GetScreenRect(); + if(parentmenu && parentmenu->IsChild() && !parentmenu->submenu) + parentmenu->SetupRestoreFocus(); + Point p = r.BottomLeft(); + if(GUI_GlobalStyle() >= GUISTYLE_XP) + p += style->pullshift; + SubMenuBase::Pull(this, p, Size(r.Width(), -r.Height())); + if(parentmenu) + parentmenu->SyncState(); +} + +void TopSubMenuItem::MouseEnter(Point p, dword) +{ + Refresh(); + if(isenabled && parentmenu->GetActiveSubmenu()) + Pull(); +} + +bool TopSubMenuItem::Key(dword key, int) { + if(isenabled && (key == K_ENTER || key == K_DOWN)) { + Pull(); + return true; + } + return false; +} + +void TopSubMenuItem::GotFocus() +{ + Refresh(); +} + +void TopSubMenuItem::LostFocus() +{ + Refresh(); +} + +bool TopSubMenuItem::HotKey(dword key) +{ + if(BarCtrl::Scan(proc, key)) + return true; + if(isenabled && (key == accel || CompareAccessKey(accesskey, key))) { + Pull(); + return true; + } + return false; +} + +void TopSubMenuItem::MouseLeave() +{ + Refresh(); +} + +void TopSubMenuItem::LeftDown(Point, dword) +{ + if(isenabled && !menu.IsOpen()) { + Pull(); + Refresh(); + } +} + +void TopSubMenuItem::SyncState() +{ + int q = GetState(); + if(q != state) { + state = q; + Refresh(); + } +} + +// ---------------------------------------------------- + +int TopMenuItem::GetState() +{ + if(!IsEnabled()) return NORMAL; + if(HasMouse() && GetMouseLeft() || GetMouseRight()) return PUSH; + if(HasFocus() || HasMouse()) return HIGHLIGHT; + return NORMAL; +} + +void TopMenuItem::Paint(Draw& w) +{ + PaintTopItem(w, state = GetState()); +} + +void TopMenuItem::MouseEnter(Point, dword) +{ + Refresh(); +} + +void TopMenuItem::MouseLeave() +{ + Refresh(); +} + +void TopMenuItem::LeftUp(Point, dword) +{ + if(!isenabled) return; + WhenAction(); + Refresh(); +} + +void TopMenuItem::LeftDown(Point, dword) +{ + Refresh(); +} + +void TopMenuItem::GotFocus() +{ + Refresh(); +} + +void TopMenuItem::LostFocus() +{ + Refresh(); +} + +bool TopMenuItem::Key(dword key, int count) +{ + if(isenabled && key == K_ENTER) { + WhenAction(); + return true; + } + return false; +} + +Size TopMenuItem::GetMinSize() const +{ + return AddFrameSize(GetTextSize(text, StdFont()) + Size(12, 7)); +} + +int TopMenuItem::GetStdHeight(Font font) +{ + return font.Info().GetHeight() + 7; +} + +void TopMenuItem::SyncState() +{ + if(state != GetState()) { + state = GetState(); + Refresh(); + } +} + +END_UPP_NAMESPACE diff --git a/uppsrc/Draw/DrawTextUtil.cpp b/uppsrc/Draw/DrawTextUtil.cpp index 3aaed39f5..2320782eb 100644 --- a/uppsrc/Draw/DrawTextUtil.cpp +++ b/uppsrc/Draw/DrawTextUtil.cpp @@ -87,6 +87,9 @@ void DrawTLText(Draw& draw, int x, int y, int cx, const wchar *text, const wchar *t = s; int apos = HIWORD(accesskey); int akey = LOWORD(accesskey); + DDUMP(text); + DDUMP(akey); + DDUMP(apos); for(;;) { if(*s == '\n' || *s == '\0') { int a = x;