| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // ================================================================================
- // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
- // == See tb_core.h for more information. ==
- // ================================================================================
- #include "tb_widgets_listener.h"
- #include "tb_popup_window.h"
- namespace tb {
- // == TBPopupAlignment ======================================================================================
- TBRect TBPopupAlignment::GetAlignedRect(TBWidget *popup, TBWidget *target) const
- {
- TBWidget *root = target->GetParentRoot();
- SizeConstraints sc(root->GetRect().w, root->GetRect().h);
- PreferredSize ps = popup->GetPreferredSize(sc);
- // Amount of pixels that should be avoided if the target rect needs to be moved.
- int avoid_w = 0, avoid_h = 0;
- int x = 0, y = 0;
- int w = MIN(ps.pref_w, root->GetRect().w);
- int h = MIN(ps.pref_h, root->GetRect().h);
- if (pos_in_root.x != UNSPECIFIED &&
- pos_in_root.y != UNSPECIFIED)
- {
- x = pos_in_root.x;
- y = pos_in_root.y;
- avoid_w = pos_offset.x;
- avoid_h = pos_offset.y;
- // Make sure it's moved into view horizontally
- if (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM)
- x = Clamp(x, 0, root->GetRect().w - w);
- }
- else
- {
- target->ConvertToRoot(x, y);
- if (align == TB_ALIGN_TOP || align == TB_ALIGN_BOTTOM)
- {
- if (expand_to_target_width)
- w = MAX(w, target->GetRect().w);
- // If the menu is aligned top or bottom, limit its height to the worst case available height.
- // Being in the center of the root, that is half the root height minus the target rect.
- h = MIN(h, root->GetRect().h / 2 - target->GetRect().h);
- }
- avoid_w = target->GetRect().w;
- avoid_h = target->GetRect().h;
- }
- if (align == TB_ALIGN_BOTTOM)
- y = y + avoid_h + h > root->GetRect().h ? y - h : y + avoid_h;
- else if (align == TB_ALIGN_TOP)
- y = y - h < 0 ? y + avoid_h : y - h;
- else if (align == TB_ALIGN_RIGHT)
- {
- x = x + avoid_w + w > root->GetRect().w ? x - w : x + avoid_w;
- y = MIN(y, root->GetRect().h - h);
- }
- else // if (align == TB_ALIGN_LEFT)
- {
- x = x - w < 0 ? x + avoid_w : x - w;
- y = MIN(y, root->GetRect().h - h);
- }
- return TBRect(x, y, w, h);
- }
- // == TBPopupWindow =========================================================================================
- TBPopupWindow::TBPopupWindow(TBWidget *target)
- : m_target(target)
- {
- TBWidgetListener::AddGlobalListener(this);
- SetSkinBg(TBIDC("TBPopupWindow"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- SetSettings(WINDOW_SETTINGS_NONE);
- }
- TBPopupWindow::~TBPopupWindow()
- {
- TBWidgetListener::RemoveGlobalListener(this);
- }
- bool TBPopupWindow::Show(const TBPopupAlignment &alignment)
- {
- // Calculate and set a good size for the popup window
- SetRect(alignment.GetAlignedRect(this, m_target.Get()));
- TBWidget *root = m_target.Get()->GetParentRoot();
- root->AddChild(this);
- return true;
- }
- bool TBPopupWindow::OnEvent(const TBWidgetEvent &ev)
- {
- if (ev.type == EVENT_TYPE_KEY_DOWN && ev.special_key == TB_KEY_ESC)
- {
- Close();
- return true;
- }
- return TBWindow::OnEvent(ev);
- }
- void TBPopupWindow::OnWidgetFocusChanged(TBWidget *widget, bool focused)
- {
- if (focused && !IsEventDestinationFor(widget))
- Close();
- }
- bool TBPopupWindow::OnWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev)
- {
- if (ev.type == EVENT_TYPE_RIGHT_POINTER_DOWN)
- Close();
- if ((ev.type == EVENT_TYPE_POINTER_DOWN || ev.type == EVENT_TYPE_CONTEXT_MENU) &&
- !IsEventDestinationFor(ev.target))
- Close();
- return false;
- }
- void TBPopupWindow::OnWidgetDelete(TBWidget *widget)
- {
- // If the target widget is deleted, close!
- if (!m_target.Get())
- Close();
- }
- bool TBPopupWindow::OnWidgetDying(TBWidget *widget)
- {
- // If the target widget or an ancestor of it is dying, close!
- if (widget == m_target.Get() || widget->IsAncestorOf(m_target.Get()))
- Close();
- return false;
- }
- }; // namespace tb
|