From c2adf88db4df23513e7476e1057275f6b6467bd5 Mon Sep 17 00:00:00 2001 From: Gonzalo Odiard Date: Wed, 23 Jan 2013 16:03:32 +0000 Subject: Partial port drawing operations to cairo The activity starts but the canvas draw is wrong. The old code used bitmap masks to define non rectangular areas, like in the drum instruments or the loops. Part of this is implemented with cairo, but is not finished. As a final note, this is a too big patch, more work is needed, and probably part of the code can be refactored. Signed-off-by: Gonzalo Odiard --- (limited to 'Jam') diff --git a/Jam/Block.py b/Jam/Block.py index 004adae..97a95a2 100644 --- a/Jam/Block.py +++ b/Jam/Block.py @@ -7,6 +7,7 @@ import common.Config as Config from common.Config import scale from common.Util.NoteDB import PARAMETER +from common.Util import CairoUtil #::: NOTE: # All the graphics resources are loaded in Desktop and referenced here as necessary @@ -26,7 +27,6 @@ class Block: def __init__( self, owner, data ): self.owner = owner - self.gc = owner.gc self.data = {} for key in data.keys(): @@ -243,31 +243,31 @@ class Block: def invalidate_rect( self, base = True ): self.owner.invalidate_rect( self.x, self.y, self.width, self.height, base ) - def draw( self, startX, startY, stopX, stopY, pixmap ): + def draw(self, startX, startY, stopX, stopY, ctx): if stopY <= self.y or startY >= self.endY: return False - self._drawB( startX, startY, stopX, stopY, pixmap ) + self._drawB(startX, startY, stopX, stopY, ctx) - def _drawB( self, startX, startY, stopX, stopY, pixmap ): + def _drawB( self, startX, startY, stopX, stopY, ctx): if stopX <= self.x: return False if self.child: - self.child._drawB( startX, startY, stopX, stopY, pixmap ) + self.child._drawB(startX, startY, stopX, stopY, ctx) if startX >= self.endX: return False - self._doDraw( startX, startY, stopX, stopY, pixmap ) + self._doDraw(startX, startY, stopX, stopY, ctx) return True - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): + def _doDraw( self, startX, startY, stopX, stopY, ctx): pass # override in subclasses - def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): + def drawHighlight( self, startX, startY, stopX, stopY, ctx): pass # override in subclasses class Instrument(Block): @@ -332,7 +332,7 @@ class Instrument(Block): self.owner.activateInstrument( self ) Block.button_release( self, event ) - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): + def _doDraw( self, startX, startY, stopX, stopY, ctx): x = max( startX, self.x ) y = max( startY, self.y ) endX = min( stopX, self.endX ) @@ -340,15 +340,29 @@ class Instrument(Block): width = endX - x height = endY - y + ctx.save() # draw border - if self.active: self.gc.foreground = self.owner.colors["Border_Active"] - else: self.gc.foreground = self.owner.colors["Border_Inactive"] - self.gc.set_clip_origin( self.x-Instrument.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) + CairoUtil.draw_round_rect(ctx, x, y, width, height) + ctx.set_line_width(3) + if self.active: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Bg_Active"])) + else: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Bg_Inactive"])) + ctx.fill_preserve() + if self.active: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Border_Active"])) + else: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Border_Inactive"])) + ctx.stroke() - # draw block - self.gc.set_clip_origin( self.x-Instrument.MASK_START, self.y-self.height ) - pixmap.draw_drawable( self.gc, self.img[self.active], x-self.x, y-self.y, x, y, width, height ) + ctx.translate(x, y) + ctx.set_source_surface(self.img[self.active]) + ctx.paint() + ctx.restore() def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): self.gc.foreground = self.owner.colors["Border_Highlight"] @@ -480,28 +494,54 @@ class Drum(Block): self.owner.activateDrum( self ) Block.button_release( self, event ) - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): + def _doDraw(self, startX, startY, stopX, stopY, ctx): x = max( startX, self.x ) y = max( startY, self.y ) endX = min( stopX, self.endX ) endY = min( stopY, self.endY ) width = endX - x height = endY - y - + ctx.save() # draw border - if self.active: self.gc.foreground = self.owner.colors["Border_Active"] - else: self.gc.foreground = self.owner.colors["Border_Inactive"] - self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) + CairoUtil.draw_drum_mask(ctx, x, y, width) + + ctx.set_line_width(3) + if self.active: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Bg_Active"])) + else: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Bg_Inactive"])) + ctx.fill_preserve() + if self.active: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Border_Active"])) + else: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Border_Inactive"])) + ctx.stroke() # draw block - self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y-self.height ) - pixmap.draw_drawable( self.gc, self.img[self.active], x-self.x, y-self.y, x, y, width, height ) + ctx.save() + ctx.translate(x, y) + ctx.set_source_surface(self.img[self.active]) + ctx.paint() + ctx.restore() # draw key - self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1] ) - pixmap.draw_drawable( self.gc, self.keyImage[ self.active ], 0, 0, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) + #self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, + # self.y+Drum.KEYRECT[1] ) + ctx.save() + ctx.translate(self.x + Drum.KEYRECT[0] - Block.KEYMASK_START, + self.y + Drum.KEYRECT[1]) + ctx.set_source_surface(self.keyImage[ self.active ]) + ctx.paint() + ctx.restore() + + #pixmap.draw_drawable( self.gc, , 0, 0, self.x+Drum.KEYRECT[0], + #self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) + ctx.restore() def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): self.gc.foreground = self.owner.colors["Border_Highlight"] @@ -752,14 +792,21 @@ class Loop(Block): self.owner.activateLoop( root.child ) Block.button_release( self, event ) - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): + def _doDraw( self, startX, startY, stopX, stopY, ctx): y = max( startY, self.y ) endY = min( stopY, self.endY ) height = endY - y loop = self.img[ self.active ] - if self.active: self.gc.foreground = self.owner.colors["Border_Active"] - else: self.gc.foreground = self.owner.colors["Border_Inactive"] + ctx.save() + # TODO: we have all this logic here again? + # is not the same than in Picker.py line 330 ? + if self.active: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Border_Active"])) + else: + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.owner.colors["Border_Inactive"])) #-- draw head ----------------------------------------- @@ -768,14 +815,18 @@ class Loop(Block): endX = min( stopX, self.x + Loop.HEAD ) width = endX - x + ctx.save() # draw border - self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) + # self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y ) + ctx.rectangle(x, y, width, height) + ctx.fill() # draw block - self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) - + #self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y-self.height ) + ctx.translate(x, y) + ctx.set_source_surface(loop) + ctx.paint() + ctx.restore() #-- draw beats ---------------------------------------- beats = self.owner.noteDB.getPage(self.data["id"]).beats - 1 # last beat is drawn with the tail @@ -788,13 +839,19 @@ class Loop(Block): endX = min( stopX, curx + Loop.BEAT_MUL3 ) width = endX - x + ctx.save() # draw border - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - + #self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y ) + ctx.rectangle(x, y, width, height) + ctx.fill() # draw block - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) + #self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height ) + ctx.translate(x, y) + ctx.set_source_surface(loop) + ctx.paint() + #pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, + # y, width, height ) + ctx.restore() curx += Loop.BEAT_MUL3 beats -= 3 @@ -805,14 +862,18 @@ class Loop(Block): endX = min( stopX, endX ) width = endX - x + ctx.save() # draw border - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) + #self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y ) + ctx.rectangle(x, y, width, height) + ctx.fill() # draw block - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) - + #self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height ) + ctx.translate(x, y) + ctx.set_source_surface(loop) + ctx.paint() + ctx.restore() curx += Loop.BEAT*beats @@ -822,19 +883,29 @@ class Loop(Block): x = max( startX, curx ) endX = min( stopX, self.endX ) width = endX - x - + ctx.save() # draw border - self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) + #self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y ) + ctx.rectangle(x, y, width, height) + ctx.fill() # draw block - self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) + #self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y-self.height ) + ctx.translate(x, y) + ctx.set_source_surface(loop) + ctx.paint() + ctx.restore() #-- draw key ------------------------------------------ if self.keyActive: - self.gc.set_clip_origin( self.x+Loop.KEYRECT[0]-Block.KEYMASK_START, self.y+Loop.KEYRECT[1] ) - pixmap.draw_drawable( self.gc, self.keyImage[ self.active ], 0, 0, self.x+Loop.KEYRECT[0], self.y+Loop.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) + #self.gc.set_clip_origin( self.x+Loop.KEYRECT[0]- + # Block.KEYMASK_START, self.y+Loop.KEYRECT[1] ) + ctx.save() + ctx.translate(self.x + Loop.KEYRECT[0], self.y + Loop.KEYRECT[1]) + ctx.set_source_surface(self.keyImage[ self.active ]) + ctx.paint() + ctx.restore() + ctx.restore() def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): self.gc.foreground = self.owner.colors["Border_Highlight"] diff --git a/Jam/Desktop.py b/Jam/Desktop.py index ac84c3f..c62d018 100644 --- a/Jam/Desktop.py +++ b/Jam/Desktop.py @@ -1,3 +1,5 @@ +import logging + from gi.repository import GObject from gi.repository import Gtk from gi.repository import Gdk @@ -7,6 +9,7 @@ import common.Config as Config from gettext import gettext as _ import common.Util.InstrumentDB as InstrumentDB +from common.Util import CairoUtil from Jam import Block from Jam import Popup @@ -21,17 +24,15 @@ class Desktop( Gtk.EventBox ): self.drawingArea = Gtk.DrawingArea() self.add( self.drawingArea ) - # take drawing setup from owner - self.gc = owner.gc self.colors = owner.colors - self.blockMask = owner.blockMask + # TODO the masks are pending + # self.blockMask = owner.blockMask self.noteDB = owner.noteDB self.dirtyRectToAdd = Gdk.Rectangle() # used by the invalidate_rect function - self.screenBuf = None self.screenBufDirty = False - self.screenBufDirtyRect = () + self.screenBufDirtyRect = Gdk.Rectangle() self.blocks = [] # items on the desktop self.activeInstrument = None @@ -45,7 +46,7 @@ class Desktop( Gtk.EventBox ): self.connect( "button-press-event", self.on_button_press ) self.connect( "button-release-event", self.on_button_release ) self.connect( "motion-notify-event", self.on_motion_notify ) - self.drawingArea.connect( "expose-event", self.on_expose ) + self.drawingArea.connect("draw", self.__draw_cb) self.clickedBlock = None self.possibleParent = None @@ -68,10 +69,8 @@ class Desktop( Gtk.EventBox ): b.dumpToStream( ostream ) def on_size_allocate( self, widget, allocation ): - if self.screenBuf == None or self.alloc.width != allocation.width or self.alloc.height != allocation.height: - win = Gdk.get_default_root_window() - self.screenBuf = Gdk.Pixmap( win, allocation.width, allocation.height ) - self.invalidate_rect( 0, 0, allocation.width, allocation.height ) + + self.invalidate_rect(0, 0, allocation.width, allocation.height) self.alloc = allocation self.absoluteLoc = [0,0] parent = self.get_parent() @@ -313,10 +312,10 @@ class Desktop( Gtk.EventBox ): return if event.is_hint or widget != self: - x, y, state = self.window.get_pointer() + _pp, x, y, _flags = self.get_window().get_pointer() event.x = float(x) event.y = float(y) - event.state = state + #event.state = state blockCount = len(self.blocks) @@ -387,55 +386,55 @@ class Desktop( Gtk.EventBox ): #========================================================== # Drawing - def draw( self ): + def draw(self, ctx): startX = self.screenBufDirtyRect.x startY = self.screenBufDirtyRect.y stopX = startX + self.screenBufDirtyRect.width stopY = startY + self.screenBufDirtyRect.height - self.gc.set_clip_rectangle( self.screenBufDirtyRect ) + #self.gc.set_clip_rectangle( self.screenBufDirtyRect ) # draw background - self.gc.foreground = self.colors["bg"] - self.screenBuf.draw_rectangle( self.gc, True, startX, startY, self.screenBufDirtyRect.width, self.screenBufDirtyRect.height ) - + ctx.save() + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo(self.colors["bg"])) + ctx.rectangle(startX, startY, self.screenBufDirtyRect.width, + self.screenBufDirtyRect.height ) + ctx.fill() + ctx.restore() # draw blocks - self.gc.set_clip_mask( self.blockMask ) + #self.gc.set_clip_mask( self.blockMask ) for block in self.blocks: - block.draw( startX, startY, stopX, stopY, self.screenBuf ) + block.draw(startX, startY, stopX, stopY, ctx) self.screenBufDirty = False - def on_expose( self, DA, event ): + def __draw_cb(self, DA, ctx): if self.screenBufDirty: - self.draw() + self.draw(ctx) self.drawingAreaDirty = False - startX = event.area.x - startY = event.area.y - stopX = event.area.x + event.area.width - stopY = event.area.y + event.area.height +# startX = event.area.x +# startY = event.area.y +# stopX = event.area.x + event.area.width +# stopY = event.area.y + event.area.height - self.gc.set_clip_rectangle( event.area ) +# self.gc.set_clip_rectangle( event.area ) - # draw base - DA.window.draw_drawable( self.gc, self.screenBuf, startX, startY, startX, startY, event.area.width, event.area.height ) if self.possibleDelete: return - self.gc.set_clip_mask( self.blockMask ) - # draw possible parent - if self.possibleParent: - self.possibleParent.drawHighlight( startX, startY, stopX, stopY, DA.window ) + # TODO + #if self.possibleParent: + # self.possibleParent.drawHighlight( startX, startY, stopX, stopY, DA.window ) # draw dragged objects if self.dragging: - self.clickedBlock.draw( startX, startY, stopX, stopY, DA.window ) + self.clickedBlock.draw(startX, startY, stopX, stopY, ctx) # draw possible substitute if self.possibleSubstitute: @@ -443,7 +442,7 @@ class Desktop( Gtk.EventBox ): # draw key highlight if self.overKey: - self.overKey.drawKeyHighlight( DA.window ) + self.overKey.drawKeyHighlight(DA.get_window()) def invalidate_rect( self, x, y, width, height, base = True ): self.dirtyRectToAdd.x = x @@ -459,8 +458,11 @@ class Desktop( Gtk.EventBox ): self.screenBufDirtyRect.width = width self.screenBufDirtyRect.height = height else: - self.screenBufDirtyRect = self.screenBufDirtyRect.union( self.dirtyRectToAdd ) + self.screenBufDirtyRect = \ + Gdk.rectangle_union(self.screenBufDirtyRect, + self.dirtyRectToAdd) self.screenBufDirty = True - if self.drawingArea.window != None: - self.drawingArea.window.invalidate_rect( self.dirtyRectToAdd, True ) + if self.drawingArea.get_window() != None: + self.drawingArea.get_window().invalidate_rect(self.dirtyRectToAdd, + True) self.drawingAreaDirty = True diff --git a/Jam/JamMain.py b/Jam/JamMain.py index 99b5059..ec295cb 100644 --- a/Jam/JamMain.py +++ b/Jam/JamMain.py @@ -3,6 +3,7 @@ from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GObject from gi.repository import Pango +from gi.repository import PangoCairo import cairo import os @@ -43,6 +44,7 @@ from common.Util import OS from common.Tooltips import Tooltips import common.Util.Network as Net +from common.Util import CairoUtil import xdrlib import time @@ -57,11 +59,6 @@ from math import sqrt # wrapping during sync correction HEARTBEAT_BUFFER = 100 -def hexa_to_cairo_color(color_hexa): - _, color = Gdk.Color.parse(color_hexa) - logging.error('color %s class %s', color, color.__class__) - return (color.red / 65536.0, color.green / 65536.0, color.blue / 65536.0) - class JamMain(Gtk.EventBox): @@ -117,27 +114,31 @@ class JamMain(Gtk.EventBox): xoColorKey = ("#8D8D8D,#FFDDEA") xoColor = XoColor(xoColorKey) - win = Gdk.get_default_root_window() - self.colors = {"bg": Config.PANEL_BCK_COLOR, - "black": style.COLOR_BLACK.get_html(), + # colors in Config and in XoColor are strings, + # the colors in style are style.Color, transform all to Gdk.Color + self.colors = {"bg": CairoUtil.get_gdk_color(Config.PANEL_BCK_COLOR), + "black": style.COLOR_BLACK.get_gdk_color(), #"Picker_Bg": colormap.alloc_color("#404040"), #"Picker_Bg_Inactive": colormap.alloc_color("#808080"), - "Picker_Bg": style.COLOR_TOOLBAR_GREY.get_html(), - "Picker_Bg_Inactive": style.COLOR_BUTTON_GREY.get_html(), - "Picker_Fg": style.COLOR_WHITE.get_html(), - "Border_Active": xoColor.get_stroke_color(), - "Border_Inactive": "#8D8D8D", - "Border_Highlight": "#FFFFFF", - "Bg_Active": xoColor.get_fill_color(), - "Bg_Inactive": "#DBDBDB", - "Preview_Note_Fill": Config.BG_COLOR, - "Preview_Note_Border": Config.FG_COLOR, - "Preview_Note_Selected": style.COLOR_WHITE.get_html(), - "Note_Fill_Active": lighten("#590000"), + "Picker_Bg": style.COLOR_TOOLBAR_GREY.get_gdk_color(), + "Picker_Bg_Inactive": style.COLOR_BUTTON_GREY.get_gdk_color(), + "Picker_Fg": style.COLOR_WHITE.get_gdk_color(), + "Border_Active": \ + CairoUtil.get_gdk_color(xoColor.get_stroke_color()), + "Border_Inactive": CairoUtil.get_gdk_color("#8D8D8D"), + "Border_Highlight": CairoUtil.get_gdk_color("#FFFFFF"), + "Bg_Active": CairoUtil.get_gdk_color(xoColor.get_fill_color()), + "Bg_Inactive": CairoUtil.get_gdk_color("#DBDBDB"), + "Preview_Note_Fill": CairoUtil.get_gdk_color(Config.BG_COLOR), + "Preview_Note_Border": CairoUtil.get_gdk_color(Config.FG_COLOR), + "Preview_Note_Selected": style.COLOR_WHITE.get_gdk_color(), + # TODO: lighten here can be removed, check if is used in other + # places + "Note_Fill_Active": Gdk.Color(*lighten("#590000")), # base "Border_Active" - "Note_Fill_Inactive": lighten("#8D8D8D"), + "Note_Fill_Inactive": Gdk.Color(*lighten("#8D8D8D")), # base "Border_Inactive" - "Beat_Line": "#959595"} + "Beat_Line": CairoUtil.get_gdk_color("#959595")} self.colors["Note_Border_Active"] = self.colors["Border_Active"] self.colors["Note_Border_Inactive"] = self.colors["Border_Inactive"] @@ -171,11 +172,10 @@ class JamMain(Gtk.EventBox): self.blockMask = Gdk.bitmap_create_from_data( None, bitmap, pix.get_width(), pix.get_height()) - pix = GdkPixbuf.Pixbuf.new_from_file(imagefile('sampleBG.png')) - self.sampleBg = Gdk.Pixmap(win, pix.get_width(), pix.get_height()) - self.sampleBg.draw_pixbuf(self.gc, pix, 0, 0, 0, 0, pix.get_width(), - pix.get_height(), Gdk.RGB_DITHER_NONE) - self.sampleBg.endOffset = pix.get_width() - 5 + """ + self.sampleBg = cairo.ImageSurface.create_from_png( + imagefile('sampleBG.png')) + """ if True: # load sample note clipmask pix = GdkPixbuf.Pixbuf.new_from_file(imagefile('sampleNoteMask.png')) pixels = pix.get_pixels() @@ -283,7 +283,7 @@ class JamMain(Gtk.EventBox): #-- GUI ----------------------------------------------- if True: # GUI - self.modify_bg(Gtk.StateType.NORMAL, self.colors["bg"]) # window bg + self.modify_bg(Gtk.StateType.NORMAL, self.colors["bg"]) self.GUI = {} self.GUI["mainVBox"] = Gtk.VBox() @@ -296,18 +296,20 @@ class JamMain(Gtk.EventBox): #-- Bank ---------------------------------------------- separator = Gtk.Label(label=" ") separator.set_size_request(-1, style.TOOLBOX_SEPARATOR_HEIGHT) - self.GUI["mainVBox"].pack_start(separator, False) + self.GUI["mainVBox"].pack_start(separator, False, True, 0) self.GUI["notebook"] = Gtk.Notebook() self.GUI["notebook"].set_scrollable(True) self.GUI["notebook"].modify_bg(Gtk.StateType.NORMAL, self.colors["Picker_Bg"]) self.GUI["notebook"].modify_bg(Gtk.StateType.ACTIVE, self.colors["Picker_Bg_Inactive"]) - self.GUI["notebook"].props.tab_vborder = style.TOOLBOX_TAB_VBORDER - self.GUI["notebook"].props.tab_hborder = style.TOOLBOX_TAB_HBORDER + # TODO gtk3 no available anymore? + #self.GUI["notebook"].props.tab_vborder = style.TOOLBOX_TAB_VBORDER + #self.GUI["notebook"].props.tab_hborder = style.TOOLBOX_TAB_HBORDER self.GUI["notebook"].set_size_request(-1, scale(160)) self.GUI["notebook"].connect("switch-page", self.setPicker) - self.GUI["mainVBox"].pack_start(self.GUI["notebook"], False, False) + self.GUI["mainVBox"].pack_start(self.GUI["notebook"], False, + False, 0) self.pickers = {} self.pickerScroll = {} for type in [Picker.Instrument, Picker.Drum, Picker.Loop]: @@ -410,10 +412,10 @@ class JamMain(Gtk.EventBox): self.activity.connect("shared", self.shared) - if self.activity._shared_activity: # PEER - self.activity._shared_activity.connect("buddy-joined", + if self.activity.shared_activity: # PEER + self.activity.shared_activity.connect("buddy-joined", self.buddy_joined) - self.activity._shared_activity.connect("buddy-left", + self.activity.shared_activity.connect("buddy-left", self.buddy_left) self.activity.connect("joined", self.joined) self.network.setMode(Net.MD_WAIT) @@ -972,29 +974,32 @@ class JamMain(Gtk.EventBox): x = (Block.Block.WIDTH - pix.get_width()) // 2 y = (Block.Block.HEIGHT - pix.get_height()) // 2 - img = cairo.ImageSurface(cairo.FORMAT_RGB24, Block.Block.WIDTH, + img = cairo.ImageSurface(cairo.FORMAT_ARGB32, Block.Block.WIDTH, Block.Block.HEIGHT) # TODO: two images? may be we can draw the rectangle with cairo later ctx = cairo.Context(img) - ctx.set_source_rgb(*hexa_to_cairo_color(self.colors["Bg_Inactive"])) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Bg_Inactive"])) ctx.rectangle(0, 0, Block.Block.WIDTH, Block.Block.HEIGHT) ctx.translate(x, y) ctx.set_source_surface(pix, 0, 0) ctx.paint() self.instrumentImage[id] = img - img2 = cairo.ImageSurface(cairo.FORMAT_RGB24, Block.Block.WIDTH, + img2 = cairo.ImageSurface(cairo.FORMAT_ARGB32, Block.Block.WIDTH, Block.Block.HEIGHT) ctx2 = cairo.Context(img2) - ctx2.set_source_rgb(*hexa_to_cairo_color(self.colors["Bg_Active"])) + ctx2.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Bg_Active"])) ctx2.rectangle(0, 0, Block.Block.WIDTH, Block.Block.HEIGHT) ctx2.translate(x, y) ctx2.set_source_surface(pix, 0, 0) ctx2.paint() self.instrumentImageActive[id] = img2 - def _drawNotes(self, pixmap, beats, notes, active): - self.gc.set_clip_mask(self.sampleNoteMask) + def _drawNotes(self, ctx, beats, notes, active): + #self.gc.set_clip_mask(self.sampleNoteMask) + ctx.save() for note in notes: # draw N notes x = self.ticksToPixels(note.cs.onset) # include end cap offset @@ -1006,73 +1011,86 @@ class JamMain(Gtk.EventBox): y = self.pitchToPixels(note.cs.pitch) # draw fill if active: - self.gc.foreground = self.colors["Note_Fill_Active"] + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Note_Fill_Active"])) else: - self.gc.foreground = self.colors["Note_Fill_Inactive"] - self.gc.set_clip_origin(x, y - self.sampleNoteHeight) - pixmap.draw_rectangle(self.gc, True, x + 1, y + 1, width + 1, - self.sampleNoteHeight - 2) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Note_Fill_Inactive"])) + #self.gc.set_clip_origin(x, y - self.sampleNoteHeight) + ctx.rectangle(x + 1, y + 1, width + 1, self.sampleNoteHeight - 2) + ctx.fill() # draw border if active: - self.gc.foreground = self.colors["Note_Border_Active"] + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Note_Border_Active"])) else: - self.gc.foreground = self.colors["Note_Border_Inactive"] - self.gc.set_clip_origin(x, y) - pixmap.draw_rectangle(self.gc, True, x, y, width, - self.sampleNoteHeight) - self.gc.set_clip_origin(endX - self.sampleNoteMask.endOffset, y) - pixmap.draw_rectangle(self.gc, True, endX, y, 3, - self.sampleNoteHeight) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Note_Border_Inactive"])) + #self.gc.set_clip_origin(x, y) + ctx.rectangle(x, y, width, self.sampleNoteHeight) + ctx.fill() + #self.gc.set_clip_origin(endX - self.sampleNoteMask.endOffset, y) + ctx.rectangle(endX, y, 3, self.sampleNoteHeight) + ctx.fill() + ctx.restore() def prepareKeyImage(self, key): - win = Gdk.get_default_root_window() - pangolayout = self.create_pango_layout(_(self.valid_shortcuts[key])) + text =_(self.valid_shortcuts[key]) + + # TODO: two images? may be we can draw the rectangle with cairo later + self.keyImage[key] = self._prepare_key_image(text, + self.colors["Bg_Inactive"], self.colors["Border_Inactive"]) + + self.keyImageActive[key] = self._prepare_key_image(text, + self.colors["Bg_Active"], self.colors["Border_Active"]) + + def _prepare_key_image(self, text, bg_color, border_color): + img = cairo.ImageSurface(cairo.FORMAT_ARGB32, Block.Block.KEYSIZE, + Block.Block.KEYSIZE) + ctx = cairo.Context(img) + pango_layout = PangoCairo.create_layout(ctx) fontDesc = Pango.FontDescription("bold") - pangolayout.set_font_description(fontDesc) - extents = pangolayout.get_pixel_extents() - x = (Block.Block.KEYSIZE - extents[1][2]) // 2 - y = (Block.Block.KEYSIZE - extents[1][3]) // 2 - - pixmap = Gdk.Pixmap(win, Block.Block.KEYSIZE, Block.Block.KEYSIZE) - self.gc.foreground = self.colors["Border_Inactive"] - pixmap.draw_rectangle(self.gc, True, 0, 0, Block.Block.KEYSIZE, - Block.Block.KEYSIZE) - self.gc.foreground = self.colors["Bg_Inactive"] - pixmap.draw_layout(self.gc, x, y, pangolayout) - self.keyImage[key] = pixmap - - pixmap = Gdk.Pixmap(win, Block.Block.KEYSIZE, Block.Block.KEYSIZE) - self.gc.foreground = self.colors["Border_Active"] - pixmap.draw_rectangle(self.gc, True, 0, 0, Block.Block.KEYSIZE, - Block.Block.KEYSIZE) - self.gc.foreground = self.colors["Bg_Active"] - pixmap.draw_layout(self.gc, x, y, pangolayout) - self.keyImageActive[key] = pixmap + pango_layout.set_font_description(fontDesc) + pango_layout.set_text(unicode(text), len(unicode(text))) + extents = pango_layout.get_pixel_extents() + x = (Block.Block.KEYSIZE - extents[1].width) // 2 + y = (Block.Block.KEYSIZE - extents[1].height) // 2 + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo(border_color)) + ctx.rectangle(0, 0, Block.Block.KEYSIZE, Block.Block.KEYSIZE) + ctx.fill() + ctx.translate(x, y) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo(bg_color)) + PangoCairo.show_layout(ctx, pango_layout) + ctx.stroke() + return img def updateLoopImage(self, id): page = self.noteDB.getPage(id) - win = Gdk.get_default_root_window() width = Block.Loop.WIDTH[page.beats] height = Block.Loop.HEIGHT - - self.gc.set_clip_rectangle((0, 0, width, height)) - - pixmap = Gdk.Pixmap(win, width, height) - self.gc.foreground = self.colors["Bg_Inactive"] - pixmap.draw_rectangle(self.gc, True, 0, 0, width, height) - self._drawNotes(pixmap, page.beats, self.noteDB.getNotesByTrack(id, 0), - False) - self.loopImage[id] = pixmap - - self.gc.set_clip_rectangle((0, 0, width, height)) - - pixmap = Gdk.Pixmap(win, width, height) - self.gc.foreground = self.colors["Bg_Active"] - pixmap.draw_rectangle(self.gc, True, 0, 0, width, height) - self._drawNotes(pixmap, page.beats, self.noteDB.getNotesByTrack(id, 0), + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + ctx = cairo.Context(surface) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Bg_Inactive"])) + ctx.rectangle(0, 0, width, height) + ctx.fill() + + self._drawNotes(ctx, page.beats, self.noteDB.getNotesByTrack(id, 0), + False) + self.loopImage[id] = surface + + #self.gc.set_clip_rectangle((0, 0, width, height)) + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + ctx = cairo.Context(surface) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Bg_Active"])) + ctx.rectangle(0, 0, width, height) + ctx.fill() + self._drawNotes(ctx, page.beats, self.noteDB.getNotesByTrack(id, 0), True) - self.loopImageActive[id] = pixmap + self.loopImageActive[id] = surface def ticksToPixels(self, ticks): return self.loopTickOffset + int(round(ticks * self.pixelsPerTick)) @@ -1157,9 +1175,9 @@ class JamMain(Gtk.EventBox): def shared(self, activity): if Config.DEBUG: print "TamTamJam:: successfully shared, start host mode" - self.activity._shared_activity.connect("buddy-joined", + self.activity.shared_activity.connect("buddy-joined", self.buddy_joined) - self.activity._shared_activity.connect("buddy-left", self.buddy_left) + self.activity.shared_activity.connect("buddy-left", self.buddy_left) self.network.setMode(Net.MD_HOST) self.updateSync() self.syncTimeout = GObject.timeout_add(1000, self.updateSync) @@ -1167,7 +1185,7 @@ class JamMain(Gtk.EventBox): def joined(self, activity): if Config.DEBUG: print "TamTamJam:: joined activity!!" - for buddy in self.activity._shared_activity.get_joined_buddies(): + for buddy in self.activity.shared_activity.get_joined_buddies(): print buddy.props.ip4_address def buddy_joined(self, activity, buddy): diff --git a/Jam/Parasite.py b/Jam/Parasite.py index c5ac2ec..f29bee6 100644 --- a/Jam/Parasite.py +++ b/Jam/Parasite.py @@ -5,6 +5,7 @@ import common.Config as Config from common.Util.NoteDB import PARAMETER from common.Util.CSoundClient import new_csound_client +from common.Util import CairoUtil class LoopParasite: @@ -31,7 +32,6 @@ class LoopParasite: self.lastDragP = 0 self.lastDragD = 0 - self.gc = self.owner.gc self.colors = self.owner.colors self.updateParameter( None, None ) @@ -325,24 +325,36 @@ class LoopParasite: #======================================================= # Draw - def draw( self, win, gc, startX, stopX ): - if stopX < self.x: return False # we don't need to draw and no one after us will draw - if startX > self.x + self.width: return True # we don't need to draw, but maybe a later note does + def draw(self, ctx, startX, stopX): + # we don't need to draw and no one after us will draw + if stopX < self.x: + return False + # we don't need to draw, but maybe a later note does + if startX > self.x + self.width: + return True # draw fill - self.gc.foreground = self.colors["Preview_Note_Fill"] - self.gc.set_clip_origin( self.x, self.y-self.owner.sampleNoteHeight ) - self.owner.previewBuffer.draw_rectangle( self.gc, True, self.x+1, self.y+1, self.width-2, self.owner.sampleNoteHeight-2 ) + ctx.save() + ctx.set_source_rgb(CairoUtil.gdk_color_to_cairo( + self.colors["Preview_Note_Fill"])) + ctx.rectangle(self.x + 1, self.y + 1, self.width - 2, + self.owner.sampleNoteHeight - 2) + ctx.fill() + # draw border if self.selected: - self.gc.foreground = self.colors["Preview_Note_Selected"] + ctx.set_source_rgb(CairoUtil.gdk_color_to_cairo( + self.colors["Preview_Note_Selected"])) else: - self.gc.foreground = self.colors["Preview_Note_Border"] - self.gc.set_clip_origin( self.x, self.y ) + ctx.set_source_rgb(CairoUtil.gdk_color_to_cairo( + self.colors["Preview_Note_Border"])) + #self.gc.set_clip_origin( self.x, self.y ) endX = self.x + self.width - 3 - self.owner.previewBuffer.draw_rectangle( self.gc, True, self.x, self.y, self.width-3, self.owner.sampleNoteHeight ) - self.gc.set_clip_origin( endX-self.owner.sampleNoteMask.endOffset, self.y ) - self.owner.previewBuffer.draw_rectangle( self.gc, True, endX, self.y, 3, self.owner.sampleNoteHeight ) - + ctx.rectangle(self.x, self.y, self.width - 3, + self.owner.sampleNoteHeight) + ctx.fill() + #self.gc.set_clip_origin( endX-self.owner.sampleNoteMask.endOffset, self.y ) + ctx.rectangle(endX, self.y, 3, self.owner.sampleNoteHeight) + ctx.fill() + ctx.restore() return True # we drew something - diff --git a/Jam/Picker.py b/Jam/Picker.py index 5456555..3d1288e 100644 --- a/Jam/Picker.py +++ b/Jam/Picker.py @@ -1,13 +1,16 @@ from gi.repository import Gtk from gi.repository import Gdk +from gi.repository import GdkPixbuf import os - +import cairo import sets +import StringIO from common.Util.CSoundClient import new_csound_client from common.port.scrolledbox import HScrolledBox import common.Config as Config +from common.Util import CairoUtil from gettext import gettext as _ from sugar3.graphics.palette import Palette, WidgetInvoker @@ -24,10 +27,9 @@ class Picker(HScrolledBox): self.owner = owner - # take drawing setup from owner - self.gc = owner.gc self.colors = owner.colors - self.blockMask = owner.blockMask + # TODO gtk3 no masks yet + #self.blockMask = owner.blockMask self.filter = filter @@ -142,35 +144,47 @@ class Instrument( Picker ): data = { "name": self.instrumentDB.instId[id].nameTooltip, "id": id } - win = Gdk.get_default_root_window() width = Block.Instrument.WIDTH height = Block.Instrument.HEIGHT - pixmap = Gdk.Pixmap( win, width, height ) - - self.gc.set_clip_rectangle( ( 0, 0, width, height ) ) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + ctx = cairo.Context(surface) # draw bg - self.gc.foreground = self.colors["Picker_Bg"] - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Picker_Bg"])) + ctx.rectangle(0, 0, width, height) + ctx.fill_preserve() - self.gc.set_clip_mask( self.blockMask ) + # TODO gtk3 no masks yet + #self.gc.set_clip_mask( self.blockMask ) # draw border - self.gc.foreground = self.colors["Border_Inactive"] - self.gc.set_clip_origin( -Block.Instrument.MASK_START, 0 ) - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) + + # TODO gtk3 mask + #self.gc.set_clip_origin( -Block.Instrument.MASK_START, 0 ) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Border_Inactive"])) + ctx.rectangle(0, 0, width, height) + ctx.stroke() # draw block - inst = self.owner.getInstrumentImage( data["id"] ) - self.gc.set_clip_origin( -Block.Instrument.MASK_START, -height ) - pixmap.draw_drawable( self.gc, inst, 0, 0, 0, 0, width, height ) + #self.gc.set_clip_origin( -Block.Instrument.MASK_START, -height ) + ctx.set_source_surface(self.owner.getInstrumentImage(data["id"]), 0, 0) + ctx.paint() - image = Gtk.Image() - image.set_from_pixmap( pixmap, None ) + # may be there are a better way to put the content of the surface in + # a GtkImage + pixbuf_data = StringIO.StringIO() + surface.write_to_png(pixbuf_data) + pxb_loader = GdkPixbuf.PixbufLoader.new_with_type('png') + pxb_loader.write(pixbuf_data.getvalue()) + pxb_loader.close() + + image = Gtk.Image.new_from_pixbuf(pxb_loader.get_pixbuf()) block = Gtk.EventBox() - block.modify_bg( Gtk.StateType.NORMAL, self.colors["Picker_Bg"] ) - block.add( image ) + block.modify_bg(Gtk.StateType.NORMAL, self.colors["Picker_Bg"]) + block.add(image) Picker.addBlock( self, data, data["name"], block ) @@ -210,35 +224,46 @@ class Drum( Picker ): data = { "name": self.instrumentDB.instId[id].nameTooltip, "id": id } - win = Gdk.get_default_root_window() width = Block.Drum.WIDTH height = Block.Drum.HEIGHT - pixmap = Gdk.Pixmap( win, width, height ) - self.gc.set_clip_rectangle( ( 0, 0, width, height ) ) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + ctx = cairo.Context(surface) + # draw bg - self.gc.foreground = self.colors["Picker_Bg"] - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Picker_Bg"])) + ctx.rectangle(0, 0, width, height) + ctx.fill_preserve() - self.gc.set_clip_mask( self.blockMask ) + # TODO gtk3 masaks pending + #self.gc.set_clip_mask( self.blockMask ) # draw border - self.gc.foreground = self.colors["Border_Inactive"] - self.gc.set_clip_origin( -Block.Drum.MASK_START, 0 ) - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Border_Inactive"])) + ctx.rectangle(0, 0, width, height) + ctx.stroke() # draw block - inst = self.owner.getInstrumentImage( data["id"] ) - self.gc.set_clip_origin( -Block.Drum.MASK_START, -height ) - pixmap.draw_drawable( self.gc, inst, 0, 0, 0, 0, width, height ) + #self.gc.set_clip_origin( -Block.Drum.MASK_START, -height ) + ctx.set_source_surface(self.owner.getInstrumentImage(data["id"]), 0, 0) + ctx.paint() + + # may be there are a better way to put the content of the surface in + # a GtkImage + pixbuf_data = StringIO.StringIO() + surface.write_to_png(pixbuf_data) + pxb_loader = GdkPixbuf.PixbufLoader.new_with_type('png') + pxb_loader.write(pixbuf_data.getvalue()) + pxb_loader.close() - image = Gtk.Image() - image.set_from_pixmap( pixmap, None ) + image = Gtk.Image.new_from_pixbuf(pxb_loader.get_pixbuf()) block = Gtk.EventBox() - block.modify_bg( Gtk.StateType.NORMAL, self.colors["Picker_Bg"] ) - block.add( image ) + block.modify_bg(Gtk.StateType.NORMAL, self.colors["Picker_Bg"]) + block.add(image) Picker.addBlock( self, data, data["name"], block ) @@ -307,29 +332,33 @@ class Loop( Picker ): page = self.owner.noteDB.getPage( id ) - win = Gdk.get_default_root_window() width = Block.Loop.WIDTH[page.beats] height = Block.Loop.HEIGHT - pixmap = Gdk.Pixmap( win, width, height ) - self.gc.set_clip_rectangle( ( 0, 0, width, height ) ) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + ctx = cairo.Context(surface) # draw bg - self.gc.foreground = self.colors["Picker_Bg"] - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Picker_Bg"])) + ctx.rectangle(0, 0, width, height) + ctx.fill() - self.gc.set_clip_mask( self.blockMask ) - self.gc.foreground = self.owner.colors["Border_Inactive"] + #self.gc.set_clip_mask( self.blockMask ) + ctx.set_source_rgb(*CairoUtil.gdk_color_to_cairo( + self.colors["Border_Inactive"])) #-- draw head ----------------------------------------- # draw border - self.gc.set_clip_origin( -Block.Loop.MASK_START, 0 ) - pixmap.draw_rectangle( self.gc, True, 0, 0, Block.Loop.HEAD, height ) + #self.gc.set_clip_origin( -Block.Loop.MASK_START, 0 ) + ctx.rectangle(0, 0, Block.Loop.HEAD, height) + ctx.fill() # draw block - self.gc.set_clip_origin( -Block.Loop.MASK_START, -height ) - pixmap.draw_drawable( self.gc, loop, 0, 0, 0, 0, Block.Loop.HEAD, height ) + #self.gc.set_clip_origin( -Block.Loop.MASK_START, -height ) + ctx.set_source_surface(loop) + ctx.paint() #-- draw beats ---------------------------------------- @@ -337,12 +366,17 @@ class Loop( Picker ): curx = Block.Loop.HEAD while beats > 3: # draw border - self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, 0 ) - pixmap.draw_rectangle( self.gc, True, curx, 0, Block.Loop.BEAT_MUL3, height ) + #self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, 0 ) + ctx.rectangle(curx, 0, Block.Loop.BEAT_MUL3, height) + ctx.fill() # draw block - self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, -height ) - pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, Block.Loop.BEAT_MUL3, height ) + #self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, -height ) + ctx.save() + ctx.translate(curx, 0) + ctx.set_source_surface(loop) + ctx.paint() + ctx.restore() curx += Block.Loop.BEAT_MUL3 beats -= 3 @@ -351,27 +385,43 @@ class Loop( Picker ): w = Block.Loop.BEAT*beats # draw border - self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, 0 ) - pixmap.draw_rectangle( self.gc, True, curx, 0, w, height ) + #self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, 0 ) + ctx.rectangle(curx, 0, w, height) + ctx.fill() # draw block - self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, -height ) - pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, w, height ) + #self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, -height ) + ctx.set_source_surface(loop) + ctx.save() + ctx.translate(curx, 0) + ctx.set_source_surface(loop) + ctx.paint() + #pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, w, height ) + ctx.restore() curx += w #-- draw tail ----------------------------------------- # draw border + """ self.gc.set_clip_origin( curx-Block.Loop.MASK_TAIL, 0 ) pixmap.draw_rectangle( self.gc, True, curx, 0, Block.Loop.TAIL, height ) # draw block self.gc.set_clip_origin( curx-Block.Loop.MASK_TAIL, -height ) pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, Block.Loop.TAIL, height ) + """ + + # may be there are a better way to put the content of the surface in + # a GtkImage + pixbuf_data = StringIO.StringIO() + surface.write_to_png(pixbuf_data) + pxb_loader = GdkPixbuf.PixbufLoader.new_with_type('png') + pxb_loader.write(pixbuf_data.getvalue()) + pxb_loader.close() - image = Gtk.Image() - image.set_from_pixmap( pixmap, None ) + image = Gtk.Image.new_from_pixbuf(pxb_loader.get_pixbuf()) block = Gtk.EventBox() block.modify_bg( Gtk.StateType.NORMAL, self.colors["Picker_Bg"] ) diff --git a/Jam/Popup.py b/Jam/Popup.py index 51de523..98fd0d6 100644 --- a/Jam/Popup.py +++ b/Jam/Popup.py @@ -391,9 +391,9 @@ class Loop( Popup ): self.settingBlock = False - self.gc = self.owner.gc self.colors = self.owner.colors - self.sampleNoteMask = self.owner.sampleNoteMask + # TODO: gtk3 masks not available yet + #self.sampleNoteMask = self.owner.sampleNoteMask self.noteDB = self.owner.noteDB self.csnd = new_csound_client() @@ -478,7 +478,7 @@ class Loop( Popup ): True, padding=style.DEFAULT_PADDING) self.previewDA = self.GUI["previewDA"] = Gtk.DrawingArea() self.GUI["previewDA"].connect( "size-allocate", self.handlePreviewAlloc ) - self.GUI["previewDA"].connect( "expose-event", self.handlePreviewExpose ) + self.GUI["previewDA"].connect("draw", self.__draw_cb) self.GUI["previewEventBox"].add( self.GUI["previewDA"] ) self.GUI["mainBox"].show_all() @@ -489,25 +489,28 @@ class Loop( Popup ): self.dirtyRectToAdd = ( 0, 0, 0, 0 ) self.sampleBg = self.owner.sampleBg - self.GUI["previewDA"].set_size_request( -1, self.sampleBg.get_size()[1] ) + self.GUI["previewDA"].set_size_request(-1, self.sampleBg.get_height()) self.sampleNoteHeight = self.owner.sampleNoteHeight - self.sampleNoteMask = self.owner.sampleNoteMask - - self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.sampleBg.get_size()[1] - self.sampleNoteHeight) - self.pixelsPerPitch = float(self.sampleBg.get_size()[1] - self.sampleNoteHeight)/(Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH) + # TODO: gtk3 Masks not available yet + #self.sampleNoteMask = self.owner.sampleNoteMask + + self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / \ + (self.sampleBg.get_height() - self.sampleNoteHeight) + self.pixelsPerPitch = float(self.sampleBg.get_height() - \ + self.sampleNoteHeight) / (Config.MAXIMUM_PITCH - \ + Config.MINIMUM_PITCH) # Temporary Initialization self.pixelsPerTick = [0] + [ 1 for i in range(1,Config.MAXIMUM_BEATS+1) ] self.ticksPerPixel = [0] + [ 1 for i in range(1,Config.MAXIMUM_BEATS+1) ] - self.cursor = { \ - "default": None, \ - "drag-onset": Gdk.Cursor.new(Gdk.SB_RIGHT_ARROW), \ - "drag-pitch": Gdk.Cursor.new(Gdk.BOTTOM_SIDE), \ - "drag-duration": Gdk.Cursor.new(Gdk.RIGHT_SIDE), \ - "drag-playhead": Gdk.Cursor.new(Gdk.SB_H_DOUBLE_ARROW), \ - "pencil": Gdk.Cursor.new(Gdk.PENCIL), \ - "paste": Gdk.Cursor.new(Gdk.CursorType.CENTER_PTR), \ - "error": None } + self.cursor = {"default": None, + "drag-onset": Gdk.Cursor.new(Gdk.CursorType.SB_RIGHT_ARROW), + "drag-pitch": Gdk.Cursor.new(Gdk.CursorType.BOTTOM_SIDE), + "drag-duration": Gdk.Cursor.new(Gdk.CursorType.RIGHT_SIDE), + "drag-playhead": Gdk.Cursor.new(Gdk.CursorType.SB_H_DOUBLE_ARROW), + "pencil": Gdk.Cursor.new(Gdk.CursorType.PENCIL), + "paste": Gdk.Cursor.new(Gdk.CursorType.CENTER_PTR), + "error": None} self.recording = False self.recordLoop = None @@ -722,7 +725,7 @@ class Loop( Popup ): def handlePreviewMotion( self, widget, event ): if event.is_hint: - x, y, state = self.previewDA.window.get_pointer() + x, y, state = self.previewDA.get_window().get_pointer() event.x = float(x) event.y = float(y) event.state = state @@ -808,7 +811,7 @@ class Loop( Popup ): # draw background self.previewBuffer.draw_drawable( self.gc, self.sampleBg, 0, 0, 0, 0, self.previewDA.width-5, self.previewDA.height ) - self.previewBuffer.draw_drawable( self.gc, self.sampleBg, self.sampleBg.endOffset, 0, self.previewDA.width-5, 0, 5, self.previewDA.height ) + self.previewBuffer.draw_drawable( self.gc, self.sampleBg, self.sampleBg.get_width() - 5, 0, self.previewDA.width-5, 0, 5, self.previewDA.height ) # draw beat lines self.gc.set_line_attributes( Config.BEAT_LINE_SIZE, Gdk.LINE_ON_OFF_DASH, Gdk.CAP_BUTT, Gdk.JOIN_MITER ) @@ -821,28 +824,46 @@ class Loop( Popup ): self.gc.set_clip_mask( self.sampleNoteMask ) notes = self.owner.noteDB.getNotesByTrack( page, self.activeTrack, self ) for n in notes: + # TODO: + # LoopParasite changed signature to (ctx, x, y) if not n.draw( self.previewBuffer, self.gc, startX, stopX ): break self.previewDirty = False - def handlePreviewExpose( self, widget, event ): + def __draw_cb(self, widget, ctx): if self.previewDirty: self.previewDraw() - self.gc.set_clip_rectangle( event.area ) - # draw base - widget.window.draw_drawable( self.gc, self.previewBuffer, event.area.x, event.area.y, event.area.x, event.area.y, event.area.width, event.area.height ) + #Gtk.DrawingArea.do_draw(self, ctx) - if self.marqueeLoc: # draw the selection rect - self.gc.set_line_attributes( Config.MARQUEE_SIZE, Gdk.LINE_ON_OFF_DASH, Gdk.CAP_BUTT, Gdk.JOIN_MITER ) - self.gc.foreground = self.colors["Preview_Note_Selected"] - widget.window.draw_rectangle( self.gc, False, self.marqueeRect[0][0], self.marqueeRect[0][1], self.marqueeRect[1][0], self.marqueeRect[1][1] ) + # draw the selection rect + if self.marqueeLoc: + ctx.save() + ctx.set_line_width(Config.MARQUEE_SIZE) + ctx.set_dash((10,10)) # Gdk.LINE_ON_OFF_DASH equivalent? + ctx.set_line_cap(cairo.LINE_CAP_BUTT) + ctx.set_line_join(cairo.LINE_JOIN_MITER) + ctx.set_source_rgb(CairoUtil.gdk_color_to_cairo( + self.colors["Preview_Note_Selected"])) + ctx.rectangle(self.marqueeRect[0][0], self.marqueeRect[0][1], + self.marqueeRect[1][0], self.marqueeRect[1][1]) + ctx.stroke() + ctx.restore() if self.recording: # draw playhead - self.gc.set_line_attributes( Config.PLAYHEAD_SIZE, Gdk.LINE_SOLID, Gdk.CAP_BUTT, Gdk.JOIN_MITER ) - self.gc.foreground = self.colors["black"] - widget.window.draw_line( self.gc, self.playheadX, event.area.y, self.playheadX, event.area.y + event.area.height ) + ctx.save() + ctx.set_line_width(Config.PLAYHEAD_SIZE) + ctx.set_line_cap(cairo.LINE_CAP_BUTT) + ctx.set_line_join(cairo.LINE_JOIN_MITER) + ctx.set_source_rgb(CairoUtil.gdk_color_to_cairo( + self.colors["black"])) + # TODO: event properties is not available anymore + # use clipping? + ctx.rectangle(self.playheadX, event.area.y, self.playheadX, + event.area.y + event.area.height) + ctx.stroke() + ctx.restore() def invalidatePreview( self, x, y, width, height, page = -1, base = True ): if page != -1 and page != self.getPage(): @@ -863,8 +884,9 @@ class Loop( Popup ): self.previewDirtyRect = self.previewDirtyRect.union( self.dirtyRectToAdd ) self.previewDirty = True - if self.previewDA.window != None: - self.previewDA.window.invalidate_rect( self.dirtyRectToAdd, True ) + if self.previewDA.get_window() != None: + self.previewDA.get_window().invalidate_rect(self.dirtyRectToAdd, + True) #======================================================= # Recording @@ -1379,7 +1401,7 @@ class Loop( Popup ): self.setCursor("pencil") def setCursor( self, cursor ): - self.window.set_cursor(self.cursor[cursor]) + self.get_window().set_cursor(self.cursor[cursor]) def ticksToPixels( self, beats, ticks ): return int(round( ticks * self.pixelsPerTick[beats] )) @@ -1404,8 +1426,6 @@ class Shortcut( Popup ): def __init__( self, label, owner ): Popup.__init__( self, label, owner ) - self.gc = self.owner.gc - self.GUI = {} self.GUI["mainBox"] = Gtk.VBox() @@ -1425,7 +1445,7 @@ class Shortcut( Popup ): for row in layout: offset = row[0] hbox = Gtk.HBox() - self.GUI["keyBox"].pack_start( hbox, padding = 2 ) + self.GUI["keyBox"].pack_start(hbox, True, True, padding=2) separator = Gtk.Label(label="") separator.set_size_request( int(Block.Block.KEYSIZE*row[0]) + style.DEFAULT_PADDING, -1 ) hbox.pack_start(separator, False, True, 0) @@ -1434,7 +1454,7 @@ class Shortcut( Popup ): hbox.pack_end(separator, False, True, 0) for key in row[1]: self.GUI[key] = Gtk.ToggleButton() - self.GUI[key].connect( "expose-event", self.keyExpose ) + self.GUI[key].connect("draw", self.__draw_cb) self.GUI[key].connect( "toggled", self.keyToggled ) self.GUI[key].set_size_request( Block.Block.KEYSIZE, Block.Block.KEYSIZE ) self.GUI[key].key = key @@ -1481,10 +1501,13 @@ class Shortcut( Popup ): else: self.owner.onKeyPress( widget, event ) - def keyExpose( self, widget, event ): - self.gc.set_clip_mask( self.owner.blockMask ) - self.gc.set_clip_origin( event.area.x - Block.Block.KEYMASK_START, event.area.y ) - widget.window.draw_drawable( self.gc, widget.image[widget.get_active()], 0, 0, event.area.x, event.area.y, event.area.width, event.area.height ) + def __draw_cb(self, widget, ctx): + # TODO gtk3 no mask yet + #self.gc.set_clip_mask( self.owner.blockMask ) + #self.gc.set_clip_origin( event.area.x - Block.Block.KEYMASK_START, event.area.y ) + # TODO: why is doing this? + #widget.window.draw_drawable( self.gc, widget.image[widget.get_active()], 0, 0, event.area.x, event.area.y, event.area.width, event.area.height ) + Gtk.ToggleButton.do_draw(self, ctx) return True def keyToggled( self, widget ): -- cgit v0.9.1