Changeset - 547d65ea9902
[Not reviewed]
default
0 9 0
Drew Perttula - 11 years ago 2014-06-01 20:35:38
drewp@bigasterisk.com
port curvecalc to gtk3. mostly worked, but there are severe bugs with redraws
Ignore-this: 2a9ba18d1c180831446257054e5d7e8a
9 files changed with 378 insertions and 315 deletions:
0 comments (0 inline, 0 general)
bin/curvecalc
Show inline comments
 
@@ -4,139 +4,145 @@
 
now launches like this:
 
% bin/curvecalc http://light9.bigasterisk.com/show/dance2007/song1
 

	
 

	
 

	
 
todo: curveview should preserve more objects, for speed maybe
 

	
 
"""
 
from __future__ import division
 

	
 
import sys
 
sys.path.append('/usr/lib/python2.7/dist-packages') # For gtk
 
from twisted.internet import gtk2reactor
 
gtk2reactor.install()
 
from twisted.internet import gtk3reactor
 
gtk3reactor.install()
 
from twisted.internet import reactor
 

	
 
import time, textwrap, os, optparse, gtk, linecache, signal, traceback, json
 
import time, textwrap, os, optparse, linecache, signal, traceback, json
 
import gi
 
from gi.repository import Gtk
 
from gi.repository import GObject
 
from gi.repository import Gdk
 

	
 
from urlparse import parse_qsl
 
import louie as dispatcher 
 
from rdflib import URIRef, Literal, RDF, RDFS
 
import logging
 

	
 
from run_local import log
 
from light9 import showconfig, networking
 
from light9.rdfdb import clientsession
 
from light9.curvecalc.curve import Curveset
 
from light9.curvecalc import curveview 
 
from light9.curvecalc.musicaccess import Music
 
from light9.wavelength import wavelength
 
from light9.namespaces import L9
 
from light9.curvecalc.subterm import Subterm
 
from light9.curvecalc.subtermview import add_one_subterm
 
from light9.curvecalc.output import Output
 
from light9.gtkpyconsole import togglePyConsole
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from light9.rdfdb.patch import Patch
 
from light9.editchoicegtk import EditChoice
 
from light9.editchoicegtk import EditChoice, Local
 
from light9.observable import Observable
 

	
 
class SubtermExists(ValueError):
 
    pass
 

	
 
class Main(object):
 
    def __init__(self, graph, opts, session, curveset, music):
 
        self.graph, self.opts, self.session = graph, opts, session
 
        self.curveset, self.music = curveset, music
 
        self.lastSeenInputTime = 0
 
        self.currentSubterms = [] # Subterm objects that are synced to the graph
 

	
 
        wtree = self.wtree = gtk.Builder()
 
        wtree = self.wtree = Gtk.Builder()
 
        wtree.add_from_file("light9/curvecalc/curvecalc.glade")
 
        mainwin = wtree.get_object("MainWindow")
 
        
 
        mainwin.connect("destroy", self.onQuit)
 
        wtree.connect_signals(self)
 
        gtk.rc_parse("theme/marble-ice/gtk-2.0/gtkrc")
 
        gtk.rc_parse_string("""style "default" {font_name = "sans 9"}""")
 
        Gtk.rc_parse("theme/marble-ice/gtk-2.0/gtkrc")
 
        Gtk.rc_parse_string("""style "default" {font_name = "sans 9"}""")
 
        if self.opts.reload:
 
            self.refreshTheme()
 
        mainwin.show_all()
 

	
 
        mainwin.connect("delete-event", lambda *args: reactor.crash())
 
        def updateTitle():
 
            mainwin.set_title("curvecalc - %s" %
 
                              graph.label(
 
                                  graph.value(session, L9['currentSong'])))
 
        graph.addHandler(updateTitle)
 
        mainwin.parse_geometry("1x1-0+0")
 

	
 
        # this is the only one i found that would set the size right,
 
        # but it's a minimum size, which i don't really want
 
        mainwin.set_size_request(1678, 922)
 

	
 
        songChoice = Observable(None) # to be connected with the session song
 

	
 
        def setSong():
 
            songChoice(graph.value(session, L9['currentSong']))
 
            dispatcher.send("song_has_changed")
 
        graph.addHandler(setSong)
 
        # next here, watch songChoice and patch the graph
 
        def songToGraph(newSong):
 
            if newSong is Local:
 
                raise NotImplementedError('what do i patch')
 
            graph.patchObject(context=session, subject=session,
 
                              predicate=L9['currentSong'], newObject=newSong)
 
        songChoice.subscribe(songToGraph)
 
        def current_player_song(song):
 
            # (this is run on every frame)
 
            ps = wtree.get_object("playerSong")
 
            if URIRef(ps.get_uri()) != song:
 
                print "update playerSong"
 
                def setLabel():
 
                    ps.set_label(graph.label(song))
 
                graph.addHandler(setLabel)
 
                ps.set_uri(song)
 
            if song != songChoice():
 
                if wtree.get_object("followPlayerSongChoice").get_active():
 
                    songChoice(song)
 
                
 
        self.current_player_song = current_player_song
 
        dispatcher.connect(current_player_song, "current_player_song")
 
        
 

	
 
        ec = EditChoice(graph, songChoice, label="Editing song:")
 
        wtree.get_object("currentSongEditChoice").add(ec)
 
        ec.show()
 
        
 
        wtree.get_object("subterms").connect("add", self.onSubtermChildAdded)
 
        
 

	
 
        self.refreshCurveView()       
 
        
 
        self.makeStatusLines(wtree.get_object("status"))
 
        self.setupNewSubZone()
 
        self.acceptDragsOnCurveViews()
 
                
 
        # may not work
 
        wtree.get_object("paned1").set_position(600)
 

	
 
    def setupNewSubZone(self):
 
        self.wtree.get_object("newSubZone").drag_dest_set(
 
            flags=gtk.DEST_DEFAULT_ALL,
 
            targets=[('text/uri-list', 0, 0)],
 
            actions=gtk.gdk.ACTION_COPY)
 
            flags=Gtk.DestDefaults.ALL,
 
            targets=[Gtk.TargetEntry('text/uri-list', 0, 0)],
 
            actions=Gdk.DragAction.COPY)
 
        
 
    def acceptDragsOnCurveViews(self):
 
        w = self.wtree.get_object("curves")
 
        w.drag_dest_set(flags=gtk.DEST_DEFAULT_ALL,
 
                        targets=[('text/uri-list', 0, 0)],
 
                        actions=gtk.gdk.ACTION_COPY)
 
        w.drag_dest_set(flags=Gtk.DestDefaults.ALL,
 
                        targets=[Gtk.TargetEntry('text/uri-list', 0, 0)],
 
                        actions=Gdk.DragAction.COPY)
 
        def recv(widget, context, x, y, selection,
 
                       targetType, time):
 
            subUri = URIRef(selection.data.strip())
 
            print "into curves", subUri
 
            with self.graph.currentState(
 
                    tripleFilter=(subUri, RDFS.label, None)) as current:
 
                subName = current.label(subUri)
 

	
 
            if '?' in subUri:
 
                subName = self.handleSubtermDrop(subUri)
 
            else:
 
                try:
 
@@ -286,25 +292,25 @@ class Main(object):
 
            newList.append(term)
 
        self.currentSubterms[:] = newList
 

	
 
        master = self.wtree.get_object("subterms")
 
        log.debug("removing subterm widgets")
 
        [master.remove(c) for c in master.get_children()]
 
        for term in self.currentSubterms:
 
            add_one_subterm(term, self.curveset, master)
 
        master.show_all()
 
        log.debug("%s table children showing" % len(master.get_children()))
 
        
 
    def refreshTheme(self):
 
        gtk.rc_reparse_all()
 
        Gtk.rc_reparse_all()
 
        reactor.callLater(1, self.refreshTheme)
 

	
 
    def onSubtermChildAdded(self, subtermsTable, *args):
 
        # this would probably work, but isn't getting called
 
        log.info("onSubtermChildAdded")
 
        v = subtermsTable.get_parent().props.vadjustment
 
        v.props.value = v.props.upper
 

	
 
    def onQuit(self, *args):
 
        reactor.crash()
 
        # there's a hang after this, maybe in sem_wait in two
 
        # threads. I don't know whose they are.
 
@@ -351,26 +357,26 @@ class Main(object):
 
    def makeStatusLines(self, master):
 
        """various labels that listen for dispatcher signals"""
 
        for row, (signame, textfilter) in enumerate([
 
            ('input time', lambda t: "%.2fs"%t),
 
            ('output levels',
 
             lambda levels: textwrap.fill("; ".join(["%s:%.2f"%(n,v)
 
                                                     for n,v in
 
                                                     levels.items()[:2]
 
                                                     if v>0]),70)),
 
            ('update period', lambda t: "%.1fms"%(t*1000)),
 
            ('update status', lambda x: str(x)),
 
            ]):
 
            key = gtk.Label("%s:" % signame)
 
            value = gtk.Label("")
 
            key = Gtk.Label("%s:" % signame)
 
            value = Gtk.Label("")
 
            master.resize(row + 1, 2)
 
            master.attach(key, 0, 1, row, row + 1)
 
            master.attach(value, 1, 2, row, row + 1)
 
            key.set_alignment(1, 0)
 
            value.set_alignment(0, 0)
 

	
 
            dispatcher.connect(lambda val, value=value, tf=textfilter:
 
                               value.set_text(tf(val)),
 
                               signame, weak=False)
 
        dispatcher.connect(lambda val: setattr(self, 'lastSeenInputTime', val),
 
                           'input time', weak=False)
 
        master.show_all()
 
@@ -448,24 +454,25 @@ def launch(args, graph, session, opts, s
 
        pass
 

	
 
    curveset = Curveset(graph=graph, session=session, sliders=opts.sliders)
 
        
 
    log.debug("startup: output %s", time.time() - startTime)
 

	
 
    mt = MaxTime(graph, session)
 
    dispatcher.connect(lambda: mt.get(), "get max time", weak=False)
 

	
 
    start = Main(graph, opts, session, curveset, music)
 
    out = Output(graph, session, music, curveset, start.currentSubterms)
 

	
 

	
 
    dispatcher.send("show all")
 
        
 
    if opts.startup_only:
 
        log.debug("quitting now because of --startup-only")
 
        return
 

	
 
    from twisted.web import server, resource
 
    class Hover(resource.Resource):
 
        isLeaf = True
 
        def render_GET(self, request):
 
            if request.path == '/hoverTime':
 
                results = dispatcher.send("onPlayPause")
lib/ipython_view.py
Show inline comments
 
@@ -6,29 +6,30 @@ Backend to the console plugin.
 
@author: Eitan Isaacson
 
@organization: IBM Corporation
 
@copyright: Copyright (c) 2007 IBM Corporation
 
@license: BSD
 
 
 
All rights reserved. This program and the accompanying materials are made 
 
available under the terms of the BSD which accompanies this distribution, and 
 
is available at U{http://www.opensource.org/licenses/bsd-license.php}
 
"""
 
# this file is a modified version of source code from the Accerciser project
 
# http://live.gnome.org/accerciser
 
 
 
import gtk
 
from gi.repository import Gtk
 
from gi.repository import Gdk
 
import re
 
import sys
 
import os
 
import pango
 
from gi.repository import Pango
 
from StringIO import StringIO
 
 
 
try:
 
	import IPython
 
except Exception,e:
 
	raise "Error importing IPython (%s)" % str(e)
 
 
 
ansi_colors =  {'0;30': 'Black',
 
                '0;31': 'Red',
 
                '0;32': 'Green',
 
                '0;33': 'Brown',
 
                '0;34': 'Blue',
 
@@ -146,28 +147,28 @@ class IterableIPShell:
 
    return str1
 
 
 
  def shell(self, cmd,verbose=0,debug=0,header=''):
 
    stat = 0
 
    if verbose or debug: print header+cmd
 
    # flush stdout so we don't mangle python's buffering
 
    if not debug:
 
      input, output = os.popen4(cmd)
 
      print output.read()
 
      output.close()
 
      input.close()
 
 
 
class ConsoleView(gtk.TextView):
 
class ConsoleView(Gtk.TextView):
 
  def __init__(self):
 
    gtk.TextView.__init__(self)
 
    self.modify_font(pango.FontDescription('Mono'))
 
    Gtk.TextView.__init__(self)
 
    self.modify_font(Pango.FontDescription('Mono'))
 
    self.set_cursor_visible(True)
 
    self.text_buffer = self.get_buffer()
 
    self.mark = self.text_buffer.create_mark('scroll_mark', 
 
                                             self.text_buffer.get_end_iter(),
 
                                             False)
 
    for code in ansi_colors:
 
      self.text_buffer.create_tag(code, 
 
                                  foreground=ansi_colors[code], 
 
                                  weight=700)
 
    self.text_buffer.create_tag('0')
 
    self.text_buffer.create_tag('notouch', editable=False)
 
    self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
 
@@ -258,39 +259,39 @@ class IPythonView(ConsoleView, IterableI
 
    self.execute()
 
    self.cout.truncate(0)
 
    self.showPrompt(self.prompt)
 
    self.interrupt = False
 
 
 
  def raw_input(self, prompt=''):
 
    if self.interrupt:
 
      self.interrupt = False
 
      raise KeyboardInterrupt
 
    return self.getCurrentLine()
 
 
 
  def keyPress(self, widget, event):
 
    if event.state & gtk.gdk.CONTROL_MASK and event.keyval == 99:
 
    if event.state & Gdk.ModifierType.CONTROL_MASK and event.keyval == 99:
 
      self.interrupt = True
 
      self._processLine()
 
      return True
 
    elif event.keyval == gtk.keysyms.Return:
 
    elif event.keyval == Gtk.keysyms.Return:
 
      self._processLine()
 
      return True
 
    elif event.keyval == gtk.keysyms.Up:
 
    elif event.keyval == Gtk.keysyms.Up:
 
      self.changeLine(self.historyBack())
 
      return True
 
    elif event.keyval == gtk.keysyms.Down:
 
    elif event.keyval == Gtk.keysyms.Down:
 
      self.changeLine(self.historyForward())
 
      return True
 
    # todo: Home needs to advance past the ipython prompt
 
    elif event.keyval == gtk.keysyms.Tab:
 
    elif event.keyval == Gtk.keysyms.Tab:
 
      if not self.getCurrentLine().strip():
 
        return False
 
      completed, possibilities = self.complete(self.getCurrentLine())
 
      if len(possibilities) > 1:
 
        slice = self.getCurrentLine()
 
        self.write('\n')
 
        for symbol in possibilities:
 
          self.write(symbol+'\n')
 
        self.showPrompt(self.prompt)
 
      self.changeLine(completed or slice)
 
      return True
 
 
light9/curvecalc/curvecalc.glade
Show inline comments
 
<?xml version="1.0" encoding="UTF-8"?>
 
<!-- Generated with glade 3.16.1 -->
 
<interface>
 
  <requires lib="gtk+" version="2.24"/>
 
  <!-- interface-naming-policy toplevel-contextual -->
 
  <requires lib="gtk+" version="3.10"/>
 
  <object class="GtkAccelGroup" id="accelgroup1"/>
 
  <object class="GtkAdjustment" id="adjustment1">
 
    <property name="upper">100</property>
 
    <property name="step_increment">1</property>
 
    <property name="page_increment">10</property>
 
  </object>
 
  <object class="GtkTextBuffer" id="help">
 
    <property name="text">Mousewheel zoom; C-p play/pause music at mouse
 
Drag sub into curve area for new curve+subterm
 
Keys in a selected curve: C to collapse; R to rebuild broken canvas widget; 1..5 add point at time cursor; q,w,e,r,t,y set marker at time cursor
 
Curve point bindings: B1 drag point; C-B1 curve add point; S-B1 sketch points; B1 drag select points
 
Available in functions: nsin/ncos period=amp=1; within(a,b) bef(x) aft(x) compare to time; smoove(x) cubic smoothstep; chan(name); curvename(t) eval curve</property>
 
  </object>
 
  <object class="GtkWindow" id="MainWindow">
 
    <property name="can_focus">False</property>
 
    <child>
 
      <object class="GtkVBox" id="vbox1">
 
        <property name="visible">True</property>
 
        <property name="can_focus">False</property>
 
        <child>
 
          <object class="GtkMenuBar" id="menubar1">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem1">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">_Curvecalc</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu1">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <child>
 
                      <object class="GtkImageMenuItem" id="imagemenuitem2">
 
                        <property name="label">gtk-save</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="use_underline">True</property>
 
                        <property name="use_stock">True</property>
 
                        <signal name="activate" handler="onSave" swapped="no"/>
 
                        <accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
 
                        <signal name="activate" handler="onSave" swapped="no"/>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkImageMenuItem" id="imagemenuitem5">
 
                        <property name="label">gtk-quit</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="use_underline">True</property>
 
                        <property name="use_stock">True</property>
 
                        <signal name="activate" handler="onQuit" swapped="no"/>
 
                        <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
 
                        <signal name="activate" handler="onQuit" swapped="no"/>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem7">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">_Edit</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu5">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <child>
 
                      <object class="GtkImageMenuItem" id="imagemenuitem1">
 
                        <property name="label">gtk-cut</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="use_underline">True</property>
 
                        <property name="use_stock">True</property>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkImageMenuItem" id="imagemenuitem3">
 
                        <property name="label">gtk-copy</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="use_underline">True</property>
 
                        <property name="use_stock">True</property>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkImageMenuItem" id="imagemenuitem4">
 
                        <property name="label">gtk-paste</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="use_underline">True</property>
 
                        <property name="use_stock">True</property>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkImageMenuItem" id="imagemenuitem6">
 
                        <property name="label">gtk-delete</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="use_underline">True</property>
 
                        <property name="use_stock">True</property>
 
                        <signal name="activate" handler="onDelete" swapped="no"/>
 
                        <accelerator key="Delete" signal="activate"/>
 
                        <signal name="activate" handler="onDelete" swapped="no"/>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem13">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">_Create</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu6">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <property name="ubuntu_local">True</property>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem14">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Curve...</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onNewCurve" swapped="no"/>
 
                        <accelerator key="n" signal="activate" modifiers="GDK_CONTROL_MASK"/>
 
                        <signal name="activate" handler="onNewCurve" swapped="no"/>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem15">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Subterm...</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onNewSubterm" swapped="no"/>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem2">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">_View</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu2">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem8">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">See current time</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onSeeCurrentTime" swapped="no"/>
 
                        <accelerator key="Escape" signal="activate"/>
 
                        <signal name="activate" handler="onSeeCurrentTime" swapped="no"/>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem9">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">See from current time -&gt; end</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onSeeTimeUntilEnd" swapped="no"/>
 
                        <accelerator key="Escape" signal="activate" modifiers="GDK_SHIFT_MASK"/>
 
                        <signal name="activate" handler="onSeeTimeUntilEnd" swapped="no"/>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem10">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Zoom all</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onZoomAll" swapped="no"/>
 
                        <accelerator key="Escape" signal="activate" modifiers="GDK_CONTROL_MASK"/>
 
                        <signal name="activate" handler="onZoomAll" swapped="no"/>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem11">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Zoom in (wheel up)</property>
 
                        <property name="use_underline">True</property>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem12">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Zoom out (wheel down)</property>
 
                        <property name="use_underline">True</property>
 
                      </object>
 
                    </child>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem17">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Redraw curves</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onRedrawCurves" swapped="no"/>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem3">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">_Playback</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu3">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem5">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">_Play/pause</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="activate" handler="onPlayPause" swapped="no"/>
 
                        <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
 
                        <signal name="activate" handler="onPlayPause" swapped="no"/>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem4">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">Poin_ts</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu4">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <child>
 
                      <object class="GtkMenuItem" id="menuitem6">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Delete</property>
 
                        <property name="use_underline">True</property>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
            <child>
 
              <object class="GtkMenuItem" id="menuitem16">
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="label" translatable="yes">Debug</property>
 
                <property name="use_underline">True</property>
 
                <child type="submenu">
 
                  <object class="GtkMenu" id="menu7">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <property name="ubuntu_local">True</property>
 
                    <child>
 
                      <object class="GtkCheckMenuItem" id="checkmenuitem1">
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="use_action_appearance">False</property>
 
                        <property name="label" translatable="yes">Python console</property>
 
                        <property name="use_underline">True</property>
 
                        <signal name="toggled" handler="onPythonConsole" swapped="no"/>
 
                        <accelerator key="p" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
 
                        <signal name="toggled" handler="onPythonConsole" swapped="no"/>
 
                      </object>
 
                    </child>
 
                  </object>
 
                </child>
 
              </object>
 
            </child>
 
          </object>
 
          <packing>
 
            <property name="expand">False</property>
 
            <property name="fill">True</property>
 
            <property name="position">0</property>
 
          </packing>
 
@@ -331,46 +342,47 @@
 
                <property name="label" translatable="yes">Player is on song </property>
 
                <property name="justify">right</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">1</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <object class="GtkLinkButton" id="playerSong">
 
                <property name="label" translatable="yes">(song)</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="has_tooltip">True</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="relief">none</property>
 
                <property name="xalign">0</property>
 
                <property name="uri">http://glade.gnome.org</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">2</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <object class="GtkCheckButton" id="followPlayerSongChoice">
 
                <property name="label" translatable="yes">follow player song choice</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="receives_default">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="xalign">0.5</property>
 
                <property name="draw_indicator">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="padding">15</property>
 
                <property name="position">3</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <placeholder/>
 
            </child>
 
@@ -397,59 +409,59 @@
 
                  <object class="GtkVBox" id="vbox4">
 
                    <property name="height_request">100</property>
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <child>
 
                      <object class="GtkHBox" id="hbox2">
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="spacing">7</property>
 
                        <child>
 
                          <object class="GtkButton" id="button22">
 
                            <property name="label">gtk-add</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">True</property>
 
                            <property name="receives_default">True</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <property name="use_stock">True</property>
 
                            <signal name="clicked" handler="onNewCurve" swapped="no"/>
 
                          </object>
 
                          <packing>
 
                            <property name="expand">False</property>
 
                            <property name="fill">False</property>
 
                            <property name="position">0</property>
 
                          </packing>
 
                        </child>
 
                        <child>
 
                          <object class="GtkButton" id="button7">
 
                            <property name="label" translatable="yes">Collapse all</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">True</property>
 
                            <property name="receives_default">True</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <signal name="clicked" handler="onCollapseAll" swapped="no"/>
 
                          </object>
 
                          <packing>
 
                            <property name="expand">False</property>
 
                            <property name="fill">True</property>
 
                            <property name="position">1</property>
 
                          </packing>
 
                        </child>
 
                        <child>
 
                          <object class="GtkButton" id="button6">
 
                            <property name="label" translatable="yes">Collapse none	</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">True</property>
 
                            <property name="receives_default">True</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <signal name="clicked" handler="onCollapseNone" swapped="no"/>
 
                          </object>
 
                          <packing>
 
                            <property name="expand">False</property>
 
                            <property name="fill">True</property>
 
                            <property name="position">2</property>
 
                          </packing>
 
                        </child>
 
                        <child>
 
                          <placeholder/>
 
                        </child>
 
                        <child>
 
@@ -457,47 +469,51 @@
 
                        </child>
 
                        <child>
 
                          <placeholder/>
 
                        </child>
 
                      </object>
 
                      <packing>
 
                        <property name="expand">False</property>
 
                        <property name="fill">False</property>
 
                        <property name="position">0</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <object class="GtkVBox" id="zoomControlBox">
 
                      <object class="GtkBox" id="zoomControlBox">
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <property name="orientation">vertical</property>
 
                        <child>
 
                          <object class="GtkLabel" id="zoomControl">
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">False</property>
 
                            <property name="label" translatable="yes">[zoom control]</property>
 
                          </object>
 
                          <packing>
 
                            <property name="expand">False</property>
 
                            <property name="fill">True</property>
 
                            <property name="position">0</property>
 
                          </packing>
 
                        </child>
 
                      </object>
 
                      <packing>
 
                        <property name="expand">False</property>
 
                        <property name="fill">True</property>
 
                        <property name="position">1</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                    <child>
 
                      <object class="GtkScrolledWindow" id="scrolledwindow1">
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">True</property>
 
                        <property name="hscrollbar_policy">never</property>
 
                        <child>
 
                          <object class="GtkViewport" id="viewport2">
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">False</property>
 
                            <child>
 
                              <object class="GtkEventBox" id="eventbox1">
 
                                <property name="visible">True</property>
 
                                <property name="can_focus">True</property>
 
@@ -515,25 +531,25 @@
 
                                      <placeholder/>
 
                                    </child>
 
                                  </object>
 
                                </child>
 
                              </object>
 
                            </child>
 
                          </object>
 
                        </child>
 
                      </object>
 
                      <packing>
 
                        <property name="expand">True</property>
 
                        <property name="fill">True</property>
 
                        <property name="position">2</property>
 
                        <property name="position">3</property>
 
                      </packing>
 
                    </child>
 
                  </object>
 
                </child>
 
                <child type="label">
 
                  <object class="GtkLabel" id="label10">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <property name="label" translatable="yes">Curves</property>
 
                  </object>
 
                </child>
 
              </object>
 
@@ -561,32 +577,43 @@
 
                        <child>
 
                          <object class="GtkViewport" id="viewport1">
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">False</property>
 
                            <property name="vadjustment">adjustment1</property>
 
                            <property name="shadow_type">none</property>
 
                            <child>
 
                              <object class="GtkTable" id="subterms">
 
                                <property name="visible">True</property>
 
                                <property name="can_focus">False</property>
 
                                <property name="n_columns">2</property>
 
                                <signal name="add" handler="onSubtermChildAdded" swapped="no"/>
 
                                <signal name="child-added" handler="onSubtermChildAdded" swapped="no"/>
 
                                <signal name="map" handler="onSubtermsMap" swapped="no"/>
 
                                <child>
 
                                  <placeholder/>
 
                                </child>
 
                                <child>
 
                                  <placeholder/>
 
                                </child>
 
                                <child>
 
                                  <placeholder/>
 
                                </child>
 
                                <child>
 
                                  <placeholder/>
 
                                </child>
 
                                <child>
 
                                  <placeholder/>
 
                                </child>
 
                                <child>
 
                                  <placeholder/>
 
                                </child>
 
                              </object>
 
                            </child>
 
                          </object>
 
                        </child>
 
                      </object>
 
                      <packing>
 
                        <property name="expand">True</property>
 
                        <property name="fill">True</property>
 
                        <property name="position">0</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
@@ -604,28 +631,28 @@
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <object class="GtkHBox" id="box2">
 
                        <property name="visible">True</property>
 
                        <property name="can_focus">False</property>
 
                        <child>
 
                          <placeholder/>
 
                        </child>
 
                        <child>
 
                          <object class="GtkButton" id="button2">
 
                            <property name="label">gtk-add</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <property name="visible">True</property>
 
                            <property name="can_focus">True</property>
 
                            <property name="receives_default">True</property>
 
                            <property name="use_action_appearance">False</property>
 
                            <property name="use_stock">True</property>
 
                            <signal name="clicked" handler="onNewSubterm" swapped="no"/>
 
                          </object>
 
                          <packing>
 
                            <property name="expand">False</property>
 
                            <property name="fill">False</property>
 
                            <property name="position">1</property>
 
                          </packing>
 
                        </child>
 
                        <child>
 
                          <placeholder/>
 
                        </child>
 
@@ -670,24 +697,36 @@
 
                <property name="shadow_type">none</property>
 
                <child>
 
                  <object class="GtkTable" id="status">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <property name="n_columns">2</property>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                    <child>
 
                      <placeholder/>
 
                    </child>
 
                  </object>
 
                </child>
 
                <child type="label">
 
                  <object class="GtkLabel" id="label1">
 
                    <property name="visible">True</property>
 
                    <property name="can_focus">False</property>
 
                    <property name="label" translatable="yes">Status</property>
 
                    <property name="use_markup">True</property>
 
                  </object>
 
                </child>
 
              </object>
 
              <packing>
 
@@ -712,180 +751,72 @@
 
            </child>
 
          </object>
 
          <packing>
 
            <property name="expand">False</property>
 
            <property name="fill">False</property>
 
            <property name="padding">5</property>
 
            <property name="position">3</property>
 
          </packing>
 
        </child>
 
      </object>
 
    </child>
 
  </object>
 
  <object class="GtkAccelGroup" id="accelgroup1"/>
 
  <object class="GtkAdjustment" id="adjustment1">
 
    <property name="upper">100</property>
 
    <property name="step_increment">1</property>
 
    <property name="page_increment">10</property>
 
  </object>
 
  <object class="GtkTextBuffer" id="help">
 
    <property name="text">Mousewheel zoom; C-p play/pause music at mouse
 
Drag sub into curve area for new curve+subterm
 
Keys in a selected curve: C to collapse; R to rebuild broken canvas widget; 1..5 add point at time cursor; q,w,e,r,t,y set marker at time cursor
 
Curve point bindings: B1 drag point; C-B1 curve add point; S-B1 sketch points; B1 drag select points
 
Available in functions: nsin/ncos period=amp=1; within(a,b) bef(x) aft(x) compare to time; smoove(x) cubic smoothstep; chan(name); curvename(t) eval curve</property>
 
  </object>
 
  <object class="GtkImage" id="image2">
 
    <property name="visible">True</property>
 
    <property name="can_focus">False</property>
 
    <property name="stock">gtk-refresh</property>
 
  </object>
 
  <object class="GtkListStore" id="liststore1"/>
 
  <object class="GtkDialog" id="newCurve">
 
    <property name="can_focus">False</property>
 
    <property name="border_width">5</property>
 
    <property name="title" translatable="yes">New curve</property>
 
    <property name="modal">True</property>
 
    <property name="window_position">mouse</property>
 
    <property name="type_hint">normal</property>
 
    <child internal-child="vbox">
 
      <object class="GtkVBox" id="dialog-vbox1">
 
        <property name="visible">True</property>
 
        <property name="can_focus">False</property>
 
        <property name="spacing">2</property>
 
        <child internal-child="action_area">
 
          <object class="GtkHButtonBox" id="dialog-action_area1">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <property name="layout_style">end</property>
 
            <child>
 
              <object class="GtkButton" id="button5">
 
                <property name="label">gtk-cancel</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="use_stock">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">0</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <object class="GtkButton" id="button4">
 
                <property name="label">gtk-add</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="can_default">True</property>
 
                <property name="has_default">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="use_stock">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">1</property>
 
              </packing>
 
            </child>
 
          </object>
 
          <packing>
 
            <property name="expand">False</property>
 
            <property name="fill">True</property>
 
            <property name="pack_type">end</property>
 
            <property name="position">0</property>
 
          </packing>
 
        </child>
 
        <child>
 
          <object class="GtkLabel" id="label12">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <property name="label" translatable="yes">Name for new curve</property>
 
          </object>
 
          <packing>
 
            <property name="expand">True</property>
 
            <property name="fill">True</property>
 
            <property name="position">1</property>
 
          </packing>
 
        </child>
 
        <child>
 
          <object class="GtkEntry" id="newCurveName">
 
            <property name="visible">True</property>
 
            <property name="can_focus">True</property>
 
            <property name="has_focus">True</property>
 
            <property name="is_focus">True</property>
 
            <property name="invisible_char">●</property>
 
            <property name="activates_default">True</property>
 
            <property name="primary_icon_activatable">False</property>
 
            <property name="secondary_icon_activatable">False</property>
 
            <property name="primary_icon_sensitive">True</property>
 
            <property name="secondary_icon_sensitive">True</property>
 
          </object>
 
          <packing>
 
            <property name="expand">True</property>
 
            <property name="fill">True</property>
 
            <property name="position">2</property>
 
          </packing>
 
        </child>
 
      </object>
 
    </child>
 
    <action-widgets>
 
      <action-widget response="2">button5</action-widget>
 
      <action-widget response="1">button4</action-widget>
 
    </action-widgets>
 
  </object>
 
  <object class="GtkDialog" id="newSubterm">
 
    <property name="can_focus">False</property>
 
    <property name="border_width">5</property>
 
    <property name="type">popup</property>
 
    <property name="title" translatable="yes">New curve</property>
 
    <property name="modal">True</property>
 
    <property name="window_position">mouse</property>
 
    <property name="type_hint">normal</property>
 
    <child internal-child="vbox">
 
      <object class="GtkVBox" id="dialog-vbox3">
 
      <object class="GtkBox" id="dialog-vbox3">
 
        <property name="visible">True</property>
 
        <property name="can_focus">False</property>
 
        <property name="spacing">2</property>
 
        <child internal-child="action_area">
 
          <object class="GtkHButtonBox" id="dialog-action_area3">
 
          <object class="GtkButtonBox" id="dialog-action_area3">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <property name="layout_style">end</property>
 
            <child>
 
              <object class="GtkButton" id="button12">
 
                <property name="label">gtk-cancel</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="use_stock">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">0</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <object class="GtkButton" id="button3">
 
                <property name="label">gtk-add</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="can_default">True</property>
 
                <property name="has_default">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="use_stock">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">1</property>
 
              </packing>
 
            </child>
 
          </object>
 
          <packing>
 
            <property name="expand">False</property>
 
            <property name="fill">True</property>
 
@@ -909,62 +840,166 @@ Available in functions: nsin/ncos period
 
          <object class="GtkVBox" id="vbox11">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <child>
 
              <object class="GtkComboBox" id="newSubtermName">
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="has_focus">True</property>
 
                <property name="is_focus">True</property>
 
                <property name="model">liststore1</property>
 
                <property name="has_entry">True</property>
 
                <property name="entry_text_column">0</property>
 
                <child internal-child="entry">
 
                  <object class="GtkEntry" id="combobox-entry1">
 
                    <property name="can_focus">False</property>
 
                  </object>
 
                </child>
 
              </object>
 
              <packing>
 
                <property name="expand">True</property>
 
                <property name="fill">True</property>
 
                <property name="position">0</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <object class="GtkCheckButton" id="newSubtermMakeCurve">
 
                <property name="label" translatable="yes">_Make new curve with the same name</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="receives_default">False</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="use_underline">True</property>
 
                <property name="xalign">0.5</property>
 
                <property name="active">True</property>
 
                <property name="draw_indicator">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">True</property>
 
                <property name="fill">True</property>
 
                <property name="position">1</property>
 
              </packing>
 
            </child>
 
          </object>
 
          <packing>
 
            <property name="expand">True</property>
 
            <property name="fill">True</property>
 
            <property name="position">2</property>
 
          </packing>
 
        </child>
 
      </object>
 
    </child>
 
    <action-widgets>
 
      <action-widget response="2">button12</action-widget>
 
      <action-widget response="1">button3</action-widget>
 
    </action-widgets>
 
  </object>
 
  <object class="GtkDialog" id="newCurve">
 
    <property name="can_focus">False</property>
 
    <property name="border_width">5</property>
 
    <property name="title" translatable="yes">New curve</property>
 
    <property name="modal">True</property>
 
    <property name="window_position">mouse</property>
 
    <property name="type_hint">normal</property>
 
    <child internal-child="vbox">
 
      <object class="GtkBox" id="dialog-vbox1">
 
        <property name="visible">True</property>
 
        <property name="can_focus">False</property>
 
        <property name="spacing">2</property>
 
        <child internal-child="action_area">
 
          <object class="GtkButtonBox" id="dialog-action_area1">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <property name="layout_style">end</property>
 
            <child>
 
              <object class="GtkButton" id="button5">
 
                <property name="label">gtk-cancel</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="use_stock">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">0</property>
 
              </packing>
 
            </child>
 
            <child>
 
              <object class="GtkButton" id="button4">
 
                <property name="label">gtk-add</property>
 
                <property name="use_action_appearance">False</property>
 
                <property name="visible">True</property>
 
                <property name="can_focus">True</property>
 
                <property name="can_default">True</property>
 
                <property name="has_default">True</property>
 
                <property name="receives_default">True</property>
 
                <property name="use_stock">True</property>
 
              </object>
 
              <packing>
 
                <property name="expand">False</property>
 
                <property name="fill">False</property>
 
                <property name="position">1</property>
 
              </packing>
 
            </child>
 
          </object>
 
          <packing>
 
            <property name="expand">False</property>
 
            <property name="fill">True</property>
 
            <property name="pack_type">end</property>
 
            <property name="position">0</property>
 
          </packing>
 
        </child>
 
        <child>
 
          <object class="GtkLabel" id="label12">
 
            <property name="visible">True</property>
 
            <property name="can_focus">False</property>
 
            <property name="label" translatable="yes">Name for new curve</property>
 
          </object>
 
          <packing>
 
            <property name="expand">True</property>
 
            <property name="fill">True</property>
 
            <property name="position">1</property>
 
          </packing>
 
        </child>
 
        <child>
 
          <object class="GtkEntry" id="newCurveName">
 
            <property name="visible">True</property>
 
            <property name="can_focus">True</property>
 
            <property name="has_focus">True</property>
 
            <property name="is_focus">True</property>
 
            <property name="invisible_char">●</property>
 
            <property name="activates_default">True</property>
 
            <property name="primary_icon_activatable">False</property>
 
            <property name="secondary_icon_activatable">False</property>
 
          </object>
 
          <packing>
 
            <property name="expand">True</property>
 
            <property name="fill">True</property>
 
            <property name="position">2</property>
 
          </packing>
 
        </child>
 
      </object>
 
    </child>
 
    <action-widgets>
 
      <action-widget response="2">button5</action-widget>
 
      <action-widget response="1">button4</action-widget>
 
    </action-widgets>
 
  </object>
 
  <object class="GtkSizeGroup" id="sizegroup1"/>
 
  <object class="GtkSizeGroup" id="sizegroup2"/>
 
  <object class="GtkTextBuffer" id="textbuffer1">
 
    <property name="text" translatable="yes">song01(t)</property>
 
  </object>
 
  <object class="GtkVBox" id="vbox2">
 
    <property name="visible">True</property>
 
    <property name="can_focus">False</property>
 
    <child>
 
      <object class="GtkImage" id="image1">
 
        <property name="width_request">289</property>
 
        <property name="height_request">120</property>
 
        <property name="visible">True</property>
 
        <property name="can_focus">False</property>
 
        <property name="stock">gtk-missing-image</property>
 
      </object>
 
      <packing>
 
@@ -978,18 +1013,13 @@ Available in functions: nsin/ncos period
 
        <property name="visible">True</property>
 
        <property name="can_focus">False</property>
 
        <property name="yalign">0.4699999988079071</property>
 
        <property name="label" translatable="yes">vidref from Sat 15:30</property>
 
      </object>
 
      <packing>
 
        <property name="expand">True</property>
 
        <property name="fill">True</property>
 
        <property name="position">1</property>
 
      </packing>
 
    </child>
 
  </object>
 
  <object class="GtkSizeGroup" id="sizegroup1"/>
 
  <object class="GtkSizeGroup" id="sizegroup2"/>
 
  <object class="GtkTextBuffer" id="textbuffer1">
 
    <property name="text" translatable="yes">song01(t)</property>
 
  </object>
 
</interface>
light9/curvecalc/curveview.py
Show inline comments
 
from __future__ import division
 
import math, time, logging
 
import gtk, goocanvas
 
from gi.repository import Gtk
 
from gi.repository import GObject
 
from gi.repository import Gdk
 
from gi.repository import GooCanvas
 
import louie as dispatcher
 
from rdflib import Literal
 
from light9.curvecalc.zoomcontrol import RegionZoom
 
from light9.curvecalc import cursors
 
from light9.curvecalc.curve import introPad, postPad
 
from light9.dmxchanedit import gradient
 
from lib.goocanvas_compat import Points, polyline_new_line
 

	
 
log = logging.getLogger()
 
print "curveview.py toplevel"
 
def vlen(v):
 
    return math.sqrt(v[0]*v[0] + v[1]*v[1])
 

	
 
def angle_between(base, p0, p1):
 
    p0 = p0[0] - base[0], p0[1] - base[1]
 
    p1 = p1[0] - base[0], p1[1] - base[1]
 
    p0 = [x/vlen(p0) for x in p0]
 
    p1 = [x/vlen(p1) for x in p1]
 
    dot = p0[0]*p1[0]+p0[1]*p1[1]
 
@@ -80,41 +83,41 @@ class SelectManip(object):
 
    """
 
    def __init__(self, parent, getSelectedIndices, getWorldPoint, getScreenPoint,
 
                 getCanvasSize, setPoints, getWorldTime, getWorldValue, getDragRange):
 
        """parent goocanvas group"""
 
        self.getSelectedIndices = getSelectedIndices
 
        self.getWorldPoint = getWorldPoint
 
        self.getScreenPoint = getScreenPoint
 
        self.getCanvasSize = getCanvasSize
 
        self.setPoints = setPoints
 
        self.getWorldTime = getWorldTime
 
        self.getDragRange = getDragRange
 
        self.getWorldValue = getWorldValue
 
        self.grp = goocanvas.Group(parent=parent)
 
        self.grp = GooCanvas.CanvasGroup(parent=parent)
 
        
 
        self.title = goocanvas.Text(parent=self.grp, text="selectmanip",
 
        self.title = GooCanvas.CanvasText(parent=self.grp, text="selectmanip",
 
                                    x=10, y=10, fill_color='white', font="ubuntu 10")
 

	
 
        self.bbox = goocanvas.Rect(parent=self.grp,
 
        self.bbox = GooCanvas.CanvasRect(parent=self.grp,
 
                                   fill_color_rgba=0xffff0030,
 
                                   line_width=0)
 

	
 
        self.xTrans = goocanvas.Polyline(parent=self.grp, close_path=True,
 
        self.xTrans = polyline_new_line(parent=self.grp, close_path=True,
 
                                         fill_color_rgba=0xffffff88,
 
                                         )
 
        self.centerScale = goocanvas.Polyline(parent=self.grp, close_path=True,
 
        self.centerScale = polyline_new_line(parent=self.grp, close_path=True,
 
                                              fill_color_rgba=0xffffff88,
 
                                         )
 

	
 
        thickLine = lambda: goocanvas.Polyline(parent=self.grp,
 
        thickLine = lambda: polyline_new_line(parent=self.grp,
 
                                               stroke_color_rgba=0xffffccff,
 
                                               line_width=6)
 
        self.leftScale = thickLine()
 
        self.rightScale = thickLine()
 
        self.topScale = thickLine()
 
        
 
        for grp, name in [(self.xTrans, 'x'),
 
                          (self.leftScale, 'left'),
 
                          (self.rightScale, 'right'),
 
                          (self.topScale, 'top'),
 
                          (self.centerScale, 'centerScale'),
 
                          ]:
 
@@ -216,51 +219,51 @@ class SelectManip(object):
 
        change, call this to redo the layout of the manip"""
 
        idxs = self.getSelectedIndices()
 
        pts = [self.getScreenPoint(i) for i in idxs]
 
        
 
        b = self.bbox.props
 
        b.x = min(p[0] for p in pts) - 5
 
        b.y = min(p[1] for p in pts) - 5
 
        margin = 10 if len(pts) > 1 else 0
 
        b.width = max(p[0] for p in pts) - b.x + margin
 
        b.height = min(max(p[1] for p in pts) - b.y + margin,
 
                       self.getCanvasSize().height - b.y - 1)
 

	
 
        multi = (goocanvas.ITEM_VISIBLE if len(pts) > 1 else
 
                 goocanvas.ITEM_INVISIBLE)
 
        multi = (GooCanvas.CanvasItemVisibility.VISIBLE if len(pts) > 1 else
 
                 GooCanvas.CanvasItemVisibility.INVISIBLE)
 
        b.visibility = multi
 
        self.leftScale.props.visibility = multi
 
        self.rightScale.props.visibility = multi
 
        self.topScale.props.visibility = multi
 
        self.centerScale.props.visibility = multi
 

	
 
        self.title.props.text = "%s %s selected" % (
 
            len(idxs), "point" if len(idxs) == 1 else "points")
 

	
 
        centerX = b.x + b.width / 2
 

	
 
        midY = self.getCanvasSize().height * .5
 
        loY = self.getCanvasSize().height * .8
 

	
 
        self.leftScale.props.points = goocanvas.Points([
 
        self.leftScale.props.points = Points([
 
            (b.x, b.y), (b.x, b.y + b.height)])
 
        self.rightScale.props.points = goocanvas.Points([
 
        self.rightScale.props.points = Points([
 
            (b.x + b.width, b.y), (b.x + b.width, b.y + b.height)])
 

	
 
        self.topScale.props.points = goocanvas.Points([
 
        self.topScale.props.points = Points([
 
            (b.x, b.y), (b.x + b.width, b.y)])
 

	
 
        self.updateXTrans(centerX, midY)
 

	
 
        self.centerScale.props.points = goocanvas.Points([
 
        self.centerScale.props.points = Points([
 
            (centerX - 5, loY - 5),
 
            (centerX + 5, loY - 5),
 
            (centerX + 5, loY + 5),
 
            (centerX - 5, loY + 5)])
 
            
 

	
 
    def updateXTrans(self, centerX, midY):       
 
        x1 = centerX - 30
 
        x2 = centerX - 20
 
        x3 = centerX + 20
 
        x4 = centerX + 30
 
        y1 = midY - 10
 
@@ -273,25 +276,25 @@ class SelectManip(object):
 
            (x2, y2),
 
            
 
            (x3, y2),
 
            (x3, y1),
 
            (x4, midY), # right tip
 
            (x3, y4),
 
            (x3, y3),
 
            
 
            (x2, y3),
 
            (x2, y4)
 
            ]
 

	
 
        self.xTrans.props.points = goocanvas.Points(shape)
 
        self.xTrans.props.points = Points(shape)
 

	
 
    def destroy(self):
 
        self.grp.remove()
 

	
 
class Curveview(object):
 
    """
 
    graphical curve widget only. Please pack .widget
 
    """
 
    def __init__(self, curve, markers, knobEnabled=False, isMusic=False,
 
                 zoomControl=None):
 
        """knobEnabled=True highlights the previous key and ties it to a
 
        hardware knob"""
 
@@ -346,109 +349,111 @@ class Curveview(object):
 
            return
 
        self.unselect()
 
        
 
    def rebuild(self):
 
        """
 
        sometimes after windows get resized, canvas gets stuck with a
 
        weird offset. I can't find where it is, so for now we support
 
        rebuilding the canvas widget
 
        """
 
        if hasattr(self, 'widget'):
 
            self.widget.destroy()
 
            self._time = -999
 
            print "rebuilding canvas"
 
            print "rebuilding canvas, destroyed old widget"
 

	
 
        self.timelineLine = self.curveGroup = self.selectManip = None
 
        self.widget = gtk.EventBox()
 
        self.widget = Gtk.EventBox()
 
        self.widget.set_can_focus(True)
 
        self.widget.add_events(gtk.gdk.KEY_PRESS_MASK |
 
                               gtk.gdk.FOCUS_CHANGE_MASK)
 
        self.widget.add_events(Gdk.EventMask.KEY_PRESS_MASK |
 
                               Gdk.EventMask.FOCUS_CHANGE_MASK)
 
        self.onFocusOut()
 

	
 
        box = gtk.VBox()
 
        box = Gtk.VBox()
 
        box.set_border_width(1)
 
        self.widget.add(box)
 
        box.show()
 
        
 
        self.canvas = goocanvas.Canvas()
 
        box.pack_start(self.canvas)
 
        self.canvas = GooCanvas.Canvas()
 
        box.pack_start(self.canvas, expand=True, fill=True, padding=0)
 
        self.canvas.show()
 

	
 
        p = self.canvas.props
 
        p.background_color = 'black'
 
        p.x2 = 2000
 

	
 
        self.size = self.canvas.get_allocation()
 
        self.root = self.canvas.get_root_item()
 

	
 
        self.canvas.connect("size-allocate", self.update_curve)
 
        self.canvas.connect("expose-event", self.onExpose)
 
        self.canvas.connect("draw", self.onExpose)
 

	
 
        self.canvas.connect("leave-notify-event", self.onLeave)
 
        self.canvas.connect("enter-notify-event", self.onEnter)
 
        self.canvas.connect("motion-notify-event", self.onMotion)
 
        self.canvas.connect("scroll-event", self.onScroll)
 
        self.canvas.connect("button-release-event", self.onRelease)
 
        self.root.connect("button-press-event", self.onCanvasPress)
 

	
 
        self.widget.connect("key-press-event", self.onKeyPress)
 

	
 
        self.widget.connect("focus-in-event", self.onFocusIn)
 
        self.widget.connect("focus-out-event", self.onFocusOut)
 
        #self.widget.connect("event", self.onAny)       
 
        self.widget.connect("event", self.onAny)
 

	
 
    def onAny(self, w, event):
 
        print "   %s on %s" % (event, w)
 
        
 
    def onFocusIn(self, *args):
 
        dispatcher.send("all curves lose selection", butNot=self)
 

	
 
        self.widget.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("red"))
 
        self.widget.modify_bg(Gtk.StateFlags.NORMAL, Gdk.color_parse("red"))
 

	
 
    def onFocusOut(self, widget=None, event=None):
 
        self.widget.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("gray30"))
 
        self.widget.modify_bg(Gtk.StateFlags.NORMAL, Gdk.color_parse("gray30"))
 

	
 
        # you'd think i'm unselecting when we lose focus, but we also
 
        # lose focus when the user moves off the toplevel window, and
 
        # that's not a time to forget the selection. See the 'all
 
        # curves lose selection' signal for the fix.
 

	
 
    def onKeyPress(self, widget, event):
 
        if event.string in list('12345'):
 
            x = int(event.string)
 
            self.add_point((self.current_time(), (x - 1) / 4.0))
 
        if event.string in list('qwerty'):
 
            self.add_marker((self.current_time(), event.string))
 

	
 
    def onExpose(self, *args):
 
        print "onExpose for %s, culled=%s" % (self, self.culled)
 
        if self.culled:
 
            self.update_curve()
 

	
 
    def onDelete(self):
 
        if self.selected_points:
 
            self.remove_point_idx(*self.selected_points)
 
        
 
            
 
    def onCanvasPress(self, item, target_item, event):
 
        # when we support multiple curves per canvas, this should find
 
        # the close one and add a point to that. Binding to the line
 
        # itself is probably too hard to hit. Maybe a background-color
 
        # really thick line would be a nice way to allow a sloppier
 
        # click
 

	
 
        self.widget.grab_focus()
 
        
 
        if event.get_state() & gtk.gdk.CONTROL_MASK:
 

	
 
        _, flags = event.get_state()
 
        if flags & Gdk.ModifierType.CONTROL_MASK:
 
            self.new_point_at_mouse(event)
 
        elif event.get_state() & gtk.gdk.SHIFT_MASK:
 
        elif flags & Gdk.ModifierType.SHIFT_MASK:
 
            self.sketch_press(event)
 
        else:
 
            self.select_press(event)
 

	
 
        # this stops some other handler that wants to unfocus 
 
        return True
 

	
 
    def playPause(self):
 
        """
 
        user has pressed ctrl-p over a curve view, possibly this
 
        one. Returns the time under the mouse if we know it, or else
 
        None
 
@@ -621,94 +626,102 @@ class Curveview(object):
 
        z, ht, marginBottom, marginTop = self._coords()
 
        return (x / self.size.width * (z.end - z.start) + z.start,
 
                ((ht - marginBottom) - y) / (ht - (marginBottom + marginTop)))
 

	
 
    def input_time(self, val, forceUpdate=False):
 
        if self._time == val:
 
            return
 
        self.update_time_bar(val)
 
        
 
    def update_time_bar(self, t):
 

	
 
        if not getattr(self, 'timelineLine', None):
 
            self.timelineGroup = goocanvas.Group(parent=self.root)
 
            self.timelineLine = goocanvas.Polyline(
 
            self.timelineGroup = GooCanvas.CanvasGroup(parent=self.root)
 
            self.timelineLine = polyline_new_line(
 
                parent=self.timelineGroup,
 
                points=goocanvas.Points([(0,0), (0,0)]),
 
                points=Points([(0,0), (0,0)]),
 
                line_width=2, stroke_color='red')
 

	
 
        try:
 
            pts = [self.screen_from_world((t, 0)),
 
                   self.screen_from_world((t, 1))]
 
        except ZeroDivisionError:
 
            pts = [(-1, -1), (-1, -1)]
 
        self.timelineLine.set_property('points', goocanvas.Points(pts))
 
        self.timelineLine.set_property('points', Points(pts))
 
        
 
        self._time = t
 
        if self.knobEnabled:
 
            self.delete('knob')
 
            prevKey = self.curve.point_before(t)
 
            if prevKey is not None:
 
                pos = self.screen_from_world(prevKey)
 
                self.create_oval(pos[0] - 8, pos[1] - 8,
 
                                 pos[0] + 8, pos[1] + 8,
 
                                 outline='#800000',
 
                                 tags=('knob',))
 
                dispatcher.send("knob out", value=prevKey[1], curve=self.curve)
 

	
 
    def canvasIsVisible(self):
 
        print "test canvasIsVisible"
 
        if not hasattr(self, "scrollWin"):
 
            self.scrollWin = self.canvas
 
            while not isinstance(self.scrollWin, gtk.ScrolledWindow):
 
            while not isinstance(self.scrollWin, Gtk.ScrolledWindow):
 
                self.scrollWin = self.scrollWin.get_parent()
 

	
 
        sw = self.scrollWin
 
        top = sw.get_toplevel()
 
        visy1 = sw.translate_coordinates(top, 0, 0)[1]
 
        visy2 = visy1 + sw.get_allocation().height
 

	
 
        coords = self.canvas.translate_coordinates(top, 0, 0)
 
        if not coords: # probably broken after a reload()
 
            print "  canvas coords failed"
 
            return False
 
        cany1 = coords[1]
 
        cany2 = cany1 + self.canvas.get_allocation().height
 
        return not (cany2 < visy1 or cany1 > visy2)
 
        ret = not (cany2 < visy1 or cany1 > visy2)
 
        print "  return %s" % ret
 
        return ret
 
        
 
    def update_curve(self, *args):
 
        if not self.redrawsEnabled:
 
            print "update_curve skipping1"
 
            return
 

	
 
        if not self.canvasIsVisible():
 
            self.culled = True
 
            print "update_curve skipping2"
 
            return
 
        self.culled = False
 
        
 
        self.size = self.canvas.get_allocation()
 
 
 
        visible_x = (self.world_from_screen(0,0)[0],
 
                     self.world_from_screen(self.size.width, 0)[0])
 

	
 
        visible_idxs = self.curve.indices_between(visible_x[0], visible_x[1],
 
                                                  beyond=1)
 
        visible_points = [self.curve.points[i] for i in visible_idxs]
 

	
 
        if getattr(self, 'curveGroup', None):
 
            print "rm old curveGroup"
 
            self.curveGroup.remove()
 
        self.curveGroup = goocanvas.Group(parent=self.root)
 
        self.curveGroup = GooCanvas.CanvasGroup(parent=self.root)
 

	
 
        # this makes gtk quietly stop working. Getting called too early?
 
        #self.canvas.set_property("background-color",
 
        #                         "gray20" if self.curve.muted else "black")
 

	
 
        self.update_time_bar(self._time)
 
        print "drawing! height=%s" % self.size.height
 
        if self.size.height < 40:
 
            self._draw_line(visible_points, area=True)
 
        else:
 
            self._draw_time_tics(visible_x)
 
            self._draw_line(visible_points)
 
            self._draw_markers(
 
                self.markers.points[i] for i in
 
                self.markers.indices_between(visible_x[0], visible_x[1]))
 

	
 
            self.dots = {} # idx : canvas rectangle
 

	
 
            if len(visible_points) < 50 and not self.curve.muted:
 
@@ -723,28 +736,28 @@ class Curveview(object):
 

	
 
    def _draw_markers(self, pts):
 
        colorMap = {
 
            'q':'#598522',
 
            'w':'#662285',
 
            'e':'#852922',
 
            'r':'#85225C',
 
            't':'#856B22',
 
            'y':'#227085',
 
            }
 
        for t, name in pts:
 
            x = int(self.screen_from_world((t,0))[0]) + .5
 
            goocanvas.polyline_new_line(self.curveGroup,
 
                                        x, 0, x, self.size.height,
 
                                        line_width=.4 if name in 'rty' else .8,
 
                                        stroke_color=colorMap.get(name, 'gray'))
 
            polyline_new_line(self.curveGroup,
 
                              x, 0, x, self.size.height,
 
                              line_width=.4 if name in 'rty' else .8,
 
                              stroke_color=colorMap.get(name, 'gray'))
 

	
 
    def _draw_time_tics(self,visible_x):
 
        tic = self._draw_one_tic
 

	
 
        tic(0, "0")
 
        t1,t2=visible_x
 
        if t2-t1<30:
 
            for t in range(int(t1),int(t2)+1):
 
                tic(t,str(t))
 
        tic(introPad, str(introPad))
 

	
 
        endtimes = dispatcher.send("get max time")
 
@@ -754,32 +767,32 @@ class Curveview(object):
 
            tic(endtime - postPad, "post %.1f" % (endtime - postPad))
 
        
 
    def _draw_one_tic(self,t,label):
 
        try:
 
            x = self.screen_from_world((t,0))[0]
 
            if not 0 <= x < self.size.width:
 
                return
 
            x = max(5, x) # cheat left-edge stuff onscreen
 
        except ZeroDivisionError:
 
            x = -100
 
            
 
        ht = self.size.height
 
        goocanvas.polyline_new_line(self.curveGroup,
 
        polyline_new_line(self.curveGroup,
 
                                    x, ht,
 
                                    x, ht - 20,
 
                                    line_width=.5,
 
                                    stroke_color='gray70')
 
        goocanvas.Text(parent=self.curveGroup,
 
        GooCanvas.CanvasText(parent=self.curveGroup,
 
                       fill_color="white",
 
                       anchor=gtk.ANCHOR_SOUTH,
 
                       anchor=GooCanvas.CanvasAnchorType.SOUTH,
 
                       font="ubuntu 7",
 
                       x=x+3, y=ht-20,
 
                       text=label)
 

	
 
    def _draw_line(self, visible_points, area=False):
 
        linepts=[]
 
        step=1
 
        linewidth = 1.5
 
        maxPointsToDraw = self.size.width / 2
 
        if len(visible_points) > maxPointsToDraw:
 
            step = int(len(visible_points) / maxPointsToDraw)
 
            linewidth = .8
 
@@ -792,62 +805,62 @@ class Curveview(object):
 

	
 
        if self.curve.muted:
 
            fill = 'grey34'
 
        else:
 
            fill = 'white'
 

	
 
        if area:
 
            try:
 
                base = self.screen_from_world((0, 0))[1]
 
            except ZeroDivisionError:
 
                base = -100
 
            base = base + linewidth / 2
 
            goocanvas.Polyline(parent=self.curveGroup,
 
                               points=goocanvas.Points(
 
            polyline_new_line(parent=self.curveGroup,
 
                               points=Points(
 
                                   [(linepts[0][0], base)] +
 
                                   linepts +
 
                                   [(linepts[-1][0], base)]),
 
                               close_path=True,
 
                               line_width=0,
 
                               fill_color="green",
 
                               )
 

	
 
        self.pl = goocanvas.Polyline(parent=self.curveGroup,
 
                                     points=goocanvas.Points(linepts),
 
        self.pl = polyline_new_line(parent=self.curveGroup,
 
                                     points=Points(linepts),
 
                                     line_width=linewidth,
 
                                     stroke_color=fill,
 
                                     )
 
                
 
            
 
    def _draw_handle_points(self,visible_idxs,visible_points):
 
        for i,p in zip(visible_idxs,visible_points):
 
            rad=3
 
            worldp = p
 
            try:
 
                p = self.screen_from_world(p)
 
            except ZeroDivisionError:
 
                p = (-100, -100)
 
            dot = goocanvas.Rect(parent=self.curveGroup,
 
            dot = GooCanvas.CanvasRect(parent=self.curveGroup,
 
                                 x=int(p[0] - rad) + .5,
 
                                 y=int(p[1] - rad) + .5,
 
                                 width=rad * 2, height=rad * 2,
 
                                 stroke_color='gray90',
 
                                 fill_color='blue',
 
                                 line_width=1,
 
                                 #tags=('curve','point', 'handle%d' % i)
 
                                 )
 

	
 
            if worldp[1] == 0:
 
                rad += 3
 
                goocanvas.Ellipse(parent=self.curveGroup,
 
                GooCanvas.CanvasEllipse(parent=self.curveGroup,
 
                                  center_x=p[0],
 
                                  center_y=p[1],
 
                                  radius_x=rad,
 
                                  radius_y=rad,
 
                                  line_width=2,
 
                                  stroke_color='#00a000',
 
                                  #tags=('curve','point', 'handle%d' % i)
 
                                  )
 
            dot.connect("button-press-event", self.dotpress, i)
 
            #self.tag_bind('handle%d' % i,"<ButtonPress-1>",
 
            #              lambda ev,i=i: self.dotpress(ev,i))
 
            #self.tag_bind('handle%d' % i, "<Key-d>",
 
@@ -931,25 +944,25 @@ class Curveview(object):
 
            start, end = end, start
 
        self.select_indices(self.curve.indices_between(start,end))
 

	
 
    def onEnter(self, widget, event):
 
        self.entered = True
 

	
 
    def onLeave(self, widget, event):
 
        self.entered = False
 

	
 
    def onMotion(self, widget, event):
 
        self.lastMouseX = event.x
 

	
 
        if event.state & gtk.gdk.SHIFT_MASK and 1: # and B1
 
        if event.state & Gdk.ModifierType.SHIFT_MASK and 1: # and B1
 
            self.sketch_motion(event)
 
            return
 

	
 
        self.select_motion(event)
 
        
 
        if not self.dragging_dots:
 
            return
 
        if not event.state & 256:
 
            return # not lmb-down
 

	
 
        # this way is accumulating error and also making it harder to
 
        # undo (e.g. if the user moves far out of the window or
 
@@ -985,60 +998,60 @@ class Curveview(object):
 
                continue
 
            moved = True
 
            updates.append((idx, tuple(newp)))
 
        self.curve.set_points(updates)
 
        return moved
 
            
 
    def unselect(self):
 
        self.select_indices([])
 

	
 
    def onScroll(self, widget, event):
 
        t = self.world_from_screen(event.x, 0)[0]
 
        self.zoomControl.zoom_about_mouse(
 
            t, factor=1.5 if event.direction == gtk.gdk.SCROLL_DOWN else 1/1.5)
 
            t, factor=1.5 if event.direction == Gdk.ScrollDirection.DOWN else 1/1.5)
 
        
 
    def onRelease(self, widget, event):
 
        self.print_state("dotrelease")
 

	
 
        if event.state & gtk.gdk.SHIFT_MASK: # relese-B1
 
        if event.state & Gdk.ModifierType.SHIFT_MASK: # relese-B1
 
            self.sketch_release(event)
 
            return
 

	
 
        self.select_release(event)
 
 
 
        if not self.dragging_dots:
 
            return
 
        self.last_mouse_world = None
 
        self.dragging_dots = False
 

	
 
class CurveRow(object):
 
    """
 
    one of the repeating curve rows (including widgets on the left)
 

	
 
    i wish these were in a list-style TreeView so i could set_reorderable on it
 

	
 
    please pack self.box
 
    """
 
    def __init__(self, name, curve, markers, slider, knobEnabled, zoomControl):
 
        self.name = name
 
        self.box = gtk.VBox()
 
        self.box = Gtk.VBox()
 
        self.box.set_border_width(1)
 

	
 
        self.cols = gtk.HBox()
 
        self.cols = Gtk.HBox()
 
        self.box.add(self.cols)
 
        
 
        controls = gtk.Frame()
 
        controls = Gtk.Frame()
 
        controls.set_size_request(115, -1)
 
        controls.set_shadow_type(gtk.SHADOW_OUT)
 
        self.cols.pack_start(controls, expand=False)
 
        controls.set_shadow_type(Gtk.ShadowType.OUT)
 
        self.cols.pack_start(controls, expand=False, fill=True, padding=0)
 
        self.setupControls(controls, name, curve, slider)
 

	
 
        self.curveView = Curveview(curve, markers, knobEnabled=knobEnabled,
 
                                   isMusic=name in ['music', 'smooth_music'],
 
                                   zoomControl=zoomControl)
 
        
 
        self.initCurveView()
 
        dispatcher.connect(self.rebuild, "all curves rebuild")
 

	
 
        # incomplete: this makes the row start with a small size
 
        # request, but doesn't update the row widgets
 
        self.collapsed.props.active = True
 
@@ -1047,54 +1060,54 @@ class CurveRow(object):
 
        self.curveView.rebuild()
 
        self.initCurveView()
 
        self.update_ui_to_collapsed_state()
 

	
 
    def destroy(self):
 
        self.curveView.entered = False  # help suppress bad position events
 
        del self.curveView
 
        self.box.destroy()
 
        
 
    def initCurveView(self):
 
        self.curveView.widget.show()
 
        self.curveView.widget.set_size_request(-1, 100)
 
        self.cols.pack_start(self.curveView.widget, expand=True)       
 
        self.cols.pack_start(self.curveView.widget, expand=True, fill=True, padding=0)       
 
        
 
    def setupControls(self, controls, name, curve, slider):
 
        box = gtk.VBox()
 
        box = Gtk.VBox()
 
        controls.add(box)
 
        
 
        txt = "curve '%s'" % name
 
        if len(name) > 7:
 
            txt = name
 
        curve_name_label = gtk.Label(txt)
 
        box.pack_start(curve_name_label)
 
        curve_name_label = Gtk.Label(txt)
 
        box.pack_start(curve_name_label, expand=True, fill=True, padding=0)
 

	
 
        bools = gtk.HBox()
 
        box.pack_start(bools)
 
        self.collapsed = gtk.CheckButton("C")
 
        bools.pack_start(self.collapsed)
 
        bools = Gtk.HBox()
 
        box.pack_start(bools, expand=True, fill=True, padding=0)
 
        self.collapsed = Gtk.CheckButton("C")
 
        bools.pack_start(self.collapsed, expand=True, fill=True, padding=0)
 
        self.collapsed.connect("toggled", self.update_ui_to_collapsed_state)
 
        self.hideWhenCollapsed = [bools]
 
        self.muted = gtk.CheckButton("M")
 
        self.muted = Gtk.CheckButton("M")
 
        
 
        bools.pack_start(self.muted)
 
        bools.pack_start(self.muted, expand=True, fill=True, padding=0)
 
        self.muted.connect("toggled", self.sync_mute_to_curve)
 
        dispatcher.connect(self.mute_changed, 'mute changed', sender=curve)
 

	
 
        self.sliderLabel = None
 
        if slider is not None:
 
            # slider should have a checkbutton, defaults to off for
 
            # music tracks
 
            self.sliderLabel = gtk.Label("Slider %s" % slider)
 
            box.pack_start(self.sliderLabel)
 
            self.sliderLabel = Gtk.Label("Slider %s" % slider)
 
            box.pack_start(self.sliderLabel, expand=True, fill=True, padding=0)
 

	
 
        # widgets that need recoloring when we tint the row:
 
        #self.widgets = [leftside, self.collapsed, self.muted,
 
        #                curve_name_label, self]
 
        #if self.sliderLabel:
 
        #    self.widgets.append(self.sliderLabel)
 

	
 
    def onDelete(self):
 
        self.curveView.onDelete()
 
        
 
    def update_ui_to_collapsed_state(self, *args):
 
        if self.collapsed.get_active():
 
@@ -1133,34 +1146,33 @@ class Curvesetview(object):
 
    """
 
    def __init__(self, curvesVBox, zoomControlBox, curveset):
 
        self.live = True
 
        self.curvesVBox = curvesVBox
 
        self.curveset = curveset
 
        self.allCurveRows = set()
 

	
 
        import light9.curvecalc.zoomcontrol
 
        reload(light9.curvecalc.zoomcontrol)
 
        self.zoomControl = light9.curvecalc.zoomcontrol.ZoomControl()
 
        zoomControlBox.add(self.zoomControl.widget)
 
        self.zoomControl.widget.show_all()
 

	
 
        for c in curveset.curveNamesInOrder():
 
            self.add_curve(c) 
 

	
 
        dispatcher.connect(self.clear_curves, "clear_curves")
 
        dispatcher.connect(self.add_curve, "add_curve", sender=self.curveset)
 
        dispatcher.connect(self.set_featured_curves, "set_featured_curves")
 
        dispatcher.connect(self.song_has_changed, "song_has_changed")
 
        
 
        self.newcurvename = gtk.EntryBuffer("", 0)
 
        self.newcurvename = Gtk.EntryBuffer.new("", 0)
 

	
 
        eventBox = self.curvesVBox.get_parent()
 
        eventBox.connect("key-press-event", self.onKeyPress)
 
        eventBox.connect("button-press-event", self.takeFocus)
 

	
 
    def __del__(self):
 
        print "del curvesetview", id(self) 
 

	
 
    def clear_curves(self):
 
        """curveset is about to re-add all new curves"""
 
        while self.allCurveRows:
 
            self.allCurveRows.pop().destroy()
 
@@ -1175,25 +1187,25 @@ class Curvesetview(object):
 
        self.curvesVBox.get_parent().grab_focus()
 

	
 
    def curveRow_from_name(self, name):
 
        for cr in self.allCurveRows:
 
            if cr.name == name:
 
                return cr
 
        raise ValueError("couldn't find curveRow named %r" % name)
 

	
 
    def set_featured_curves(self, curveNames):
 
        """bring these curves to the top of the stack"""
 
        for n in curveNames[::-1]:
 
            self.curvesVBox.reorder_child(self.curveRow_from_name(n).box,
 
                                          gtk.PACK_START)
 
                                          Gtk.PACK_START)
 
        
 
    def onKeyPress(self, widget, event):
 
        if not self.live: # workaround for old instances living past reload()
 
            return
 

	
 
        if event.string == 'c':
 
            r = self.row_under_mouse()
 
            # calling toggled() had no effect; don't know why
 
            r.collapsed.set_active(not r.collapsed.get_active())
 
 
 
    def row_under_mouse(self):
 
        x, y = self.curvesVBox.get_pointer()
 
@@ -1208,25 +1220,25 @@ class Curvesetview(object):
 
        self.entry.focus()
 

	
 
    def new_curve(self, event):
 
        self.curveset.new_curve(self.newcurvename.get())
 
        self.newcurvename.set('')
 
        
 
    def add_curve(self, name, slider=None, knobEnabled=False):
 
        if isinstance(name, Literal):
 
            name = str(name)
 
        curve = self.curveset.curves[name]
 
        f = CurveRow(name, curve, self.curveset.markers,
 
                     slider, knobEnabled, self.zoomControl)
 
        self.curvesVBox.pack_start(f.box)
 
        self.curvesVBox.pack_start(f.box, expand=True, fill=True, padding=0)
 
        f.box.show_all()
 
        self.allCurveRows.add(f)
 
        f.curveView.goLive()
 

	
 
    def row(self, name):
 
        if isinstance(name, Literal):
 
            name = str(name)
 
        matches = [r for r in self.allCurveRows if r.name == name]
 
        if not matches:
 
            raise ValueError("no curveRow named %r. only %s" %
 
                             (name, [r.name for r in self.allCurveRows]))
 
        return matches[0]
light9/curvecalc/subtermview.py
Show inline comments
 
import gtk, logging
 
import logging
 
from gi.repository import Gtk
 
from louie import dispatcher
 
from rdflib import Literal, URIRef
 
from light9.namespaces import L9
 
log = logging.getLogger()
 

	
 
# inspired by http://www.daa.com.au/pipermail/pygtk/2008-August/015772.html
 
# keeping a ref to the __dict__ of the object stops it from getting zeroed
 
keep = []
 

	
 
class Subexprview(object):
 
    def __init__(self, graph, ownerSubterm, saveContext, curveset):
 
        self.graph, self.ownerSubterm = graph, ownerSubterm
 
        self.saveContext = saveContext
 
        self.curveset = curveset
 

	
 
        self.box = gtk.HBox()
 
        self.box = Gtk.HBox()
 

	
 
        self.entryBuffer = gtk.EntryBuffer("", -1)
 
        self.entry = gtk.Entry()
 
        self.error = gtk.Label("")
 
        self.entryBuffer = Gtk.EntryBuffer("", -1)
 
        self.entry = Gtk.Entry()
 
        self.error = Gtk.Label("")
 

	
 
        self.box.pack_start(self.entry, expand=True)
 
        self.box.pack_start(self.error, expand=False)
 

	
 
        self.entry.set_buffer(self.entryBuffer)
 
        self.graph.addHandler(self.set_expression_from_graph)
 
        self.entryBuffer.connect("deleted-text", self.entry_changed)
 
        self.entryBuffer.connect("inserted-text", self.entry_changed)
 

	
 
        self.entry.connect("focus-in-event", self.onFocus)
 
        
 
        dispatcher.connect(self.exprError, "expr_error", sender=self.ownerSubterm)
 
@@ -58,30 +59,30 @@ class Subexprview(object):
 
                               self.ownerSubterm,
 
                               L9['expression'],
 
                               Literal(self.entryBuffer.get_text()))
 
            
 
class Subtermview(object):
 
    """
 
    has .label and .exprView widgets for you to put in a table
 
    """
 
    def __init__(self, st, curveset):
 
        self.subterm = st
 
        self.graph = st.graph
 

	
 
        self.label = gtk.Label("sub")
 
        self.label = Gtk.Label("sub")
 
        self.graph.addHandler(self.setName)
 

	
 
        self.label.drag_dest_set(flags=gtk.DEST_DEFAULT_ALL,
 
        self.label.drag_dest_set(flags=Gtk.DEST_DEFAULT_ALL,
 
                            targets=[('text/uri-list', 0, 0)],
 
                            actions=gtk.gdk.ACTION_COPY)
 
                            actions=Gtk.gdk.ACTION_COPY)
 
        self.label.connect("drag-data-received", self.onDataReceivedOnLabel)
 
        
 
        sev = Subexprview(self.graph, self.subterm.uri, self.subterm.saveContext, curveset)
 
        self.exprView = sev.box
 

	
 
    def onDataReceivedOnLabel(self, widget, context, x, y, selection,
 
                       targetType, time):
 
        self.graph.patchObject(self.subterm.saveContext,
 
                               self.subterm.uri,
 
                               L9['sub'],
 
                               URIRef(selection.data.strip()))
 

	
light9/curvecalc/zoomcontrol.py
Show inline comments
 
from __future__ import division
 
import gtk, goocanvas
 
from gi.repository import Gtk
 
from gi.repository import GObject
 
from gi.repository import GooCanvas
 
import louie as dispatcher
 
from light9.curvecalc import cursors 
 
from lib.goocanvas_compat import Points, polyline_new_line
 

	
 
class ZoomControl(object):
 
    """
 
    please pack .widget
 
    """
 

	
 
    mintime = 0
 

	
 
    def maxtime():
 
        doc = "seconds at the right edge of the bar"
 
        def fget(self): return self._maxtime
 
        def fset(self, value):
 
@@ -43,49 +46,50 @@ class ZoomControl(object):
 
        def fget(self):
 
            # work off the midpoint so that "crushing works equally
 
            # well in both directions
 
            return (self.start + self.end) / 2
 
        def fset(self, value):
 
            d = self.end-self.start
 
            self.start = value - d / 2
 
            self.end = value + d / 2
 
        return locals()
 
    offset = property(**offset())
 

	
 
    def __init__(self, **kw):
 
        self.widget = goocanvas.Canvas(bounds_padding=5)
 
        self.widget = GooCanvas.Canvas(bounds_padding=5)
 
        self.widget.set_property("background-color", "gray60")
 
        self.widget.set_size_request(-1, 30)
 
        self.widget.props.x2 = 2000
 

	
 
        endtimes = dispatcher.send("get max time")
 
        if endtimes:
 
            self.maxtime = endtimes[0][1]
 
        else:
 
            self.maxtime = 0
 

	
 
        self.start = 0
 
        self.end = 250
 

	
 
        self.root = self.widget.get_root_item()
 
        self.leftbrack = goocanvas.Polyline(parent=self.root,
 
        self.leftbrack = polyline_new_line(parent=self.root,
 
                                            line_width=5, stroke_color='black')
 
        self.rightbrack = goocanvas.Polyline(parent=self.root,
 
        self.rightbrack = polyline_new_line(parent=self.root,
 
                                             line_width=5, stroke_color='black')
 
        self.shade = goocanvas.Rect(parent=self.root,
 
        self.shade = GooCanvas.CanvasRect(parent=self.root,
 
                                    fill_color='gray70',
 
                                    line_width=.5)
 
        self.time = goocanvas.Polyline(parent=self.root,
 
        self.time = polyline_new_line(parent=self.root,
 
                                       line_width=2,
 
                                       stroke_color='red')
 

	
 
        self.redrawzoom()
 
        self.widget.connect("size-allocate", self.redrawzoom)
 

	
 
        self.widget.connect("motion-notify-event", self.adjust)
 
        self.widget.connect("button-release-event", self.release)
 
        self.leftbrack.connect("button-press-event",
 
                               lambda i, t, ev: self.press(ev, 'start'))
 
        self.rightbrack.connect("button-press-event",
 
                                lambda i, t, ev: self.press(ev, 'end'))
 
        self.shade.connect("button-press-event",
 
                           lambda i, t, ev: self.press(ev, 'offset'))
 
        
 
@@ -137,26 +141,25 @@ class ZoomControl(object):
 
        self.end = self.maxtime
 

	
 
        self.redrawzoom()
 
            
 
    def input_time(self, val):
 
        """move time cursor to this time"""
 
        self.lastTime = val
 
        try:
 
            x = self.can_for_t(self.lastTime)
 
        except ZeroDivisionError:
 
            x = -100
 
        self.time.set_property("points",
 
                               goocanvas.Points([(x, 0),
 
                                                 (x, self.size.height)]))
 
                               Points([(x, 0), (x, self.size.height)]))
 
        
 
    def press(self,ev,attr):
 
        self.adjustingattr = attr
 
        
 
    def release(self, widget, ev):
 
        if hasattr(self,'adjustingattr'):
 
            del self.adjustingattr
 
        if hasattr(self,'lastx'):
 
            del self.lastx
 
        
 
    def adjust(self, widget, ev):
 

	
 
@@ -168,78 +171,78 @@ class ZoomControl(object):
 
            self.lastx = ev.x
 
        new = self.can_for_t(getattr(self,attr)) + (ev.x - self.lastx)
 
        self.lastx = ev.x
 
        setattr(self,attr,self.t_for_can(new))
 
        self.redrawzoom()
 

	
 
    def can_for_t(self,t):
 
        a, b = self.mintime, self.maxtime
 
        return (t - a) / (b - a) * (self.size.width - 30) + 20
 
    def t_for_can(self,x):
 
        a, b = self.mintime, self.maxtime
 
        return (x - 20) / (self.size.width - 30) * (b - a) + a
 

	
 
        
 
    def redrawzoom(self,*args):
 
        """redraw pieces based on start/end"""
 
        self.size = self.widget.get_allocation()
 
        dispatcher.send("zoom changed")
 
        if not hasattr(self,'created'):
 
            return
 
        y1, y2 = 3, self.size.height - 3
 
        lip = 6
 
        try:
 
            scan = self.can_for_t(self.start)
 
            ecan = self.can_for_t(self.end)
 
        except ZeroDivisionError:
 
            # todo: set the zoom to some clear null state
 
            return
 

	
 
        self.leftbrack.set_property("points", goocanvas.Points([
 
        self.leftbrack.set_property("points", Points([
 
            (scan + lip, y1),
 
            (scan, y1),
 
            (scan, y2),
 
            (scan + lip, y2)]))
 
        self.rightbrack.set_property("points", goocanvas.Points([
 
        self.rightbrack.set_property("points", Points([
 
            (ecan - lip, y1),
 
            (ecan, y1),
 
            (ecan, y2),
 
            (ecan - lip, y2)]))
 
        self.shade.set_properties(
 
            x=scan + 5,
 
            y=y1 + lip,
 
            width=max(0, ecan - 5 - (scan + 5)),
 
            height=max(0, y2 - lip - (y1 + lip)))
 

	
 
        self.redrawTics()
 
        
 
    def redrawTics(self):
 
        if hasattr(self, 'ticsGroup'):
 
            self.ticsGroup.remove()
 
        self.ticsGroup = goocanvas.Group(parent=self.root)
 
        self.ticsGroup = GooCanvas.CanvasGroup(parent=self.root)
 

	
 
        lastx =- 1000
 

	
 
        for t in range(0,int(self.maxtime)):
 
            x = self.can_for_t(t)
 
            if 0 < x < self.size.width and x - lastx > 30:
 
                txt = str(t)
 
                if lastx == -1000:
 
                    txt = txt + "sec"
 
                goocanvas.Polyline(parent=self.ticsGroup,
 
                                   points=goocanvas.Points([(x, 0), (x, 15)]),
 
                GooCanvas.CanvasPolyline(parent=self.ticsGroup,
 
                                   points=Points([(x, 0), (x, 15)]),
 
                                   line_width=.8,
 
                                   stroke_color='black')
 
                goocanvas.Text(parent=self.ticsGroup,
 
                GooCanvas.CanvasText(parent=self.ticsGroup,
 
                               x=x, y=self.size.height-1,
 
                               anchor=gtk.ANCHOR_SOUTH,
 
                               anchor=GooCanvas.CanvasAnchorType.SOUTH,
 
                               text=txt,
 
                               font='ubuntu 7')
 
                lastx = x
 

	
 

	
 
class RegionZoom:
 
    """rigs c-a-b1 to drag out an area to zoom to. also catches other types of drag events, like b1 drag for selecting points
 

	
 
    this is used with Curveview
 
    """
 
    def __init__(self, canvas, world_from_screen, screen_from_world):
 
        self.canvas, self.world_from_screen = canvas, world_from_screen
light9/editchoicegtk.py
Show inline comments
 
import gtk
 
from gi.repository import Gtk
 
from gi.repository import Gdk
 
from rdflib import URIRef
 

	
 
class Local(object):
 
    """placeholder for the local uri that EditChoice does not
 
    manage. Set resourceObservable to Local to indicate that you're
 
    unlinked"""
 

	
 
class EditChoice(gtk.HBox):
 
class EditChoice(Gtk.HBox):
 
    """
 
    this is a gtk port of editchoice.EditChoice
 
    """
 
    def __init__(self, graph, resourceObservable, label="Editing:"):
 
        """
 
        getResource is called to get the URI of the currently
 
        """
 
        self.graph = graph
 

	
 
        # the outer box should have a distinctive border so it's more
 
        # obviously a special drop target
 
        gtk.HBox.__init__(self)
 
        self.pack_start(gtk.Label(label), expand=False)
 
        Gtk.HBox.__init__(self)
 
        self.pack_start(Gtk.Label(label),
 
                        False, True, 0) #expand, fill, pad
 

	
 
        # this is just a label, but it should look like a physical
 
        # 'thing' (and gtk labels don't work as drag sources)
 
        self.currentLink = gtk.Button("http://bar")
 
        self.currentLink = Gtk.Button("http://bar")
 

	
 
        self.pack_start(self.currentLink,
 
                        True, True, 0) #expand, fill, pad
 

	
 
        self.pack_start(self.currentLink)
 

	
 
        self.unlinkButton = gtk.Button(label="Unlink")
 
        self.pack_start(self.unlinkButton, expand=False)
 
        self.unlinkButton = Gtk.Button(label="Unlink")
 
        self.pack_start(self.unlinkButton,
 
                        False, True, 0) #expand, fill pad
 

	
 
        self.unlinkButton.connect("clicked", self.onUnlink)
 
        
 
        self.show_all()
 

	
 
        self.resourceObservable = resourceObservable
 
        resourceObservable.subscribe(self.uriChanged)
 

	
 
        self.makeDragSource()
 
        self.makeDropTarget()
 
         
 
    def makeDropTarget(self):
 
        def ddr(widget, drag_context, x, y, selection_data, info, timestamp):
 
            if selection_data.type != 'text/uri-list':
 
            if selection_data.get_data_type().name() != 'text/uri-list':
 
                raise ValueError("unknown DnD selection type %r" %
 
                                 selection_data.type)
 
            self.resourceObservable(URIRef(selection_data.data.strip()))
 
                                 selection_data.get_data_type())
 
            self.resourceObservable(URIRef(selection_data.get_data().strip()))
 
        
 
        self.currentLink.drag_dest_set(flags=gtk.DEST_DEFAULT_ALL,
 
                            targets=[('text/uri-list', 0, 0)],
 
                            actions=gtk.gdk.ACTION_LINK  | gtk.gdk.ACTION_COPY)
 
        self.currentLink.drag_dest_set(
 
            flags=Gtk.DestDefaults.ALL,
 
            targets=[Gtk.TargetEntry.new('text/uri-list', 0, 0)],
 
            actions=Gdk.DragAction.LINK  | Gdk.DragAction.COPY)
 
        self.currentLink.connect("drag_data_received", ddr)
 
                
 
    def makeDragSource(self):
 
        self.currentLink.drag_source_set(
 
            start_button_mask=gtk.gdk.BUTTON1_MASK,
 
            targets=[('text/uri-list', 0, 0)],
 
            actions=gtk.gdk.ACTION_LINK | gtk.gdk.ACTION_COPY)
 
            start_button_mask=Gdk.ModifierType.BUTTON1_MASK,
 
            targets=[Gtk.TargetEntry.new(target='text/uri-list',
 
                                         flags=0, info=0)],
 
            actions=Gdk.DragAction.LINK  | Gdk.DragAction.COPY)
 

	
 
        def source_drag_data_get(btn, context, selection_data, info, time):
 
            selection_data.set(selection_data.target, 8,
 
                               self.resourceObservable())
 
            selection_data.set_uris([self.resourceObservable()])
 

	
 
        self.currentLink.connect("drag_data_get", source_drag_data_get)
 

	
 
                
 
    def uriChanged(self, newUri):
 
        # if this resource had a type icon or a thumbnail, those would be
 
        # cool to show in here too
 
        if newUri is Local:
 
            self.currentLink.set_label("(local)")
 
            self.currentLink.drag_source_unset()
 
        else:
 
            self.graph.addHandler(self.updateLabel)
light9/gtkpyconsole.py
Show inline comments
 
from lib.ipython_view import IPythonView
 
import pango, gtk
 
import gi
 
from gi.repository import Gtk
 
from gi.repository import Pango
 

	
 
def togglePyConsole(self, item, user_ns):
 
    """
 
    toggles a toplevel window with an ipython console inside.
 

	
 
    self is an object we can stick the pythonWindow attribute on
 

	
 
    item is a checkedmenuitem
 

	
 
    user_ns is a dict you want to appear as locals in the console
 
    """
 
    if item.get_active():
 
        if not hasattr(self, 'pythonWindow'):
 
            self.pythonWindow = gtk.Window()
 
            S = gtk.ScrolledWindow()
 
            S.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
            self.pythonWindow = Gtk.Window()
 
            S = Gtk.ScrolledWindow()
 
            S.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
 
            V = IPythonView(user_ns=user_ns)
 
            V.modify_font(pango.FontDescription("luxi mono 8"))
 
            V.set_wrap_mode(gtk.WRAP_CHAR)
 
            V.modify_font(Pango.FontDescription("luxi mono 8"))
 
            V.set_wrap_mode(Gtk.WrapMode.CHAR)
 
            S.add(V)
 
            self.pythonWindow.add(S)
 
            self.pythonWindow.show_all()
 
            self.pythonWindow.set_size_request(750, 550)
 
            self.pythonWindow.set_resizable(True)
 
            def onDestroy(*args):
 
                item.set_active(False)
 
                del self.pythonWindow
 
            self.pythonWindow.connect("destroy", onDestroy)
 
    else:
 
        if hasattr(self, 'pythonWindow'):
 
            self.pythonWindow.destroy()
makefile
Show inline comments
 
@@ -40,16 +40,16 @@ create_virtualenv:
 
	ln -sf ../env/bin/python bin/python
 

	
 
tkdnd_build:
 
	# get tkdnd r95 with subversion
 
	# then apply tkdnd-patch-on-r95 to that
 
	cd tkdnd/trunk
 
	./configure
 
	make
 

	
 
bin/ascoltami2: gst_packages link_to_sys_packages
 

	
 
gst_packages:
 
	sudo aptitude install python-gi gir1.2-gst-plugins-base-1.0 libgirepository-1.0-1 gir1.2-gstreamer-1.0 gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-pulseaudio
 
	sudo aptitude install python-gi gir1.2-gst-plugins-base-1.0 libgirepository-1.0-1 gir1.2-gstreamer-1.0 gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-pulseaudio gir1.2-goocanvas-2.0-9
 

	
 
packages:
 
	sudo aptitude install coffeescript freemind normalize-audio audacity python-pygoocanvas
0 comments (0 inline, 0 general)