| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- // ================================================================================
- // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
- // == See tb_core.h for more information. ==
- // ================================================================================
- #include "tb_window.h"
- #include <assert.h>
- namespace tb {
- // == TBWindow ==========================================================================
- TBWindow::TBWindow()
- : m_settings(WINDOW_SETTINGS_DEFAULT)
- {
- // ATOMIC BEGIN
- m_axis = AXIS_Y;
- // ATOMIC END
- SetSkinBg(TBIDC("TBWindow"), WIDGET_INVOKE_INFO_NO_CALLBACKS);
- AddChild(&m_mover);
- AddChild(&m_resizer);
- m_mover.SetSkinBg(TBIDC("TBWindow.mover"));
- m_mover.AddChild(&m_textfield);
- m_textfield.SetIgnoreInput(true);
- // ATOMIC BEGIN
- m_textfield.SetSqueezable(true);
- // ATOMIC END
- m_mover.AddChild(&m_close_button);
- m_close_button.SetSkinBg(TBIDC("TBWindow.close"));
- m_close_button.SetIsFocusable(false);
- m_close_button.SetID(TBIDC("TBWindow.close"));
- SetIsGroupRoot(true);
- }
- TBWindow::~TBWindow()
- {
- if (m_resizer.GetParent()) RemoveChild(&m_resizer);
- if (m_mover.GetParent()) RemoveChild(&m_mover);
- if (m_close_button.GetParent()) m_mover.RemoveChild(&m_close_button);
- m_mover.RemoveChild(&m_textfield);
- }
- TBRect TBWindow::GetResizeToFitContentRect(RESIZE_FIT fit)
- {
- PreferredSize ps = GetPreferredSize();
- int new_w = ps.pref_w;
- int new_h = ps.pref_h;
- if (fit == RESIZE_FIT_MINIMAL)
- {
- new_w = ps.min_w;
- new_h = ps.min_h;
- }
- else if (fit == RESIZE_FIT_CURRENT_OR_NEEDED)
- {
- new_w = CLAMP(GetRect().w, ps.min_w, ps.max_w);
- new_h = CLAMP(GetRect().h, ps.min_h, ps.max_h);
- }
- if (GetParent())
- {
- new_w = MIN(new_w, GetParent()->GetRect().w);
- new_h = MIN(new_h, GetParent()->GetRect().h);
- }
- return TBRect(GetRect().x, GetRect().y, new_w, new_h);
- }
- void TBWindow::ResizeToFitContent(RESIZE_FIT fit)
- {
- SetRect(GetResizeToFitContentRect(fit));
- }
- void TBWindow::Close()
- {
- // ATOMIC BEGIN
- TBWidgetListener::InvokeWindowClose(this);
- // ATOMIC END
- Die();
- }
- bool TBWindow::IsActive() const
- {
- return GetState(WIDGET_STATE_SELECTED);
- }
- TBWindow *TBWindow::GetTopMostOtherWindow(bool only_activable_windows)
- {
- TBWindow *other_window = nullptr;
- TBWidget *sibling = GetParent()->GetLastChild();
- while (sibling && !other_window)
- {
- if (sibling != this)
- other_window = TBSafeCast<TBWindow>(sibling);
- if (only_activable_windows && other_window && !(other_window->m_settings & WINDOW_SETTINGS_CAN_ACTIVATE))
- other_window = nullptr;
- sibling = sibling->GetPrev();
- }
- return other_window;
- }
- void TBWindow::Activate()
- {
- if (!GetParent() || !(m_settings & WINDOW_SETTINGS_CAN_ACTIVATE))
- return;
- if (IsActive())
- {
- // Already active, but we may still have lost focus,
- // so ensure it comes back to us.
- EnsureFocus();
- return;
- }
- // Deactivate currently active window
- TBWindow *active_window = GetTopMostOtherWindow(true);
- if (active_window)
- active_window->DeActivate();
- // Activate this window
- SetZ(WIDGET_Z_TOP);
- SetWindowActiveState(true);
- EnsureFocus();
- }
- bool TBWindow::EnsureFocus()
- {
- // If we already have focus, we're done.
- if (focused_widget && IsAncestorOf(focused_widget))
- return true;
- // Focus last focused widget (if we have one)
- bool success = false;
- if (m_last_focus.Get())
- success = m_last_focus.Get()->SetFocus(WIDGET_FOCUS_REASON_UNKNOWN);
- // We didn't have one or failed, so try focus any child.
- if (!success)
- success = SetFocusRecursive(WIDGET_FOCUS_REASON_UNKNOWN);
- return success;
- }
- void TBWindow::DeActivate()
- {
- if (!IsActive())
- return;
- SetWindowActiveState(false);
- }
- void TBWindow::SetWindowActiveState(bool active)
- {
- SetState(WIDGET_STATE_SELECTED, active);
- m_mover.SetState(WIDGET_STATE_SELECTED, active);
- }
- void TBWindow::SetSettings(WINDOW_SETTINGS settings)
- {
- if (settings == m_settings)
- return;
- m_settings = settings;
- if (settings & WINDOW_SETTINGS_TITLEBAR)
- {
- if (!m_mover.GetParent())
- AddChild(&m_mover);
- }
- else if (!(settings & WINDOW_SETTINGS_TITLEBAR))
- {
- if (m_mover.GetParent())
- RemoveChild(&m_mover);
- }
- if (settings & WINDOW_SETTINGS_RESIZABLE)
- {
- if (!m_resizer.GetParent())
- AddChild(&m_resizer);
- }
- else if (!(settings & WINDOW_SETTINGS_RESIZABLE))
- {
- if (m_resizer.GetParent())
- RemoveChild(&m_resizer);
- }
- if (settings & WINDOW_SETTINGS_CLOSE_BUTTON)
- {
- if (!m_close_button.GetParent())
- m_mover.AddChild(&m_close_button);
- }
- else if (!(settings & WINDOW_SETTINGS_CLOSE_BUTTON))
- {
- if (m_close_button.GetParent())
- m_mover.RemoveChild(&m_close_button);
- }
- // FIX: invalidate layout / resize window!
- Invalidate();
- }
- int TBWindow::GetTitleHeight()
- {
- if (m_settings & WINDOW_SETTINGS_TITLEBAR)
- return m_mover.GetPreferredSize().pref_h;
- return 0;
- }
- TBRect TBWindow::GetPaddingRect()
- {
- TBRect padding_rect = TBWidget::GetPaddingRect();
- int title_height = GetTitleHeight();
- // ATOMIC BEGIN
- if ( m_axis == AXIS_Y ) // default axis
- {
- // ATOMIC END
- padding_rect.y += title_height;
- padding_rect.h -= title_height;
- // ATOMIC BEGIN
- }
- else if ( m_axis == AXIS_X ) // rotated sideways
- {
- padding_rect.x += title_height;
- padding_rect.w -= title_height;
- }
- // ATOMIC END
- return padding_rect;
- }
- PreferredSize TBWindow::OnCalculatePreferredSize(const SizeConstraints &constraints)
- {
- PreferredSize ps = OnCalculatePreferredContentSize(constraints);
- // Add window skin padding
- if (TBSkinElement *e = GetSkinBgElement())
- {
- ps.min_w += e->padding_left + e->padding_right;
- ps.pref_w += e->padding_left + e->padding_right;
- ps.min_h += e->padding_top + e->padding_bottom;
- ps.pref_h += e->padding_top + e->padding_bottom;
- }
- // Add window title bar height
- int title_height = GetTitleHeight();
- // ATOMIC BEGIN
- if ( m_axis == AXIS_Y ) // default axis
- {
- // ATOMIC END
- ps.min_h += title_height;
- ps.pref_h += title_height;
- // ATOMIC BEGIN
- }
- else if ( m_axis == AXIS_X ) // rotated sideways
- {
- ps.min_w += title_height;
- ps.pref_w += title_height;
- }
- // ATOMIC END
- return ps;
- }
- bool TBWindow::OnEvent(const TBWidgetEvent &ev)
- {
- if (ev.target == &m_close_button)
- {
- if (ev.type == EVENT_TYPE_CLICK)
- Close();
- return true;
- }
- return TBWidget::OnEvent(ev);
- }
- void TBWindow::OnAdded()
- {
- // If we was added last, call Activate to update status etc.
- if (GetParent()->GetLastChild() == this)
- Activate();
- }
- void TBWindow::OnRemove()
- {
- DeActivate();
- // Active the top most other window
- if (TBWindow *active_window = GetTopMostOtherWindow(true))
- active_window->Activate();
- }
- void TBWindow::OnChildAdded(TBWidget *child)
- {
- m_resizer.SetZ(WIDGET_Z_TOP);
- }
- void TBWindow::OnResized(int old_w, int old_h)
- {
- // Apply gravity on children
- TBWidget::OnResized(old_w, old_h);
- // Manually move our own decoration children
- // FIX: Put a layout in the TBMover so we can add things there nicely.
- int title_height = GetTitleHeight();
- // ATOMIC BEGIN
- if ( m_axis == AXIS_Y ) // default axis
- {
- // ATOMIC END
- m_mover.SetRect(TBRect(0, 0, GetRect().w, title_height));
- PreferredSize ps = m_resizer.GetPreferredSize();
- m_resizer.SetRect(TBRect(GetRect().w - ps.pref_w, GetRect().h - ps.pref_h, ps.pref_w, ps.pref_h));
- TBRect mover_rect = m_mover.GetPaddingRect();
- int button_size = mover_rect.h;
- m_close_button.SetRect(TBRect(mover_rect.x + mover_rect.w - button_size, mover_rect.y, button_size, button_size));
- if (m_settings & WINDOW_SETTINGS_CLOSE_BUTTON)
- mover_rect.w -= button_size;
- m_textfield.SetRect(mover_rect);
- // ATOMIC BEGIN
- }
- else if ( m_axis == AXIS_X ) // rotated sideways
- {
- m_mover.SetRect(TBRect(0, 0, title_height, GetRect().h ));
- PreferredSize ps = m_resizer.GetPreferredSize();
- m_resizer.SetRect(TBRect(GetRect().w - ps.pref_w, GetRect().h - ps.pref_h, ps.pref_w, ps.pref_h));
- TBRect mover_rect = m_mover.GetPaddingRect();
- int button_size = mover_rect.w;
- m_close_button.SetRect(TBRect(mover_rect.x + 1, mover_rect.y + 1, button_size, button_size));
- if (m_settings & WINDOW_SETTINGS_CLOSE_BUTTON)
- mover_rect.w -= button_size;
- m_textfield.SetRect(TBRect(mover_rect.x + 5, mover_rect.y + mover_rect.h - button_size, button_size - 1, button_size));
- }
- // ATOMIC END
- }
- // ATOMIC BEGIN
- void TBWindow::SetAxis(AXIS axis)
- {
- m_axis = axis;
- Invalidate();
- }
- // ATOMIC END
- }; // namespace tb
|