TBEditField::TBEditField() : m_edit_type(EDIT_TYPE_TEXT) , m_adapt_to_content_size(false) , m_virtual_width(250) { SetIsFocusable(true); SetWantLongClick(true); AddChild(&m_scrollbar_x); AddChild(&m_scrollbar_y); AddChild(&m_root); m_root.SetGravity(WIDGET_GRAVITY_ALL); m_scrollbar_x.SetGravity(WIDGET_GRAVITY_BOTTOM | WIDGET_GRAVITY_LEFT_RIGHT); m_scrollbar_y.SetGravity(WIDGET_GRAVITY_RIGHT | WIDGET_GRAVITY_TOP_BOTTOM); m_scrollbar_y.SetAxis(AXIS_Y); int scrollbar_y_w = m_scrollbar_y.GetPreferredSize().pref_w; int scrollbar_x_h = m_scrollbar_x.GetPreferredSize().pref_h; m_scrollbar_x.SetRect(TBRect(0, - scrollbar_x_h, - scrollbar_y_w, scrollbar_x_h)); m_scrollbar_y.SetRect(TBRect(- scrollbar_y_w, 0, scrollbar_y_w, 0)); m_scrollbar_x.SetOpacity(0); m_scrollbar_y.SetOpacity(0); SetSkinBg(TBIDC("TBEditField"), WIDGET_INVOKE_INFO_NO_CALLBACKS); m_style_edit.SetListener(this); m_root.SetRect(GetVisibleRect()); m_placeholder.SetTextAlign(TB_TEXT_ALIGN_LEFT); m_content_factory.editfield = this; m_style_edit.SetContentFactory(&m_content_factory); }
void TBBitmapFragmentManager::Debug() { int x = 0; for (int i = 0; i < m_fragment_maps.GetNumItems(); i++) { TBBitmapFragmentMap *fm = m_fragment_maps[i]; if (TBBitmap *bitmap = fm->GetBitmap()) g_renderer->DrawBitmap(TBRect(x, 0, fm->m_bitmap_w, fm->m_bitmap_h), TBRect(0, 0, fm->m_bitmap_w, fm->m_bitmap_h), bitmap); x += fm->m_bitmap_w + 5; } }
void TBRendererBatcher::DrawRect(const TBRect &dst_rect, const TBColor &color) { if (dst_rect.IsEmpty()) return; // Top DrawRectFill(TBRect(dst_rect.x, dst_rect.y, dst_rect.w, 1), color); // Bottom DrawRectFill(TBRect(dst_rect.x, dst_rect.y + dst_rect.h - 1, dst_rect.w, 1), color); // Left DrawRectFill(TBRect(dst_rect.x, dst_rect.y + 1, 1, dst_rect.h - 2), color); // Right DrawRectFill(TBRect(dst_rect.x + dst_rect.w - 1, dst_rect.y + 1, 1, dst_rect.h - 2), color); }
void TBScrollContainer::ValidateLayout(const SizeConstraints &constraints) { if (!m_layout_is_invalid) return; m_layout_is_invalid = false; // Layout scrollbars (no matter if they are visible or not) int scrollbar_y_w = m_scrollbar_y.GetPreferredSize().pref_w; int scrollbar_x_h = m_scrollbar_x.GetPreferredSize().pref_h; m_scrollbar_x.SetRect(TBRect(0, GetRect().h - scrollbar_x_h, GetRect().w - scrollbar_y_w, scrollbar_x_h)); m_scrollbar_y.SetRect(TBRect(GetRect().w - scrollbar_y_w, 0, scrollbar_y_w, GetRect().h)); if (TBWidget *content_child = m_root.GetFirstChild()) { int horizontal_padding = TBScrollBarVisibility::IsAlwaysOnY(m_mode) ? scrollbar_y_w : 0; int vertical_padding = TBScrollBarVisibility::IsAlwaysOnX(m_mode) ? scrollbar_x_h : 0; SizeConstraints inner_sc = constraints.ConstrainByPadding(horizontal_padding, vertical_padding); PreferredSize ps = content_child->GetPreferredSize(inner_sc); TBScrollBarVisibility visibility = TBScrollBarVisibility::Solve(m_mode, ps.pref_w, ps.pref_h, GetRect().w, GetRect().h, scrollbar_x_h, scrollbar_y_w); m_scrollbar_x.SetOpacity(visibility.x_on ? 1.f : 0.f); m_scrollbar_y.SetOpacity(visibility.y_on ? 1.f : 0.f); m_root.SetRect(TBRect(0, 0, visibility.visible_w, visibility.visible_h)); int content_w, content_h; if (m_adapt_content_size) { content_w = MAX(ps.pref_w, m_root.GetRect().w); content_h = MAX(ps.pref_h, m_root.GetRect().h); if (!visibility.x_on && m_root.GetRect().w < ps.pref_w) content_w = MIN(ps.pref_w, m_root.GetRect().w); } else { content_w = ps.pref_w; content_h = ps.pref_h; } content_child->SetRect(TBRect(0, 0, content_w, content_h)); double limit_max_w = MAX(0, content_w - m_root.GetRect().w); double limit_max_h = MAX(0, content_h - m_root.GetRect().h); m_scrollbar_x.SetLimits(0, limit_max_w, m_root.GetRect().w); m_scrollbar_y.SetLimits(0, limit_max_h, m_root.GetRect().h); } }
void TBWidgetAnimationRect::OnAnimationUpdate(float progress) { if (m_mode == MODE_DELTA_IN || m_mode == MODE_DELTA_OUT) { m_dst_rect = m_src_rect = m_widget->GetRect(); if (m_dst_rect.Equals(TBRect())) { // Widget hasn't been laid out yet, // the animation was started too soon. TBAnimationManager::AbortAnimation(this, true); return; } if (m_mode == MODE_DELTA_IN) { m_dst_rect.x += m_delta_rect.x; m_dst_rect.y += m_delta_rect.y; m_dst_rect.w += m_delta_rect.w; m_dst_rect.h += m_delta_rect.h; } else { m_src_rect.x += m_delta_rect.x; m_src_rect.y += m_delta_rect.y; m_src_rect.w += m_delta_rect.w; m_src_rect.h += m_delta_rect.h; } m_mode = MODE_SRC_TO_DST; } TBRect rect; rect.x = (int) LERP(m_src_rect.x, m_dst_rect.x, progress); rect.y = (int) LERP(m_src_rect.y, m_dst_rect.y, progress); rect.w = (int) LERP(m_src_rect.w, m_dst_rect.w, progress); rect.h = (int) LERP(m_src_rect.h, m_dst_rect.h, progress); m_widget->SetRect(rect); }
bool TBWidgetsAnimationManager::OnWidgetDying(TBWidget *widget) { bool handled = false; if (TBWindow *window = TBSafeCast<TBWindow>(widget)) { // Fade out dying windows if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(window, 1.f, TB_ALMOST_ZERO_OPACITY, true)) TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER); handled = true; } if (TBMessageWindow *window = TBSafeCast<TBMessageWindow>(widget)) { // Move out dying message windows if (TBAnimationObject *anim = new TBWidgetAnimationRect(window, TBRect(0, 50, 0, 0), TBWidgetAnimationRect::MODE_DELTA_IN)) TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_SPEED_UP); handled = true; } if (TBDimmer *dimmer = TBSafeCast<TBDimmer>(widget)) { // Fade out dying dim layers if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(dimmer, 1.f, TB_ALMOST_ZERO_OPACITY, true)) TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER); handled = true; } return handled; }
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); }
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(); 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); }
void TBRendererBatcher::DrawRectFill(const TBRect &dst_rect, const TBColor &color) { if (dst_rect.IsEmpty()) return; uint32 a = (color.a * m_opacity) / 255; AddQuadInternal(dst_rect.Offset(m_translation_x, m_translation_y), TBRect(), VER_COL(color.r, color.g, color.b, a), nullptr, nullptr); }
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); }
TBRect TBScrollContainer::GetPaddingRect() { int visible_w = GetRect().w; int visible_h = GetRect().h; if (m_scrollbar_x.GetOpacity()) visible_h -= m_scrollbar_x.GetPreferredSize().pref_h; if (m_scrollbar_y.GetOpacity()) visible_w -= m_scrollbar_y.GetPreferredSize().pref_w; return TBRect(0, 0, visible_w, visible_h); }
void DrawEdgeFadeout( TBSkin* skin, const TBRect &dst_rect, TBID skin_x, TBID skin_y, int left, int top, int right, int bottom) { if (TBSkinElement *element = skin->GetSkinElement(skin_x)) { if (element->bitmap) { int bw = element->bitmap->Width(); int bh = element->bitmap->Height(); int dw; if ((dw = GetFadeoutSize(left, bw)) > 0) g_renderer->DrawBitmap(TBRect(dst_rect.x, dst_rect.y, dw, dst_rect.h), TBRect(0, 0, bw, bh), element->bitmap); if ((dw = GetFadeoutSize(right, bw)) > 0) g_renderer->DrawBitmap(TBRect(dst_rect.x + dst_rect.w - dw, dst_rect.y, dw, dst_rect.h), TBRect(bw, 0, -bw, bh), element->bitmap); } } if (TBSkinElement *element = skin->GetSkinElement(skin_y)) { if (element->bitmap) { int bw = element->bitmap->Width(); int bh = element->bitmap->Height(); int dh; if ((dh = GetFadeoutSize(top, bh)) > 0) g_renderer->DrawBitmap(TBRect(dst_rect.x, dst_rect.y, dst_rect.w, dh), TBRect(0, 0, bw, bh), element->bitmap); if ((dh = GetFadeoutSize(bottom, bh)) > 0) g_renderer->DrawBitmap(TBRect(dst_rect.x, dst_rect.y + dst_rect.h - dh, dst_rect.w, dh), TBRect(0, bh, bw, -bh), element->bitmap); } } }
void TBProgressSpinner::OnPaint(const PaintProps &paint_props) { if (IsRunning()) { TBSkinElement *e = g_tb_skin->GetSkinElement(m_skin_fg); if (e && e->bitmap) { int size = e->bitmap->Height(); int num_frames = e->bitmap->Width() / e->bitmap->Height(); int current_frame = m_frame % num_frames; g_renderer->DrawBitmap(GetPaddingRect(), TBRect(current_frame * size, 0, size, size), e->bitmap); } } }
ResourceEditWindow::ResourceEditWindow() : m_widget_list(nullptr) , m_scroll_container(nullptr) , m_build_container(nullptr) , m_source_edit(nullptr) { // Register as global listener to intercept events in the build container TBWidgetListener::AddGlobalListener(this); g_widgets_reader->LoadFile(this, "Demo/demo01/ui_resources/resource_edit_window.tb.txt"); m_scroll_container = GetWidgetByIDAndType<TBScrollContainer>(TBIDC("scroll_container")); m_build_container = m_scroll_container->GetContentRoot(); m_source_edit = GetWidgetByIDAndType<TBEditField>(TBIDC("source_edit")); m_widget_list = GetWidgetByIDAndType<TBSelectList>(TBIDC("widget_list")); m_widget_list->SetSource(&m_widget_list_source); SetRect(TBRect(100, 50, 900, 600)); }
void TBWidgetsAnimationManager::OnWidgetAdded(TBWidget *parent, TBWidget *widget) { if (TBWindow *window = TBSafeCast<TBWindow>(widget)) { // Fade in new windows if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(window, TB_ALMOST_ZERO_OPACITY, 1.f, false)) TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER); } if (TBMessageWindow *window = TBSafeCast<TBMessageWindow>(widget)) { // Move in new message windows if (TBAnimationObject *anim = new TBWidgetAnimationRect(window, TBRect(0, -50, 0, 0), TBWidgetAnimationRect::MODE_DELTA_OUT)) TBAnimationManager::StartAnimation(anim); } if (TBDimmer *dimmer = TBSafeCast<TBDimmer>(widget)) { // Fade in dim layer if (TBAnimationObject *anim = new TBWidgetAnimationOpacity(dimmer, TB_ALMOST_ZERO_OPACITY, 1.f, false)) TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_BEZIER); } }
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 TBFontFace::DrawString(int x, int y, const TBColor &color, const char *str, int len) { if (m_bgFont) m_bgFont->DrawString(x+m_bgX, y+m_bgY, m_bgColor, str, len); if (m_font_renderer) g_renderer->BeginBatchHint(TBRenderer::BATCH_HINT_DRAW_BITMAP_FRAGMENT); int i = 0; while (str[i] && i < len) { UCS4 cp = utf8::decode_next(str, &i, len); if (cp == 0xFFFF) continue; if (TBFontGlyph *glyph = GetGlyph(cp, true)) { if (glyph->frag) { TBRect dst_rect(x + glyph->metrics.x, y + glyph->metrics.y + GetAscent(), glyph->frag->Width(), glyph->frag->Height()); TBRect src_rect(0, 0, glyph->frag->Width(), glyph->frag->Height()); if (glyph->has_rgb) g_renderer->DrawBitmap(dst_rect, src_rect, glyph->frag); else g_renderer->DrawBitmapColored(dst_rect, src_rect, color, glyph->frag); } x += glyph->metrics.advance; } else if (!m_font_renderer) // This is the test font. Use same glyph width as height and draw square. { g_renderer->DrawRect(TBRect(x, y, m_metrics.height / 3, m_metrics.height), color); x += m_metrics.height / 3 + 1; } } if (m_font_renderer) g_renderer->EndBatchHint(); }
void TBDimmer::OnAdded() { SetRect(TBRect(0, 0, GetParent()->GetRect().w, GetParent()->GetRect().h)); }
void TBImageWidget::OnPaint(const PaintProps &paint_props) { if (TBBitmapFragment *fragment = m_image.GetBitmap()) g_renderer->DrawBitmap(GetPaddingRect(), TBRect(0, 0, m_image.Width(), m_image.Height()), fragment); }
void TBRendererBatcher::DrawBitmapTile(const TBRect &dst_rect, TBBitmap *bitmap) { AddQuadInternal(dst_rect.Offset(m_translation_x, m_translation_y), TBRect(0, 0, dst_rect.w, dst_rect.h), VER_COL_OPACITY(m_opacity), bitmap, nullptr); }
void TBTextFragmentContentWidget::UpdatePos(int x, int y) { m_widget->SetRect(TBRect(x, y, GetWidth(nullptr, nullptr), GetHeight(nullptr, nullptr))); }
TBRect RotRect(const TBRect &rect, AXIS axis) { if (axis == AXIS_X) return rect; return TBRect(rect.y, rect.x, rect.h, rect.w); }