All pastes #349993 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-02-11 04:38 UTC
rendered paste body
	def OnDraw(self, widget, event):
		"""
		Fires off the drawing operation.
		
		Parameters:
			widget -- reserved for GTK callbacks, don't use it explicitly.
			event -- reserved for GTK callbacks, don't use it explicitly.
		"""
		cache = self.cachedDrawArea
		self.area = event.area
		
		#check if the expose area is within the already cached rectangle
		# TODO: reenable this if
		#if self.area.x < cache.x or (self.area.x + self.area.width > cache.x + cache.width):
		self.DrawLine()
		
		# Get a cairo surface for this drawing op
		context = widget.window.cairo_create()

		# Give it our waveform image as a source
		context.set_source_surface(self.source, self.cachedDrawArea.x, self.cachedDrawArea.y)	

		# Blit our waveform across
		context.paint()
			
		#d = widget.window
		#gc = d.new_gc()
		
		# redraw area from saved gtk.gdk.Image
		#d.draw_image(gc, self.savedLine,
		#			 event.area.x, event.area.y,
		#			 event.area.x, event.area.y,
		#			 event.area.width, event.area.height)

		# Draw play cursor position (add 1 so it lines up correctly)
		x = int(round((self.project.transport.position - self.project.viewStart) * self.project.viewScale))+1
		context.move_to(x, 0)
		context.set_line_width(1)
		context.line_to(x, self.allocation.height)
		context.set_source_rgb(*self._PLAY_CURSOR_RGB)
		context.stroke()
		
		# Set the color
		#col = gc.get_colormap().alloc_color("#FF0000")
		#gc.set_foreground(col)
		
		# And draw:
		#x = int(round((self.project.transport.position - self.project.viewStart) * self.project.viewScale))
		#d.draw_line(gc, x, 0, x, self.get_allocation().height)	
	
		return False
	
	#_____________________________________________________________________
		
	def DrawLine(self):
		""" 
		Uses Cairo to draw the timeline onto a canvas in memory.
		Must be called initially and to redraw the timeline
		after moving the project start.
		
		Parameters:
			allocation -- the gtk.gdk.Rectangle allocated to the widget.
		"""
		allocArea = self.get_allocation()
		
		rect = gtk.gdk.Rectangle(self.area.x - self.area.width, self.area.y,
						self.area.width*3, self.area.height)
		
		#Check if our area to cache is outside the allocated area
		if rect.x < 0:
			rect.x = 0
		if rect.x + rect.width > allocArea.width:
			rect.width = allocArea.width - rect.x
			
		self.source = cairo.ImageSurface(cairo.FORMAT_ARGB32, rect.width, rect.height)
		
		context = cairo.Context(self.source)
		context.set_line_width(2)
		context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)

		# Draw white background
		context.rectangle(0, 0, rect.width, rect.height)
		context.set_source_rgb(*self._BACKGROUND_RGB)
		context.fill()
		
		# Draw the widget border
		context.set_line_width(0.2)
		context.rectangle(0, 0, rect.width, rect.height)
		context.set_source_rgb(*self._BORDER_RGB)
		context.stroke()
		
		# Draw a gray frame around the background
		#col = gc.get_colormap().alloc_color("#555555")
		#gc.set_foreground(col)
							
		#d.draw_rectangle(	gc, False, # False = not filled
		#					0, 
		#					0, 
		#					self.get_allocation().width, 
		#					self.get_allocation().height)
		
		x = 0
		transport = self.project.transport
		if transport.mode == transport.MODE_BARS_BEATS:
			print "bars"
			# Calculate our scroll offset
			# viewStart is in seconds. Seconds/60 = minutes. Minutes * Beat/Minute = beats (not an integer here)
			pos = (self.project.viewStart / 60.) * self.project.bpm
			
			# floor to an integer. beat = the last beat before viewStart
			beat = int(pos)
			
			# offset = part of a beat that has past since the last beat (offset < 1)
			offset = pos - beat
			
			if offset > 0.:
				# beats * ( pixels/minute ) / ( beats/minute ) = pixels
				# Set x to the position in pixels of the last beat 
				x -= offset * ((self.project.viewScale * 60.) / self.project.bpm)
				
				# (pixels/minute) / ( beats/minute) * 1 beat = pixels
				# Add the length of one beat, in pixels
				x += (self.project.viewScale * 60.) / self.project.bpm
				
				# x is now at the pixel-position of the first beat after the viewStart
				beat += 1
		
			while x < self.get_allocation().width:
				# Draw the beat/bar divisions
				ix = int(x)
				
				if beat % self.project.meter_nom:
					lineHeight = int(self.get_allocation().height/1.2)
				else:
					lineHeight = int(self.get_allocation().height/2)
					
					context.move_to(ix, lineHeight)
					context.line_to(ix, self.get_allocation().height)
					context.set_source_rgb(*self._BEAT_BAR_RGB)
					context.stroke()
					
					# Draw the bar number
					context.set_source_rgb(*self._TEXT_RGB)
					context.move_to(ix, 15)
					context.show_text(str((beat / self.project.meter_nom)+1))
					
					#l = pango.Layout(self.create_pango_context())
					#l.set_text(str((beat / self.project.meter_nom)+1))
					#d.draw_layout(gc, ix, 5, l)
					
				beat += 1
				
				x += (60. / self.project.bpm ) * self.project.viewScale
		else:
			print "hours"
			# Working in milliseconds here. Using seconds gives modulus problems because they're floats
			viewScale = self.project.viewScale / 1000.
			viewStart = int(self.project.viewStart * 1000)
			factor, displayMilliseconds = self.GetZoomFactor(viewScale)
			
			# Calculate our scroll offset
			# sec : viewStart, truncated to 1000ms; the second that has past just before the beginning of our surface
			msec = viewStart - (viewStart % 1000)
			# sec : move to the last 'line' that wasn't drawn
			if (msec % factor) != 0:
				msec -= (msec % factor)
			# offset: the amount of milliseconds since the last second before the timeline
			offset = viewStart - msec

			if offset > 0: # x = 0. atm, it should stay that way if offset == 0.
				# offset : milliseconds
				# viewScale : pixels / milliseconds
				# offset * viewScale : offset in pixels
				x -= offset * viewScale # return to the last 'active' second
				x += viewScale * factor # positions the cursor at the first second to be drawn
				msec += factor # cursor is at the first line to be drawn now
				
			# Draw ticks up to the end of our display
			while x < self.get_allocation().width:
				ix = int(x)
				
				if msec % (self._NUM_LINES * factor):
					lineHeight = int(self.get_allocation().height/1.2)
				else:
					lineHeight = int(self.get_allocation().height/2)
					
					context.move_to(ix, lineHeight)
					context.line_to(ix, self.get_allocation().height)
					context.set_source_rgb(*self._BEAT_BAR_RGB)
					context.stroke()
					
					# Draw the bar number
					#l = pango.Layout(self.create_pango_context())
					if displayMilliseconds:
						#Should use transportmanager for this...
						number = "%d:%02d:%03d"%((msec/1000) / 60, (msec/1000) % 60, msec%1000)
					else:
						number = "%d:%02d"%((msec/1000) / 60, (msec/1000) % 60)
						
					context.set_source_rgb(*self._TEXT_RGB)
					context.move_to(ix, 15)
					context.show_text(number)
					#d.draw_layout(gc, ix, 5, l)
				
				msec += factor
				x += viewScale * factor
				
		#self.savedLine = d.get_image(0, 0, self.get_allocation().width, self.get_allocation().height)
		
		#set area to record where the cached surface goes
		self.cachedDrawArea = rect
		self.redrawWaveform = False