TBInlineSelect::TBInlineSelect() : m_value(0) , m_min(0) , m_max(100) , m_modified(false) { SetSkinBg(TBIDC("TBInlineSelect")); AddChild(&m_layout); m_layout.AddChild(&m_buttons[0]); m_layout.AddChild(&m_editfield); m_layout.AddChild(&m_buttons[1]); m_layout.SetRect(GetPaddingRect()); m_layout.SetGravity(WIDGET_GRAVITY_ALL); m_layout.SetSpacing(0); m_buttons[0].SetSkinBg(TBIDC("TBButton.flat")); m_buttons[1].SetSkinBg(TBIDC("TBButton.flat")); m_buttons[0].GetContentRoot()->AddChild(new TBSkinImage(TBIDC("arrowdark.left"))); m_buttons[1].GetContentRoot()->AddChild(new TBSkinImage(TBIDC("arrowdark.right"))); m_buttons[0].SetIsFocusable(false); m_buttons[1].SetIsFocusable(false); m_buttons[0].SetID(TBIDC("dec")); m_buttons[1].SetID(TBIDC("inc")); m_buttons[0].SetAutoRepeat(true); m_buttons[1].SetAutoRepeat(true); m_editfield.SetID(TBIDC("edit")); m_editfield.SetTextAlign(TB_TEXT_ALIGN_CENTER); m_editfield.SetEditType(EDIT_TYPE_NUMBER); m_editfield.SetText("0"); m_editfield.AddListener(this); }
TBClickLabel::TBClickLabel() { AddChild(&m_layout); m_layout.AddChild(&m_textfield); m_layout.SetRect(GetPaddingRect()); m_layout.SetGravity(WIDGET_GRAVITY_ALL); m_layout.SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP); }
TBRect TBEditField::GetVisibleRect() { TBRect rect = GetPaddingRect(); if (m_scrollbar_y.GetOpacity()) rect.w -= m_scrollbar_y.GetRect().w; if (m_scrollbar_x.GetOpacity()) rect.h -= m_scrollbar_x.GetRect().h; return rect; }
void TBEditFieldScrollRoot::OnPaintChildren(const PaintProps &paint_props) { // Avoid setting clipping (can be expensive) if we have no children to paint anyway. if (!GetFirstChild()) return; // Clip children TBRect old_clip_rect = g_renderer->SetClipRect(GetPaddingRect(), true); TBWidget::OnPaintChildren(paint_props); g_renderer->SetClipRect(old_clip_rect, false); }
TBMenuWindow::TBMenuWindow(TBWidget *target, TBID id) : TBPopupWindow(target) { SetID(id); SetSkinBg(TBIDC("TBMenuWindow"), WIDGET_INVOKE_INFO_NO_CALLBACKS); m_select_list.GetScrollContainer()->SetAdaptToContentSize(true); m_select_list.SetIsFocusable(false); ///< Avoid it autoclosing its window on click m_select_list.SetSkinBg(""); m_select_list.SetRect(GetPaddingRect()); m_select_list.SetGravity(WIDGET_GRAVITY_ALL); AddChild(&m_select_list); }
void TBLayout::OnPaintChildren(const PaintProps &paint_props) { TBRect padding_rect = GetPaddingRect(); if (padding_rect.IsEmpty()) return; // If we overflow the layout, apply clipping when painting children TBRect old_clip_rect; if (m_overflow) { // We only want clipping in one axis (the overflowing one) so we // don't damage any expanded skins on the other axis. Add some fluff. TBRect clip_rect = padding_rect; const int fluff = 100; if (m_axis == AXIS_X) clip_rect = clip_rect.Expand(m_overflow_scroll == 0 ? fluff : 0, fluff, m_overflow_scroll == m_overflow ? fluff : 0, fluff); else clip_rect = clip_rect.Expand(fluff, m_overflow_scroll == 0 ? fluff : 0, fluff, m_overflow_scroll == m_overflow ? fluff : 0); old_clip_rect = g_renderer->SetClipRect(clip_rect, true); TB_IF_DEBUG_SETTING(LAYOUT_CLIPPING, g_renderer->DrawRect(clip_rect, TBColor(255, 0, 0, 200))); } // Paint children TBWidget::OnPaintChildren(paint_props); // Paint fadeout image over the overflowed edges // to the indicate to used that it's overflowed. if (m_overflow && m_packed.paint_overflow_fadeout) { TBID skin_x, skin_y; if (m_axis == AXIS_X) skin_x = TBIDC("TBLayout.fadeout_x"); else skin_y = TBIDC("TBLayout.fadeout_y"); DrawEdgeFadeout(padding_rect, skin_x, skin_y, m_overflow_scroll, m_overflow_scroll, m_overflow - m_overflow_scroll, m_overflow - m_overflow_scroll); } // Restore clipping if (m_overflow) g_renderer->SetClipRect(old_clip_rect, false); }
bool TBScrollContainer::OnEvent(const TBWidgetEvent &ev) { if (ev.type == EVENT_TYPE_CHANGED && (ev.target == &m_scrollbar_x || ev.target == &m_scrollbar_y)) { Invalidate(); OnScroll(m_scrollbar_x.GetValue(), m_scrollbar_y.GetValue()); return true; } else if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE) { double old_val = m_scrollbar_y.GetValueDouble(); m_scrollbar_y.SetValueDouble(old_val + ev.delta_y * TBSystem::GetPixelsPerLine()); return m_scrollbar_y.GetValueDouble() != old_val; } else if (ev.type == EVENT_TYPE_KEY_DOWN) { if (ev.special_key == TB_KEY_LEFT && m_scrollbar_x.CanScrollNegative()) ScrollBySmooth(-TBSystem::GetPixelsPerLine(), 0); else if (ev.special_key == TB_KEY_RIGHT && m_scrollbar_x.CanScrollPositive()) ScrollBySmooth(TBSystem::GetPixelsPerLine(), 0); else if (ev.special_key == TB_KEY_UP && m_scrollbar_y.CanScrollNegative()) ScrollBySmooth(0, -TBSystem::GetPixelsPerLine()); else if (ev.special_key == TB_KEY_DOWN && m_scrollbar_y.CanScrollPositive()) ScrollBySmooth(0, TBSystem::GetPixelsPerLine()); else if (ev.special_key == TB_KEY_PAGE_UP && m_scrollbar_y.CanScrollNegative()) ScrollBySmooth(0, -GetPaddingRect().h); else if (ev.special_key == TB_KEY_PAGE_DOWN && m_scrollbar_y.CanScrollPositive()) ScrollBySmooth(0, GetPaddingRect().h); else if (ev.special_key == TB_KEY_HOME) ScrollToSmooth(m_scrollbar_x.GetValue(), 0); else if (ev.special_key == TB_KEY_END) ScrollToSmooth(m_scrollbar_x.GetValue(), (int)m_scrollbar_y.GetMaxValue()); else return false; return true; } return false; }
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); } } }
void GLWidget::OnPaint(const PaintProps &paint_props) { if (!init) { initGL(); init = true; } GLint v[4]; glGetIntegerv(GL_VIEWPORT, v); int dx, dy; tb::g_renderer->GetTranslate(&dx, &dy); tb::g_renderer->BeginNativeRender(); tb::TBRect r = GetRect(); tb::TBRect padr = GetPaddingRect(); glViewport(dx+padr.x, (v[3]-(dy+r.h))+padr.y, padr.w, padr.h); render(); tb::g_renderer->EndNativeRender(); }
TBButton::TBButton() : m_auto_repeat_click(false) , m_toggle_mode(false) { SetIsFocusable(true); SetClickByKey(true); SetSkinBg(TBIDC("TBButton"), WIDGET_INVOKE_INFO_NO_CALLBACKS); AddChild(&m_layout); // Set the textfield gravity to all, even though it would display the same with default gravity. // This will make the buttons layout expand if there is space available, without forcing the parent // layout to grow to make the space available. m_textfield.SetGravity(WIDGET_GRAVITY_ALL); m_layout.AddChild(&m_textfield); m_layout.SetRect(GetPaddingRect()); m_layout.SetGravity(WIDGET_GRAVITY_ALL); m_layout.SetPaintOverflowFadeout(false); }
void TBScrollContainerRoot::OnPaintChildren(const PaintProps &paint_props) { // We only want clipping in one axis (the overflowing one) so we // don't damage any expanded skins on the other axis. Add some fluff. const int fluff = 100; TBScrollContainer *sc = static_cast<TBScrollContainer *>(GetParent()); TBRect clip_rect = GetPaddingRect().Expand(sc->m_scrollbar_x.CanScrollNegative() ? 0 : fluff, sc->m_scrollbar_y.CanScrollNegative() ? 0 : fluff, sc->m_scrollbar_x.CanScrollPositive() ? 0 : fluff, sc->m_scrollbar_y.CanScrollPositive() ? 0 : fluff); TBRect old_clip_rect = g_renderer->SetClipRect(clip_rect, true); TB_IF_DEBUG_SETTING(LAYOUT_CLIPPING, g_renderer->DrawRect(clip_rect, TBColor(255, 0, 0, 200))); TBWidget::OnPaintChildren(paint_props); g_renderer->SetClipRect(old_clip_rect, false); }
TBSelectList::TBSelectList() : m_value(-1) , m_list_is_invalid(false) , m_scroll_to_current(false) , m_header_lng_string_id(TBIDC("TBList.header")) { SetSource(&m_default_source); SetIsFocusable(true); SetSkinBg(TBIDC("TBSelectList"), WIDGET_INVOKE_INFO_NO_CALLBACKS); m_container.SetGravity(WIDGET_GRAVITY_ALL); m_container.SetRect(GetPaddingRect()); AddChild(&m_container); m_layout.SetGravity(WIDGET_GRAVITY_ALL); m_layout.SetAxis(AXIS_Y); m_layout.SetSpacing(0); m_layout.SetLayoutPosition(LAYOUT_POSITION_LEFT_TOP); m_layout.SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP); m_layout.SetLayoutSize(LAYOUT_SIZE_AVAILABLE); m_container.GetContentRoot()->AddChild(&m_layout); m_container.SetScrollMode(SCROLL_MODE_Y_AUTO); m_container.SetAdaptContentSize(true); }
void TBInlineSelect::OnSkinChanged() { m_layout.SetRect(GetPaddingRect()); }
bool TBEditField::OnEvent(const TBWidgetEvent &ev) { if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_scrollbar_x) { m_style_edit.SetScrollPos(m_scrollbar_x.GetValue(), m_style_edit.scroll_y); OnScroll(m_scrollbar_x.GetValue(), m_style_edit.scroll_y); return true; } else if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_scrollbar_y) { m_style_edit.SetScrollPos(m_style_edit.scroll_x, m_scrollbar_y.GetValue()); OnScroll(m_style_edit.scroll_x, m_scrollbar_y.GetValue()); return true; } else if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE) { int old_val = m_scrollbar_y.GetValue(); m_scrollbar_y.SetValue(old_val + ev.delta_y * TBSystem::GetPixelsPerLine()); return m_scrollbar_y.GetValue() != old_val; } else if (ev.type == EVENT_TYPE_POINTER_DOWN && ev.target == this) { TBRect padding_rect = GetPaddingRect(); if (m_style_edit.MouseDown( TBPoint(ev.target_x - padding_rect.x, ev.target_y - padding_rect.y), 1, ev.count, TB_MODIFIER_NONE, ev.touch)) { // Post a message to start selection scroll PostMessageDelayed(TBIDC("selscroll"), nullptr, SELECTION_SCROLL_DELAY); return true; } } else if (ev.type == EVENT_TYPE_POINTER_MOVE && ev.target == this) { TBRect padding_rect = GetPaddingRect(); return m_style_edit.MouseMove(TBPoint(ev.target_x - padding_rect.x, ev.target_y - padding_rect.y)); } else if (ev.type == EVENT_TYPE_POINTER_UP && ev.target == this) { TBRect padding_rect = GetPaddingRect(); return m_style_edit.MouseUp(TBPoint(ev.target_x - padding_rect.x, ev.target_y - padding_rect.y), 1, TB_MODIFIER_NONE, ev.touch); } else if (ev.type == EVENT_TYPE_KEY_DOWN) { return m_style_edit.KeyDown(ev.key, ev.special_key, ev.modifierkeys); } else if (ev.type == EVENT_TYPE_KEY_UP) { return true; } else if ((ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == TBIDC("popupmenu")) || (ev.type == EVENT_TYPE_SHORTCUT)) { if (ev.ref_id == TBIDC("cut") && !m_style_edit.packed.read_only) m_style_edit.Cut(); else if (ev.ref_id == TBIDC("copy")) m_style_edit.Copy(); else if (ev.ref_id == TBIDC("paste") && !m_style_edit.packed.read_only) m_style_edit.Paste(); else if (ev.ref_id == TBIDC("delete") && !m_style_edit.packed.read_only) m_style_edit.Delete(); else if (ev.ref_id == TBIDC("undo") && !m_style_edit.packed.read_only) m_style_edit.Undo(); else if (ev.ref_id == TBIDC("redo") && !m_style_edit.packed.read_only) m_style_edit.Redo(); else if (ev.ref_id == TBIDC("selectall")) m_style_edit.selection.SelectAll(); else return false; return true; } else if (ev.type == EVENT_TYPE_CONTEXT_MENU && ev.target == this) { TBPoint pos_in_root(ev.target_x, ev.target_y); ev.target->ConvertToRoot(pos_in_root.x, pos_in_root.y); if (TBMenuWindow *menu = new TBMenuWindow(ev.target, TBIDC("popupmenu"))) { TBGenericStringItemSource *source = menu->GetList()->GetDefaultSource(); source->AddItem(new TBGenericStringItem(g_tb_lng->GetString(TBIDC("cut")), TBIDC("cut"))); source->AddItem(new TBGenericStringItem(g_tb_lng->GetString(TBIDC("copy")), TBIDC("copy"))); source->AddItem(new TBGenericStringItem(g_tb_lng->GetString(TBIDC("paste")), TBIDC("paste"))); source->AddItem(new TBGenericStringItem(g_tb_lng->GetString(TBIDC("delete")), TBIDC("delete"))); source->AddItem(new TBGenericStringItem("-")); source->AddItem(new TBGenericStringItem(g_tb_lng->GetString(TBIDC("selectall")), TBIDC("selectall"))); menu->Show(source, TBPopupAlignment(pos_in_root), -1); } return true; } return false; }
void TBSelectList::OnSkinChanged() { m_container.SetRect(GetPaddingRect()); }
void TBButton::OnSkinChanged() { m_layout.SetRect(GetPaddingRect()); }
void TBTextField::OnPaint(const PaintProps &paint_props) { m_text.Paint(this, GetPaddingRect(), paint_props.text_color); }
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 TBLayout::ValidateLayout(const SizeConstraints &constraints, PreferredSize *calculate_ps) { // Layout notes: // -All layout code is written for AXIS_X layout. // Instead of duplicating the layout code for both AXIS_X and AXIS_Y, we simply // rotate the in data (rect, gravity, preferred size) and the outdata (rect). if (!calculate_ps) { if (!m_packed.layout_is_invalid) return; m_packed.layout_is_invalid = 0; } else { // Maximum size will grow below depending of the childrens maximum size calculate_ps->max_w = calculate_ps->max_h = 0; } const int spacing = CalculateSpacing(); const TBRect padding_rect = GetPaddingRect(); const TBRect layout_rect = RotRect(padding_rect, m_axis); const SizeConstraints inner_sc = constraints.ConstrainByPadding(GetRect().w - padding_rect.w, GetRect().h - padding_rect.h); // Calculate totals for minimum and preferred width that we need for layout. int total_preferred_w = 0; int total_min_pref_diff_w = 0; int total_max_pref_diff_w = 0; for (TBWidget *child = GetFirstInLayoutOrder(); child; child = GetNextInLayoutOrder(child)) { if (child->GetVisibility() == WIDGET_VISIBILITY_GONE) continue; const int ending_space = GetTrailingSpace(child, spacing); const PreferredSize ps = RotPreferredSize(child->GetPreferredSize(inner_sc), m_axis); const WIDGET_GRAVITY gravity = RotGravity(child->GetGravity(), m_axis); total_preferred_w += ps.pref_w + ending_space; total_min_pref_diff_w += ps.pref_w - ps.min_w; if (QualifyForExpansion(gravity)) { int capped_max_w = MIN(layout_rect.w, ps.max_w); total_max_pref_diff_w += capped_max_w - ps.pref_w; } if (calculate_ps) { calculate_ps->min_h = MAX(calculate_ps->min_h, ps.min_h); calculate_ps->pref_h = MAX(calculate_ps->pref_h, ps.pref_h); calculate_ps->min_w += ps.min_w + ending_space; calculate_ps->pref_w += ps.pref_w + ending_space; calculate_ps->max_w += ps.max_w + ending_space; // The widget height depends on layout and widget properties, so get what // it would actually use if it was given max_h as available height. // If we just used its max_h, that could increase the whole layout size // even if the widget wouldn't actually use it. int height = GetWantedHeight(gravity, ps, ps.max_h); calculate_ps->max_h = MAX(calculate_ps->max_h, height); calculate_ps->size_dependency |= ps.size_dependency; } } if (calculate_ps) { // We just wanted to calculate preferred size, so return without layouting. *calculate_ps = RotPreferredSize(*calculate_ps, m_axis); return; } TB_IF_DEBUG_SETTING(LAYOUT_PS_DEBUGGING, last_layout_time = TBSystem::GetTimeMS()); // Pre Layout step (calculate distribution position) int missing_space = MAX(total_preferred_w - layout_rect.w, 0); int extra_space = MAX(layout_rect.w - total_preferred_w, 0); int offset = layout_rect.x; if (extra_space && m_packed.layout_mode_dist_pos != LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP) { // To calculate the offset we need to predict the used space. We can do that by checking // the distribution mode and total_max_pref_diff_w. That's how much the widgets could possible // expand in the layout below. int used_space = total_preferred_w; if (m_packed.layout_mode_dist != LAYOUT_DISTRIBUTION_PREFERRED) used_space += MIN(extra_space, total_max_pref_diff_w); if (m_packed.layout_mode_dist_pos == LAYOUT_DISTRIBUTION_POSITION_CENTER) offset += (layout_rect.w - used_space) / 2; else // LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM offset += layout_rect.w - used_space; } // Layout int used_space = 0; for (TBWidget *child = GetFirstInLayoutOrder(); child; child = GetNextInLayoutOrder(child)) { if (child->GetVisibility() == WIDGET_VISIBILITY_GONE) continue; const int ending_space = GetTrailingSpace(child, spacing); const PreferredSize ps = RotPreferredSize(child->GetPreferredSize(inner_sc), m_axis); const WIDGET_GRAVITY gravity = RotGravity(child->GetGravity(), m_axis); // Calculate width. May shrink if space is missing, or grow if we have extra space. int width = ps.pref_w; if (missing_space && total_min_pref_diff_w) { int diff_w = ps.pref_w - ps.min_w; float factor = (float)diff_w / (float)total_min_pref_diff_w; int removed = (int)(missing_space * factor); removed = MIN(removed, diff_w); width -= removed; total_min_pref_diff_w -= diff_w; missing_space -= removed; } else if (extra_space && total_max_pref_diff_w && QualifyForExpansion(gravity)) { int capped_max_w = MIN(layout_rect.w, ps.max_w); int diff_w = capped_max_w - ps.pref_w; float factor = (float)diff_w / (float)total_max_pref_diff_w; int added = (int)(extra_space * factor); added = MIN(added, diff_w); width += added; total_max_pref_diff_w -= capped_max_w - ps.pref_w; extra_space -= added; } // Calculate height int available_height = layout_rect.h; int height = GetWantedHeight(gravity, ps, available_height); // Calculate position int pos = layout_rect.y; switch (m_packed.layout_mode_pos) { case LAYOUT_POSITION_CENTER: pos += (available_height - height) / 2; break; case LAYOUT_POSITION_RIGHT_BOTTOM: pos += available_height - height; break; case LAYOUT_POSITION_GRAVITY: if ((gravity & WIDGET_GRAVITY_TOP) && (gravity & WIDGET_GRAVITY_BOTTOM)) pos += (available_height - height) / 2; else if (gravity & WIDGET_GRAVITY_BOTTOM) pos += available_height - height; break; default: // LAYOUT_POSITION_LEFT_TOP break; } // Done! Set rect and increase used space TBRect rect(used_space + offset, pos, width, height); used_space += width + ending_space; child->SetRect(RotRect(rect, m_axis)); } // Update overflow and overflow scroll m_overflow = MAX(0, used_space - layout_rect.w); SetOverflowScroll(m_overflow_scroll); }