<commit_before>{_} = require "../Underscore"
Utils = require "../Utils"

{Layer} = require "../Layer"
{Events} = require "../Events"

"""
ScrollComponent

content <Layer>
contentSize <{width:n, height:n}>
contentInset <{top:n, right:n, bottom:n, left:n}> TODO
contentOffset <{x:n, y:n}> TODO
scrollFrame <{x:n, y:n, width:n, height:n}>
scrollPoint <{x:n, y:n}>
scrollHorizontal <bool>
scrollVertical <bool>
speedX <number>
speedY <number>
delaysContentTouches <bool> TODO
loadPreset(<"ios"|"android">) TODO
scrollToPoint(<{x:n, y:n}>, animate=true, animationOptions={})
scrollToLayer(contentLayer, originX=0, originY=0)
scrollFrameForContentLayer(<x:n, y:n>) <{x:n, y:n, width:n, height:n}> TODO
closestContentLayer(<x:n, y:n>) <Layer> TODO

ScrollComponent Events

(all of the draggable events)
ScrollStart -> DragStart
ScrollWillMove -> DragWillMove
ScrollDidMove -> DragDidMove
scroll -> DragMove (html compat)
ScrollEnd -> DragEnd
"""

Events.ScrollStart = "scrollstart"
Events.Scroll = "scroll"
Events.ScrollMove = Events.Scroll
Events.ScrollEnd = "scrollend"
Events.ScrollAnimationDidStart = "scrollanimationdidstart"
Events.ScrollAnimationDidEnd = "scrollanimationdidend"

EventMappers = {}
EventMappers[Events.Move] = Events.Move
EventMappers[Events.ScrollStart] = Events.DragStart
EventMappers[Events.ScrollMove] = Events.DragMove
EventMappers[Events.ScrollEnd] = Events.DragEnd
EventMappers[Events.ScrollAnimationDidStart] = Events.DragAnimationStart
EventMappers[Events.ScrollAnimationDidEnd] = Events.DragAnimationEnd
EventMappers[Events.DirectionLockStart] = Events.DirectionLockStart

class exports.ScrollComponent extends Layer

	# Proxy properties directly from the draggable
	@define "velocity", @proxyProperty "content.draggable.velocity", importable: false
	@define "scrollHorizontal", @proxyProperty("content.draggable.horizontal")
	@define "scrollVertical", @proxyProperty("content.draggable.vertical")
	@define "speedX", @proxyProperty("content.draggable.speedX")
	@define "speedY", @proxyProperty("content.draggable.speedY")
	@define "isDragging", @proxyProperty "content.draggable.isDragging", importable: false
	@define "isMoving", @proxyProperty "content.draggable.isMoving", importable: false
	@define "propagateEvents", @proxyProperty("content.draggable.propagateEvents")
	@define "directionLock", @proxyProperty("content.draggable.directionLock")
	@define "directionLockThreshold", @proxyProperty("content.draggable.directionLockThreshold")

	@define "content",
		importable: false
		exportable: false
		get: -> @_content

	@define "mouseWheelSpeedMultiplier", @simpleProperty("mouseWheelSpeedMultiplier", 1)

	constructor: (options={}) ->

		# options.backgroundColor ?= null
		options.clip ?= true
		options.mouseWheelEnabled ?= false
		options.backgroundColor ?= null

		super options

		@_contentInset = options.contentInset or Utils.rectZero()
		@setContentLayer(new Layer)

		# Because we did not have a content layer before, we want to re-apply
		# the options again so everything gets configures properly.
		@_applyOptionsAndDefaults(options)
		@_enableMouseWheelHandling(options.mouseWheelEnabled)

		if options.hasOwnProperty("wrap")
			wrapComponent(@, options.wrap)

	calculateContentFrame: ->

		# Calculates the size of the content. By default this returns the total
		# size of all the content layers based on width and height. You can override
		# this for example to take scaling into account.

		contentFrame = @content.contentFrame()

		return size =
			x: 0
			y: 0
			width:  Math.max(@width,  contentFrame.x + contentFrame.width)
			height: Math.max(@height, contentFrame.y + contentFrame.height)


	setContentLayer: (layer) ->

		# Sets the content layer if you happen to want to replace the default one
		# yourself. Sets some sane defaults too.

		@_content.destroy() if @content

		@_content = layer
		@_content.parent = @
		@_content.name = "content"
		@_content.clip = true
		@_content.draggable.enabled = true
		@_content.draggable.momentum = true
		@_content.on("change:children", @updateContent)

		# Update the content view size on resizing the ScrollComponent
		@on("change:width", @updateContent)
		@on("change:height", @updateContent)

		@updateContent()
		@scrollPoint = {x:0, y:0}

		return @_content

	updateContent: =>

		# This function re-calculates the size of the content, updates the content layer
		# size and the dragging constraints based on the content size and contentInset.
		# It defaults to just the direct sub layers of the content, not recursive.

		# This function automatically gets called when you add or remove content layers,
		# but not when you change the size of the content layers. It's totally okay to
		# call it yourself, but make sure you don't overdo it.

		return unless @content

		contentFrame = @calculateContentFrame()
		contentFrame.x = contentFrame.x + @_contentInset.left
		contentFrame.y = contentFrame.y + @_contentInset.top
		@content.frame = contentFrame

		constraintsFrame = @calculateContentFrame()
		constraintsFrame =
			x: -constraintsFrame.width  + @width - @_contentInset.right
			y: -constraintsFrame.height + @height - @_contentInset.bottom
			width: 	constraintsFrame.width  + constraintsFrame.width  - @width +
				@_contentInset.left + @_contentInset.right
			height: constraintsFrame.height + constraintsFrame.height - @height +
				@_contentInset.top + @_contentInset.bottom

		@content.draggable.constraints = constraintsFrame

		# Change the default background color if we added children. We keep the default
		# color around until you set a content layer so you can see the ScrollComponent
		# on your screen after creation.
		if @content.children.length
			if @content.backgroundColor?.isEqual(Framer.Defaults.Layer.backgroundColor)
				@content.backgroundColor = null

	@define "scroll",<commit_msg>fix the scrollcomponent to not jump to the top when its content gets updated<commit_after>{_} = require "../Underscore"
Utils = require "../Utils"

{Layer} = require "../Layer"
{Events} = require "../Events"

"""
ScrollComponent

content <Layer>
contentSize <{width:n, height:n}>
contentInset <{top:n, right:n, bottom:n, left:n}> TODO
contentOffset <{x:n, y:n}> TODO
scrollFrame <{x:n, y:n, width:n, height:n}>
scrollPoint <{x:n, y:n}>
scrollHorizontal <bool>
scrollVertical <bool>
speedX <number>
speedY <number>
delaysContentTouches <bool> TODO
loadPreset(<"ios"|"android">) TODO
scrollToPoint(<{x:n, y:n}>, animate=true, animationOptions={})
scrollToLayer(contentLayer, originX=0, originY=0)
scrollFrameForContentLayer(<x:n, y:n>) <{x:n, y:n, width:n, height:n}> TODO
closestContentLayer(<x:n, y:n>) <Layer> TODO

ScrollComponent Events

(all of the draggable events)
ScrollStart -> DragStart
ScrollWillMove -> DragWillMove
ScrollDidMove -> DragDidMove
scroll -> DragMove (html compat)
ScrollEnd -> DragEnd
"""

Events.ScrollStart = "scrollstart"
Events.Scroll = "scroll"
Events.ScrollMove = Events.Scroll
Events.ScrollEnd = "scrollend"
Events.ScrollAnimationDidStart = "scrollanimationdidstart"
Events.ScrollAnimationDidEnd = "scrollanimationdidend"

EventMappers = {}
EventMappers[Events.Move] = Events.Move
EventMappers[Events.ScrollStart] = Events.DragStart
EventMappers[Events.ScrollMove] = Events.DragMove
EventMappers[Events.ScrollEnd] = Events.DragEnd
EventMappers[Events.ScrollAnimationDidStart] = Events.DragAnimationStart
EventMappers[Events.ScrollAnimationDidEnd] = Events.DragAnimationEnd
EventMappers[Events.DirectionLockStart] = Events.DirectionLockStart

class exports.ScrollComponent extends Layer

	# Proxy properties directly from the draggable
	@define "velocity", @proxyProperty "content.draggable.velocity", importable: false
	@define "scrollHorizontal", @proxyProperty("content.draggable.horizontal")
	@define "scrollVertical", @proxyProperty("content.draggable.vertical")
	@define "speedX", @proxyProperty("content.draggable.speedX")
	@define "speedY", @proxyProperty("content.draggable.speedY")
	@define "isDragging", @proxyProperty "content.draggable.isDragging", importable: false
	@define "isMoving", @proxyProperty "content.draggable.isMoving", importable: false
	@define "propagateEvents", @proxyProperty("content.draggable.propagateEvents")
	@define "directionLock", @proxyProperty("content.draggable.directionLock")
	@define "directionLockThreshold", @proxyProperty("content.draggable.directionLockThreshold")

	@define "content",
		importable: false
		exportable: false
		get: -> @_content

	@define "mouseWheelSpeedMultiplier", @simpleProperty("mouseWheelSpeedMultiplier", 1)

	constructor: (options={}) ->

		# options.backgroundColor ?= null
		options.clip ?= true
		options.mouseWheelEnabled ?= false
		options.backgroundColor ?= null

		super options

		@_contentInset = options.contentInset or Utils.rectZero()
		@setContentLayer(new Layer)

		# Because we did not have a content layer before, we want to re-apply
		# the options again so everything gets configures properly.
		@_applyOptionsAndDefaults(options)
		@_enableMouseWheelHandling(options.mouseWheelEnabled)

		if options.hasOwnProperty("wrap")
			wrapComponent(@, options.wrap)

	calculateContentFrame: ->

		# Calculates the size of the content. By default this returns the total
		# size of all the content layers based on width and height. You can override
		# this for example to take scaling into account.

		contentFrame = @content.contentFrame()

		return size =
			x: 0
			y: 0
			width:  Math.max(@width,  contentFrame.x + contentFrame.width)
			height: Math.max(@height, contentFrame.y + contentFrame.height)


	setContentLayer: (layer) ->

		# Sets the content layer if you happen to want to replace the default one
		# yourself. Sets some sane defaults too.

		@_content.destroy() if @content

		@_content = layer
		@_content.parent = @
		@_content.name = "content"
		@_content.clip = true
		@_content.draggable.enabled = true
		@_content.draggable.momentum = true
		@_content.on("change:children", @updateContent)

		# Update the content view size on resizing the ScrollComponent
		@on("change:width", @updateContent)
		@on("change:height", @updateContent)

		@updateContent()
		@scrollPoint = {x:0, y:0}

		return @_content

	updateContent: =>

		# This function re-calculates the size of the content, updates the content layer
		# size and the dragging constraints based on the content size and contentInset.
		# It defaults to just the direct sub layers of the content, not recursive.

		# This function automatically gets called when you add or remove content layers,
		# but not when you change the size of the content layers. It's totally okay to
		# call it yourself, but make sure you don't overdo it.

		return unless @content

		contentFrame = @calculateContentFrame()
		@content.width = contentFrame.width
		@content.height = contentFrame.height

		constraintsFrame = @calculateContentFrame()
		constraintsFrame =
			x: -constraintsFrame.width  + @width - @_contentInset.right
			y: -constraintsFrame.height + @height - @_contentInset.bottom
			width: 	constraintsFrame.width  + constraintsFrame.width  - @width +
				@_contentInset.left + @_contentInset.right
			height: constraintsFrame.height + constraintsFrame.height - @height +
				@_contentInset.top + @_contentInset.bottom

		@content.draggable.constraints = constraintsFrame

		# Change the default background color if we added children. We keep the default
		# color around until you set a content layer so you can see the ScrollComponent
		# on your screen after creation.
		if @content.children.length
			if @content.backgroundColor?.isEqual(Framer.Defaults.Layer.backgroundColor)
				@content.backgroundColor = null

	@define "scroll",
{'fraction_non_alphanumeric': 0.10768834734854986, 'fraction_numerical': 0.0012013042732109147, 'mean_word_length': 5.348039215686274, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1676289', 'n_tokens_mistral': 3697, 'n_tokens_neox': 3439, 'n_words': 968}