scrollable_panel = {}

__inherite(scrollable_panel, null_lua_widget_handler())

function scrollable_panel.__CreateInstance()
    return "scrollable_panel"
end

-- scrollable_panel - виджет с прокручивающимся содержимым
-- состоит из 2 элементов:
-- 1. вложенный виджет, который хранит содержимое. называет "content";
-- 2. вертикальный скроллбар, который отвечает за прокрутку содержимого. называет "scroll".
-- прокрутка осуществлется перемещением виджета content вверх и вниз.
-- скролл появляется автоматически, когда высота содержимого станет больше высоты самого scrollable_panel.
-- на виджет content могут добавляться любые другие виджеты. после каждого нового добавления
-- размер content'а пересчитывается и параметры scroll'а обновляются.
-- добавление виджетов на content осуществляется вызовом функции scrollable_panel.AddContentWidget(_this, _widget_ptr)

scrollable_panel.params = 
{
	items_count = 5
}

function scrollable_panel.Load(_this, _info, _templates)
	
	_this.AddFlags(_this.FlagClipDraw)
		
	local size = _this.GetSize()
	
	local content = sf.gui.CWidget("content", 0, 0)
	content.SetOffset(0,0)
	content.SetSize(size.X, size.Y)
	
	local content_ptr = sf.gui.CWidgetPtrT(content)
	_this.AddWidget(content_ptr)
	
	local scroll = sf.gui.CScrollWidget(
		sf.graphics.CImage(""),sf.graphics.CImage(""), sf.graphics.CImage(""), sf.graphics.CImage(""), true, "scroll", 0, 0)
	local info = sf.core.CSettingsGroup("")
	info.AddValue("scroll_template", "achievments_scroll")
	scroll.Load(info, _templates)
	
	scroll.AddFlags(sf.misc.BitwiseOr(scroll.FlagHidden, scroll.FlagDisabled))
	scroll.SetValue(0)
	scroll.SetAnchors(sf.misc.BitwiseOr(sf.misc.BitwiseOr(scroll.AnchorRight, scroll.AnchorTop), scroll.AnchorBottom))
	scroll.SetOffset(size.X-scroll.GetSize().X, 0)
	scroll.SetSize(0, size.Y)
	
	local scroll_ptr = sf.gui.CScrollWidgetPtrT(scroll)
	_this.AddWidget(scroll_ptr)
end

function scrollable_panel.DoUpdate(_this)
	return false
end

function scrollable_panel.DoDraw(_this, _renderer)
    return false
end

function scrollable_panel.OnMouseMove(_this, _pos, _state, _broadcast)
    return true
end

function scrollable_panel.OnMouseUp(_this, _pos, _button, _state, _broadcast)
    return false
end

function scrollable_panel.OnMouseDown(_this, _pos, _button, _state, _broadcast)
    return false
end

function scrollable_panel.OnDoubleClick(_this, _pos, _state, _broadcast)
    return true
end

function scrollable_panel.OnMouseWheel(_this, _pos, _delta, _state, _broadcast)

	local content = _this.GetWidget("content", false).get()
	__assert(content, "ошибка в scrollable_panel.OnMouseWheel: не найден виджет content")

	local scroll = __cast(_this.GetWidget("scroll", false).get(), sf.gui.CScrollWidget)
	__assert(scroll, "ошибка в scrollable_panel.OnMouseWheel: не найден виджет scroll")
	
	local page_size = _this.GetSize().Y
	local content_size = content.GetSize().Y

	if (page_size >= content_size) then
		return false
	end

	local delta_value =  _delta * (content_size-page_size) / scrollable_panel.params.items_count
	local value = scroll.GetValue() - delta_value
	scroll.SetValue(value)
	
	return true
end

function scrollable_panel.OnChildAction(_this, _action, _child)

	if _action.c_str() == "value_changed" then
		
		local content = _this.GetWidget("content", false).get()
		__assert(content, "ошибка в scrollable_panel.OnChildAction: не найден виджет content")
		
		local scroll = __cast(_child, sf.gui.CScrollWidget)
		__assert(scroll, "ошибка в scrollable_panel.OnChildAction: не найден виджет scroll")
		
		content.SetOffset(0, -scroll.GetValue())
		
		return true
	end
	return false
end

function scrollable_panel.AddContentWidget(_this, _widget_ptr, _update_size)

	local content = _this.GetWidget("content", false).get()
	__assert(content, "ошибка в scrollable_panel.AddContentWidget: не найден виджет content")
	
	content.AddWidget(_widget_ptr)
	
	if _update_size then
		scrollable_panel._UpdateContentSize(_this)
		scrollable_panel._UpdateScroll(_this)
	end
end

function scrollable_panel.UpdateSize(_this)
	scrollable_panel._UpdateContentSize(_this)
	scrollable_panel._UpdateScroll(_this)
end

function scrollable_panel._UpdateContentSize(_this)

	local content = _this.GetWidget("content", false).get()
	__assert(content, "ошибка в scrollable_panel._UpdateContentSize: не найден виджет content")
	
	local widgets = content.GetWidgets()
	local size = content.GetSize()
	local max_y = 0
	while (not widgets.IsEnd()) do
		local w = widgets.Get().get()
		local bottom = w.GetOffset().Y + w.GetSize().Y
		if bottom > max_y then
			max_y = bottom
		end
		widgets.Next()
	end
	content.SetSize(size.X, max_y)
end

function scrollable_panel._UpdateScroll(_this)
	
	local content = _this.GetWidget("content", false).get()
	__assert(content, "ошибка в scrollable_panel._UpdateScroll: не найден виджет content")
	
	local scroll = __cast(_this.GetWidget("scroll", false).get(), sf.gui.CScrollWidget)
	__assert(scroll, "ошибка в scrollable_panel._UpdateScroll: не найден виджет scroll")
	
	local page_size = _this.GetSize().Y
	local content_size = content.GetSize().Y

	if (page_size >= content_size) then
		scroll.AddFlags(sf.misc.BitwiseOr(scroll.FlagHidden, scroll.FlagDisabled))
		return
	end

	scroll.RemFlags(sf.misc.BitwiseOr(scroll.FlagHidden, scroll.FlagDisabled))

	scroll.SetMaxValue(content_size)
	scroll.SetPageSize(page_size)
	scroll.SetButtonValue((content_size-page_size) / scrollable_panel.params.items_count)
end
