HomeForumSourceResearchGuide
Sign in to contribute to source. how it works
Component ui.ScrollBar:h by barry
expand copy to clipboardexpand
const int SCR_BUTTON_HEIGHT = 20
const int SCR_BUTTON_WIDTH = 20

const int SLIDER_MIN_WIDTH = 20

const int HEIGHT = 20

component provides ScrollBar:h {
	
	int width
	int height = HEIGHT
	
	Color scrollButtonColor = new Color(185, 185, 200, 255)
	Color scrollButtonLineColor = new Color(140, 140, 165, 255)
	Color scrollButtonArrowColor = new Color(100, 100, 135, 255)
	Color scrollBarColor = new Color(220, 220, 235, 255)
	Color scrollSliderColor = new Color(195, 195, 210, 255)

	int scroll

	int scrollAmount = 10
	int maxScroll = 0

	int sliderWidth = 0
	int sliderX = 0

	bool dragging = false
	int dragOffset = 0

	void updateScrollBarV(int max)
		{
		//update scroll bounds, and potentially position, assuming our content could have gotten larger or smaller since we last checked...
		
		if (max > 0)
			{
			maxScroll = max
			
			if (maxScroll > (width - (SCR_BUTTON_WIDTH*2)))
				{
				sliderWidth = SLIDER_MIN_WIDTH
				}
				else
				{
				sliderWidth = (width - (SCR_BUTTON_WIDTH*2)) - maxScroll
				
				if (sliderWidth < SLIDER_MIN_WIDTH) sliderWidth = SLIDER_MIN_WIDTH
				}
			
			if (scroll > maxScroll)
				{
				scroll = maxScroll
				emitevent scrollMoved()
				}
			}
			else
			{
			sliderWidth = 0
			maxScroll = 0
			sliderX = 0
			scroll = 0
			emitevent scrollMoved()
			}
		}
	
	void ScrollBar:setMaxValue(int v)
		{
		updateScrollBarV(v)
		postRepaint()
		}

	void ScrollBar:setLength(int w)
		{
		width = w
		}
	
	void ScrollBar:setIncrement(int v)
		{
		if (v < maxScroll)
			{
			scrollAmount = v
			}
		}
	
	void ScrollBar:setScrollPos(int v)
		{
		if (v <= maxScroll)
			{
			scroll = v
			postRepaint()
			}
		}
	
	int ScrollBar:getScrollPos()
		{
		return scroll
		}

	void ScrollBar:setFocus()
		{
		//pass-through to content
		}

	bool ScrollBar:recvFocus()
		{
		//pass-through to content
		return false
		}

	void ScrollBar:loseFocus()
		{
		//pass-through to content
		}

	Rect ScrollBar:getBounds()
		{
		return new Rect(xPosition, yPosition, width, height)
		}

	void ScrollBar:mouseDown(int x, int y, int button)
		{
		//if on slider, enter dragging mode
		if (y >= height-SCR_BUTTON_HEIGHT && y <= height)
			{
			if (x >= sliderX && x <= sliderX + sliderWidth)
				{
				//we track the click-down position relative to the edge of the slider, otherwise the slider's edge with jump to the mouse pointer
				dragging = true
				dragOffset = x - sliderX
				}
			}
		}

	void ScrollBar:mouseMove(int x, int y)
		{
		//if in dragging mode, move slider and update scroll view
		if (dragging)
			{
			int sliderMinX = SCR_BUTTON_WIDTH
			int sliderMaxX = ((width) - (SCR_BUTTON_WIDTH)) - sliderWidth

			int startScroll = scroll

			if (x > dragOffset)
				x = x - dragOffset
				else
				x = 0

			if (x < sliderMinX) x = sliderMinX
			if (x > sliderMaxX) x = sliderMaxX

			int sliderNewX = x

			int percent = (sliderNewX - SCR_BUTTON_WIDTH) * 100 / ((width - (SCR_BUTTON_WIDTH*2)) - sliderWidth)

			scroll = (percent * maxScroll) / 100

			if (scroll != startScroll)
				emitevent scrollMoved()
			
			postRepaint()
			}
		}
	
	void ScrollBar:mouseUp(int x, int y, int button)
		{
		dragging = false
		}
	
	void ScrollBar:click(int x, int y, int button)
		{
		//somewhere on the vertical scroll bar
		if (x >= 0 && x <= SCR_BUTTON_WIDTH)
			{
			//scroll up button
			if (scroll > 0)
				{
				if (scroll < scrollAmount)
					scroll = 0
					else
					scroll -= scrollAmount
				
				emitevent scrollMoved()
				postRepaint()
				}
			}
			else if (x >= width - SCR_BUTTON_WIDTH && x <= width)
			{
			//scroll right button
			if (scroll < maxScroll)
				{
				if (scroll + scrollAmount > maxScroll)
					scroll = maxScroll
					else
					scroll += scrollAmount
				
				emitevent scrollMoved()
				postRepaint()
				}
			}
			//only do this if the mouse position is not over the slider...
			else if (x < sliderX || x > sliderX + sliderWidth)
			{
			//the scroll bar area - click-jump to this scroll position...
			// - we do this by calculating the percentage within the scroll bar, and converting to a percentage within the content
			int percent = (x - SCR_BUTTON_WIDTH) * 100 / (width - (SCR_BUTTON_WIDTH*2))

			scroll = (percent * maxScroll) / 100
			
			emitevent scrollMoved()
			postRepaint()
			}
		}
	
	void ScrollBar:postRepaint()
		{
		emitevent repaint()
		}
	
	void ScrollBar:paint(Canvas c)
		{
		//horizontal scroll bar
		// - left button (rect)
		c.rect(new Rect2D(xPosition, yPosition, SCR_BUTTON_WIDTH, SCR_BUTTON_HEIGHT, scrollButtonColor))
		c.rectOutline(new Rect2D(xPosition, yPosition, SCR_BUTTON_WIDTH, SCR_BUTTON_HEIGHT, scrollButtonLineColor))
		// - left button (arrow)
		c.rect(new Rect2D(xPosition + SCR_BUTTON_WIDTH - 8, yPosition + (height-SCR_BUTTON_HEIGHT) + 4, 2, SCR_BUTTON_HEIGHT-8, scrollButtonArrowColor))
		c.rect(new Rect2D(xPosition + SCR_BUTTON_WIDTH - 12, yPosition + (height-SCR_BUTTON_HEIGHT) + 6, 2, SCR_BUTTON_HEIGHT-12, scrollButtonArrowColor))
		c.rect(new Rect2D(xPosition + SCR_BUTTON_WIDTH - 16, yPosition + (height-SCR_BUTTON_HEIGHT) + 8, 2, SCR_BUTTON_HEIGHT-16, scrollButtonArrowColor))
		// - scroll slider pipe
		c.rect(new Rect2D(xPosition + SCR_BUTTON_WIDTH, yPosition, width-(SCR_BUTTON_WIDTH*2), SCR_BUTTON_HEIGHT, scrollBarColor))
		c.line(new Line2D(xPosition + SCR_BUTTON_WIDTH, yPosition, xPosition + (width - (SCR_BUTTON_WIDTH)), yPosition, scrollButtonLineColor))
		c.line(new Line2D(xPosition + SCR_BUTTON_WIDTH, yPosition + SCR_BUTTON_HEIGHT-1, xPosition + (width - (SCR_BUTTON_WIDTH)), yPosition + SCR_BUTTON_HEIGHT-1, scrollButtonLineColor))
		// - right button (rect)
		c.rect(new Rect2D(xPosition + (width-SCR_BUTTON_WIDTH), yPosition + (height-SCR_BUTTON_HEIGHT), SCR_BUTTON_WIDTH, SCR_BUTTON_HEIGHT, scrollButtonColor))
		c.rectOutline(new Rect2D(xPosition + (width-SCR_BUTTON_WIDTH), yPosition + (height-SCR_BUTTON_HEIGHT), SCR_BUTTON_WIDTH, SCR_BUTTON_HEIGHT, scrollButtonLineColor))
		// - right button (arrow)
		c.rect(new Rect2D(xPosition + (width-SCR_BUTTON_WIDTH) + 6, yPosition + (height-SCR_BUTTON_HEIGHT) + 4, 2, SCR_BUTTON_HEIGHT-8, scrollButtonArrowColor))
		c.rect(new Rect2D(xPosition + (width-SCR_BUTTON_WIDTH) + 10, yPosition + (height-SCR_BUTTON_HEIGHT) + 6, 2, SCR_BUTTON_HEIGHT-12, scrollButtonArrowColor))
		c.rect(new Rect2D(xPosition + (width-SCR_BUTTON_WIDTH) + 14, yPosition + (height-SCR_BUTTON_HEIGHT) + 8, 2, SCR_BUTTON_HEIGHT-16, scrollButtonArrowColor))
		
		//slider - calculate position
		// - we do this by calculating the position of its top edge, as a percentage of (scroll slider pipe height - slider height)
		if (sliderWidth != 0)
			{
			int percent = scroll * 100 / maxScroll

			//calculate top-edge position
			int availableWidth = (width - ((SCR_BUTTON_WIDTH*2))) - sliderWidth
			sliderX = ((percent * availableWidth) / 100) + SCR_BUTTON_WIDTH

			c.rect(new Rect2D(xPosition + sliderX, yPosition+1, sliderWidth, height-2, scrollSliderColor))
			}
		}
	
	void ScrollBar:setPosition(int x, int y)
		{
		xPosition = x
		yPosition = y
		}
	
	Point ScrollBar:getPosition()
		{
		return new Point(xPosition, yPosition)
		}

	WH ScrollBar:getPreferredSize()
		{
		return new WH(width, height)
		}
	
	void ScrollBar:setDisabled(bool d)
		{
		disabled = d
		postRepaint()
		}
	
	}
Revision history
To propose a new revision to this entity, use dana source put -uc your/new/version.dn -n ui.ScrollBar:h -m "reason for update" -u yourUsername
Version 1 (this version) by barry
Notes for this version: Standard Library Initialisation