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);

}
예제 #2
0
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);
}
예제 #3
0
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;
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #8
0
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);
		}
	}
}
예제 #9
0
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();
}
예제 #10
0
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);
}
예제 #11
0
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);
}
예제 #12
0
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());
}
예제 #14
0
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;
}
예제 #15
0
void TBSelectList::OnSkinChanged()
{
    m_container.SetRect(GetPaddingRect());
}
예제 #16
0
void TBButton::OnSkinChanged()
{
	m_layout.SetRect(GetPaddingRect());
}
예제 #17
0
void TBTextField::OnPaint(const PaintProps &paint_props)
{
	m_text.Paint(this, GetPaddingRect(), paint_props.text_color);
}
예제 #18
0
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);
}
예제 #19
0
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);
}