diff options
-rw-r--r-- | Jam/Block.py | 173 | ||||
-rw-r--r-- | Jam/Desktop.py | 76 | ||||
-rw-r--r-- | Jam/JamMain.py | 212 | ||||
-rw-r--r-- | Jam/Parasite.py | 42 | ||||
-rw-r--r-- | Jam/Picker.py | 166 | ||||
-rw-r--r-- | Jam/Popup.py | 105 | ||||
-rw-r--r-- | common/Util/CairoUtil.py | 44 | ||||
-rw-r--r-- | common/Util/ThemeWidgets.py | 25 |
8 files changed, 523 insertions, 320 deletions
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 ): diff --git a/common/Util/CairoUtil.py b/common/Util/CairoUtil.py new file mode 100644 index 0000000..7918210 --- /dev/null +++ b/common/Util/CairoUtil.py @@ -0,0 +1,44 @@ +# useful methods to work with cairo in TamTam +from gi.repository import Gdk + +def gdk_color_to_cairo(color): + return (color.red / 65536.0, color.green / 65536.0, color.blue / 65536.0) + +def get_gdk_color(str_color): + result, color = Gdk.Color.parse(str_color) + return color + +def draw_round_rect(ctx, x, y, width, height, radio=10): + # Move to A + ctx.move_to(x + radio, y) + # Straight line to B + ctx.line_to(x + width - radio, y) + # Curve to C, Control points are both at Q + ctx.curve_to(x + width, y, x + width, y, x + width, y + radio) + # Move to D + ctx.line_to(x + width, y + height - radio) + # Curve to E + ctx.curve_to(x + width, y + height, x + width, y + height, + x + width - radio, y + height) + # Line to F + ctx.line_to(x + radio, y + height) + # Curve to G + ctx.curve_to(x, y + height, x, y + height, x, y + height - radio) + # Line to H + ctx.line_to(x, y + radio) + # Curve to A + ctx.curve_to(x, y, x, y, x + radio, y) + +def draw_drum_mask(ctx, x, y, size): + side = size / 3 + ctx.move_to(x + side, y) + ctx.new_path() + ctx.line_to(x + side * 2, y) + ctx.line_to(x + size, y + side) + ctx.line_to(x + size, y + side * 2) + ctx.line_to(x + side * 2, y + size) + ctx.line_to(x + side, y + size) + ctx.line_to(x, y + side * 2) + ctx.line_to(x, y + side) + ctx.line_to(x + side, y) + ctx.close_path() diff --git a/common/Util/ThemeWidgets.py b/common/Util/ThemeWidgets.py index 5eb6da5..a941ebf 100644 --- a/common/Util/ThemeWidgets.py +++ b/common/Util/ThemeWidgets.py @@ -4,15 +4,12 @@ import cairo import logging import common.Config as Config from common.Config import imagefile +from common.Util import CairoUtil from sugar3.graphics.combobox import ComboBox from sugar3.graphics.palette import Palette, WidgetInvoker -def gdk_color_to_cairo(color): - return (color.red / 65536.0, color.green / 65536.0, color.blue / 65536.0) - - class ImageVScale(Gtk.VScale): def __init__(self, image_name, adjustment=None, slider_border=0, @@ -703,7 +700,7 @@ class RoundFixed(Gtk.Fixed): # within the dirty rect, but drawing seems to be quite fast compared # to python code, so just leave it at clipping by each geometry feature - cr.set_source_rgb(*gdk_color_to_cairo(self.bordercolor)) + cr.set_source_rgb(*CairoUtil.gdk_color_to_cairo(self.bordercolor)) if self.borderW: if stopY > self.corner and startY < self.heightMINcorner: if startX < self.borderW: # draw left border @@ -1223,30 +1220,16 @@ class keyButton(Gtk.Button): self.cr = self.window.cairo_create() self.cr.set_source_rgb(self.fillcolor[0], self.fillcolor[1], self.fillcolor[2]) - self.draw_round_rect(self.cr, self.drawX - self.width // 2, + CairoUtil.draw_round_rect(self.cr, self.drawX - self.width // 2, self.drawY - self.height // 2, self.width, self.height, 10) self.cr.fill() self.cr.set_line_width(3) self.cr.set_source_rgb(self.strokecolor[0], self.strokecolor[1], self.strokecolor[2]) - self.draw_round_rect(self.cr, self.drawX - self.width // 2, + CairoUtil.draw_round_rect(self.cr, self.drawX - self.width // 2, self.drawY - self.height // 2, self.width, self.height, 10) self.cr.stroke() - def draw_round_rect(self, context, x, y, w, h, r): - context.move_to(x + r, y) # Move to A - context.line_to(x + w - r, y) # Straight line to B - # Curve to C, Control points are both at Q - context.curve_to(x + w, y, x + w, y, x + w, y + r) - context.line_to(x + w, y + h - r) # Move to D - # Curve to E - context.curve_to(x + w, y + h, x + w, y + h, x + w - r, y + h) - context.line_to(x + r, y + h) # Line to F - context.curve_to(x, y + h, x, y + h, x, y + h - r) # Curve to G - context.line_to(x, y + r) # Line to H - context.curve_to(x, y, x, y, x + r, y) # Curve to A - return - def set_fillcolor(self, r, g, b): self.fillcolor = [r, g, b] self.queue_draw() |