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; }
void ProgressModal::Show() { assert(!dimmer_->GetParent()); TBUI* tbui = GetSubsystem<TBUI>(); TBWidget* root = tbui->GetRootWidget(); root->AddChild(dimmer_); root->AddChild(delegate_); }
TBWidget *TBSelectList::GetItemWidget(int index) { if (index == -1) return nullptr; for (TBWidget *tmp = m_layout.GetContentRoot()->GetFirstChild(); tmp; tmp = tmp->GetNext()) if (tmp->data.GetInt() == index) return tmp; return nullptr; }
void ProgressModal::Center() { UI* tbui = GetSubsystem<UI>(); TBRect rect = window_->GetRect(); TBWidget* root = tbui->GetRootWidget(); TBRect bounds(0, 0, root->GetRect().w, root->GetRect().h); window_->SetRect(rect.CenterIn(bounds).MoveIn(bounds).Clip(bounds)); delegate_->SetRect(bounds); }
bool ImageWindow::OnEvent(const TBWidgetEvent &ev) { if (ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == TBIDC("remove")) { TBWidget *image = ev.target->GetParent(); image->GetParent()->RemoveChild(image); delete image; return true; } return DemoWindow::OnEvent(ev); }
int TBTabContainer::GetNumPages() { int count = 0; for (TBWidget *tab = m_tab_layout.GetFirstChild(); tab; tab = tab->GetNext()) count++; if (!count) m_current_page = -1; return count; }
void JSUI::GatherWidgets(tb::TBWidget* widget, PODVector<tb::TBWidget*>& widgets) { if (widget->GetID() != TBID()) widgets.Push(widget); for (TBWidget *n = widget->GetFirstChild(); n; n = n->GetNext()) { GatherWidgets(n, widgets); } }
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); TBRect target_rect; TBPoint pos; 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) { pos = pos_in_root; } else { target->ConvertToRoot(pos.x, pos.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); } target_rect = target->GetRect(); } int x, y; if (align == TB_ALIGN_BOTTOM) { x = pos.x; y = pos.y + target_rect.h + h > root->GetRect().h ? pos.y - h : pos.y + target_rect.h; } else if (align == TB_ALIGN_TOP) { x = pos.x; y = pos.y - h < 0 ? pos.y + target_rect.h : pos.y - h; } else if (align == TB_ALIGN_RIGHT) { x = pos.x + target_rect.w + w > root->GetRect().w ? pos.x - w : pos.x + target_rect.w; y = MIN(pos.y, root->GetRect().h - h); } else //if (align == TB_ALIGN_LEFT) { x = pos.x - w < 0 ? pos.x + target_rect.w : pos.x - w; y = MIN(pos.y, root->GetRect().h - h); } return TBRect(x, y, w, h); }
void TBScroller::GetTargetScrollXY(int &x, int &y) const { x = 0; y = 0; TBWidget *tmp = m_target->GetScrollRoot(); while (tmp) { TBWidget::ScrollInfo info = tmp->GetScrollInfo(); x += info.x; y += info.y; tmp = tmp->GetParent(); } }
void UIWidget::Center() { if (!widget_) return; // this should center on parent widget, not root UI* ui = GetSubsystem<UI>(); TBRect rect = widget_->GetRect(); TBWidget* root = ui->GetRootWidget(); TBRect bounds(0, 0, root->GetRect().w, root->GetRect().h); widget_->SetRect(rect.CenterIn(bounds).MoveIn(bounds).Clip(bounds)); }
static void drop_callback(GLFWwindow *window, int count, const char **files_utf8) { ApplicationBackendGLFW *backend = GetBackend(window); TBWidget *target = TBWidget::hovered_widget; if (!target) target = TBWidget::focused_widget; if (!target) target = backend->GetRoot(); if (target) { TBWidgetEventFileDrop ev; for (int i = 0; i < count; i++) ev.files.Add(new TBStr(files_utf8[i])); target->InvokeEvent(ev); } }
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 UIWidget::Center() { if (!widget_) return; TBRect rect = widget_->GetRect(); TBWidget* root = widget_->GetParent(); if (!root) { UI* ui = GetSubsystem<UI>(); root = ui->GetRootWidget(); } TBRect bounds(0, 0, root->GetRect().w, root->GetRect().h); widget_->SetRect(rect.CenterIn(bounds).MoveIn(bounds).Clip(bounds)); }
void UIDragDrop::HandleMouseDown(StringHash eventType, VariantMap& eventData) { using namespace MouseButtonDown; Input* input = GetSubsystem<Input>(); if (!input->IsMouseVisible()) return; if ((eventData[P_BUTTONS].GetUInt() & MOUSEB_LEFT) && TBWidget::hovered_widget) { // see if we have a widget with a drag object TBWidget* tbw = TBWidget::hovered_widget; UIWidget* widget = nullptr; while(tbw) { if (tbw->GetDelegate()) { widget = (UIWidget*) tbw->GetDelegate(); if (widget->GetDragObject()) { // TODO: check if we're in widget bounds // this is going to need to be updated for drag/drop multiselect break; } widget = nullptr; } tbw = tbw->GetParent(); } if (!widget) return; currentTargetWidget_ = widget; dragSourceWidget_ = widget; mouseDownPosition_ = input->GetMousePosition(); } }
void ResourceEditWindow::AddWidgetListItemsRecursive(TBWidget *widget, int depth) { if (depth > 0) // Ignore the root { // Add a new ResourceItem for this widget TBStr str; const char *classname = widget->GetClassName(); if (!*classname) classname = "<Unknown widget type>"; str.SetFormatted("% *s%s", depth - 1, "", classname); if (ResourceItem *item = new ResourceItem(widget, str)) m_widget_list_source.AddItem(item); } for (TBWidget *child = widget->GetFirstChild(); child; child = child->GetNext()) AddWidgetListItemsRecursive(child, depth + 1); }
virtual void OnPaint(const PaintProps &paint_props) { // Draw stuff to the right of the debug window g_renderer->Translate(GetRect().w, 0); // Draw skin bitmap fragments if (TB_DEBUG_SETTING(RENDER_SKIN_BITMAP_FRAGMENTS)) g_tb_skin->Debug(); // Draw font glyph fragments (the font of the hovered widget) if (TB_DEBUG_SETTING(RENDER_FONT_BITMAP_FRAGMENTS)) { TBWidget *widget = TBWidget::hovered_widget ? TBWidget::hovered_widget : TBWidget::focused_widget; g_font_manager->GetFontFace(widget ? widget->GetCalculatedFontDescription() : g_font_manager->GetDefaultFontDescription())->Debug(); } g_renderer->Translate(-GetRect().w, 0); }
//static void TBRadioCheckBox::UpdateGroupWidgets(TBWidget *new_leader) { assert(new_leader->GetValue() && new_leader->GetGroupID()); // Find the group root widget. TBWidget *group = new_leader; while (group && !group->GetIsGroupRoot() && group->GetParent()) group = group->GetParent(); for (TBWidget *child = group; child; child = child->GetNextDeep(group)) if (child != new_leader && child->GetGroupID() == new_leader->GetGroupID()) child->SetValue(0); }
bool TBMover::OnEvent(const TBWidgetEvent &ev) { TBWidget *target = GetParent(); if (!target) return false; if (ev.type == EVENT_TYPE_POINTER_MOVE && captured_widget == this) { int dx = ev.target_x - pointer_down_widget_x; int dy = ev.target_y - pointer_down_widget_y; TBRect rect = target->GetRect().Offset(dx, dy); if (target->GetParent()) { // Apply limit. rect.x = CLAMP(rect.x, -pointer_down_widget_x, target->GetParent()->GetRect().w - pointer_down_widget_x); rect.y = CLAMP(rect.y, -pointer_down_widget_y, target->GetParent()->GetRect().h - pointer_down_widget_y); } target->SetRect(rect); return true; } return false; }
bool ListViewItemWidget::OnEvent(const TBWidgetEvent &ev) { if (ev.type == EVENT_TYPE_WHEEL) { return false; } if (ev.type == EVENT_TYPE_POINTER_DOWN || ev.type == EVENT_TYPE_RIGHT_POINTER_UP) { TBWidget* parent = GetParent(); while (parent) { if (parent->IsOfType<TBSelectList>()) { TBWidgetEvent nev = ev; nev.ref_id = item_->id; parent->InvokeEvent(nev); break; } parent = parent->GetParent(); } return true; } // get clicks this way, not sure we want to if (ev.type == EVENT_TYPE_CLICK && ev.target == expandBox_ && ev.target->GetID() == item_->id) { item_->SetExpanded(!item_->GetExpanded()); source_->list_->InvalidateList(); // want to bubble return false; } return TBLayout::OnEvent(ev); }
bool TBResizer::OnEvent(const TBWidgetEvent &ev) { TBWidget *target = GetParent(); if (!target) return false; if (ev.type == EVENT_TYPE_POINTER_MOVE && captured_widget == this) { int dx = ev.target_x - pointer_down_widget_x; int dy = ev.target_y - pointer_down_widget_y; TBRect rect = target->GetRect(); rect.w += dx; rect.h += dy; // Apply limit. We should not use minimum size since we can squeeze // the layout much more, and provide scroll/pan when smaller. rect.w = MAX(rect.w, 50); rect.h = MAX(rect.h, 50); target->SetRect(rect); } else return false; return true; }
bool TBSelectList::ChangeValue(SPECIAL_KEY key) { if (!m_source || !m_layout.GetContentRoot()->GetFirstChild()) return false; bool forward; if (key == TB_KEY_HOME || key == TB_KEY_DOWN) forward = true; else if (key == TB_KEY_END || key == TB_KEY_UP) forward = false; else return false; TBWidget *item_root = m_layout.GetContentRoot(); TBWidget *current = GetItemWidget(m_value); TBWidget *origin = nullptr; if (key == TB_KEY_HOME || (!current && key == TB_KEY_DOWN)) current = item_root->GetFirstChild(); else if (key == TB_KEY_END || (!current && key == TB_KEY_UP)) current = item_root->GetLastChild(); else origin = current; while (current) { if (current != origin && !current->GetDisabled()) break; current = forward ? current->GetNext() : current->GetPrev(); } // Select and focus what we found if (current) { SetValue(current->data.GetInt()); return true; } return false; }
void TBRadioCheckBox::SetValue(int value) { if (m_value == value) return; m_value = value; SetState(WIDGET_STATE_SELECTED, value ? true : false); Invalidate(); TBWidgetEvent ev(EVENT_TYPE_CHANGED); InvokeEvent(ev); if (!value || !GetGroupID()) return; // Toggle all other widgets in the same group. First get a root widget // for the search. TBWidget *group = this; while (group && !group->GetIsGroupRoot()) group = group->GetParent(); if (group) { ToggleGroup(group, this); } }
UIView* UIWidget::GetView() { if (!widget_) return 0; if (GetType() == UIView::GetTypeStatic()) return (UIView*) this; TBWidget* tbw = widget_->GetParent(); while(tbw) { TBWidgetDelegate* delegate = tbw->GetDelegate(); if (delegate) { UIWidget* d = (UIWidget*) delegate; if (d->GetType() == UIView::GetTypeStatic()) return (UIView*) d; } tbw = tbw->GetParent(); } return 0; }
void TBTabContainer::SetCurrentPage(int index) { if (index == m_current_page) return; m_current_page = index; // Update the pages visibility and tabs pressed value. index = 0; TBWidget *page = m_content_root.GetFirstChild(); TBWidget *tab = m_tab_layout.GetFirstChild(); for ( ; page && tab; page = page->GetNext(), tab = tab->GetNext(), index++) { bool active = index == m_current_page; page->SetOpacity(active ? 1.0f : 0.0f); tab->SetValue(active ? 1 : 0); } }
MenubarItemWidget::MenubarItemWidget(MenubarItem *item, MenubarItemSource *source, TBSelectItemViewer *source_viewer, int index) : m_source(source) , m_source_viewer(source_viewer) , m_index(index) { SetSkinBg(TBIDC("TBSelectItem")); SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY); SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP); SetPaintOverflowFadeout(false); TBWidget* root = GetContentRoot(); TBFontDescription fd; fd.SetID(TBIDC("Vera")); fd.SetSize(12); TBTextField* text = new TBTextField(); text->SetIgnoreInput(true); text->SetText(item->str); text->SetFontDescription(fd); root->AddChild(text); if (item->shortcut_.Length()) { TBWidget* spacer = new TBWidget(); spacer->SetIgnoreInput(true); spacer->SetGravity(WIDGET_GRAVITY_LEFT_RIGHT); root->AddChild(spacer); TBTextField* shortcut = new TBTextField(); shortcut->SetIgnoreInput(true); shortcut->SetText(item->shortcut_.CString()); shortcut->SetFontDescription(fd); shortcut->SetGravity(WIDGET_GRAVITY_RIGHT); root->AddChild(shortcut); } }
void TBTabContainer::SetValue(int index) { if (index == m_current_page || !GetNumPages()) return; m_current_page = index; // Update the pages visibility and tabs pressed value. index = 0; TBWidget *page = m_content_root.GetFirstChild(); TBWidget *tab = m_tab_layout.GetFirstChild(); for ( ; page && tab; page = page->GetNext(), tab = tab->GetNext(), index++) { bool active = index == m_current_page; page->SetVisibilility(active ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE); tab->SetValue(active ? 1 : 0); } TBWidgetEvent ev(EVENT_TYPE_TAB_CHANGED); InvokeEvent(ev); }
int32 TBTextFragmentContentWidget::GetHeight(TBFontFace *font, TBTextFragment *fragment) { return m_widget->GetRect().h ? m_widget->GetRect().h : m_widget->GetPreferredSize().pref_h; }
int32 TBTextFragmentContentWidget::GetWidth(TBFontFace *font, TBTextFragment *fragment) { return m_widget->GetRect().w ? m_widget->GetRect().w : m_widget->GetPreferredSize().pref_w; }
void TBTextFragmentContentWidget::UpdatePos(int x, int y) { m_widget->SetRect(TBRect(x, y, GetWidth(nullptr, nullptr), GetHeight(nullptr, nullptr))); }
bool TBMessageWindow::Show(const char *title, const char *message, TBMessageWindowSettings *settings) { TBWidget *target = m_target.Get(); if (!target) return false; TBMessageWindowSettings default_settings; if (!settings) settings = &default_settings; TBWidget *root = target->GetParentRoot(); const char *source = "TBLayout: axis: y, distribution: available\n" " TBLayout: distribution: available, size: available\n" " TBSkinImage: id: 2\n" " TBEditField: multiline: 1, readonly: 1, id: 1\n" " TBLayout: distribution-position: right bottom, id: 3\n"; if (!g_widgets_reader->LoadData(GetContentRoot(), source)) return false; SetText(title); GetWidgetByIDAndType<TBSkinImage>(2)->SetSkinBg(settings->icon_skin); TBEditField *editfield = GetWidgetByIDAndType<TBEditField>(1); editfield->SetStyling(settings->styling); editfield->SetText(message); editfield->SetSkinBg(""); // Create buttons if (settings->msg == TB_MSG_OK) { AddButton("TBMessageWindow.ok", true); } else if (settings->msg == TB_MSG_OK_CANCEL) { AddButton("TBMessageWindow.ok", true); AddButton("TBMessageWindow.cancel", false); } else if (settings->msg == TB_MSG_YES_NO) { AddButton("TBMessageWindow.yes", true); AddButton("TBMessageWindow.no", false); } // Size to fit content. This will use the default size of the textfield. ResizeToFitContent(); TBRect rect = GetRect(); // Get how much we overflow the textfield has given the current width, and grow our height to show all we can. // FIX: It would be better to use adapt-to-content on the editfield to achieve the most optimal size. // At least when we do full blown multi pass size checking. rect.h += editfield->GetStyleEdit()->GetOverflowY(); // Create background dimmer if (settings->dimmer) { if (TBDimmer *dimmer = new TBDimmer) { root->AddChild(dimmer); m_dimmer.Set(dimmer); } } // Center and size to the new height TBRect bounds(0, 0, root->GetRect().w, root->GetRect().h); SetRect(rect.CenterIn(bounds).MoveIn(bounds).Clip(bounds)); root->AddChild(this); return true; }