package provide pd_bindings 0.1 package require pd_menucommands package require dialog_find namespace eval ::pd_bindings:: { variable modifier namespace export window_bindings namespace export dialog_bindings namespace export canvas_bindings } # the commands are bound using "" quotations so that the $mytoplevel is # interpreted immediately. Since the command is being bound to $mytoplevel, # it makes sense to have value of $mytoplevel already in the command. This is # the opposite of the menu commands in pd_menus.tcl # binding by class is not recursive, so its useful for certain things proc ::pd_bindings::class_bindings {} { # and the Pd window is in a class to itself bind PdWindow "::pd_bindings::window_configure %W" bind PdWindow "::pd_bindings::window_focusin %W" # bind to all the canvas windows bind CanvasWindow "::pd_bindings::map %W" bind CanvasWindow "::pd_bindings::unmap %W" bind CanvasWindow "::pd_bindings::window_configure %W" bind CanvasWindow "::pd_bindings::window_focusin %W" # bindings for dialog windows, which behave differently than canvas windows bind DialogWindow "::pd_bindings::dialog_configure %W" bind DialogWindow "::pd_bindings::dialog_focusin %W" } proc ::pd_bindings::window_bindings {mytoplevel} { variable modifier # for key bindings if {$::windowingsystem eq "aqua"} { set modifier "Mod1" } else { set modifier "Control" } # File menu bind $mytoplevel <$modifier-Key-b> "menu_helpbrowser" bind $mytoplevel <$modifier-Key-f> "::dialog_find::menu_find_dialog $mytoplevel" bind $mytoplevel <$modifier-Key-n> "menu_new" bind $mytoplevel <$modifier-Key-o> "menu_open" bind $mytoplevel <$modifier-Key-p> "menu_print $mytoplevel" bind $mytoplevel <$modifier-Key-q> "pdsend \"pd verifyquit\"" bind $mytoplevel <$modifier-Key-r> "menu_raise_pdwindow" bind $mytoplevel <$modifier-Shift-Key-L> "menu_clear_console" bind $mytoplevel <$modifier-Shift-Key-Q> "pdsend \"pd quit\"" bind $mytoplevel <$modifier-Shift-Key-R> "menu_toggle_console" # DSP control bind $mytoplevel <$modifier-Key-slash> "pdsend \"pd dsp 1\"" bind $mytoplevel <$modifier-Key-period> "pdsend \"pd dsp 0\"" } proc ::pd_bindings::pdwindow_bindings {mytoplevel} { variable modifier window_bindings $mytoplevel # TODO update this to work with the console, if it is used bind $mytoplevel <$modifier-Key-a> ".pdwindow.text tag add sel 1.0 end" bind $mytoplevel <$modifier-Key-x> "tk_textCut .pdwindow.text" bind $mytoplevel <$modifier-Key-c> "tk_textCopy .pdwindow.text" bind $mytoplevel <$modifier-Key-v> "tk_textPaste .pdwindow.text" bind $mytoplevel <$modifier-Key-w> "wm iconify $mytoplevel" if {$::windowingsystem eq "aqua"} { bind $mytoplevel <$modifier-Key-m> "menu_minimize $mytoplevel" bind $mytoplevel <$modifier-Key-t> "menu_font_dialog $mytoplevel" bind $mytoplevel <$modifier-quoteleft> "menu_raisenextwindow" } else { bind $mytoplevel <$modifier-Key-m> "menu_message_dialog" bind $mytoplevel <$modifier-Key-t> "menu_texteditor" } # Tcl event bindings wm protocol $mytoplevel WM_DELETE_WINDOW "pdsend \"pd verifyquit\"" } # this is for the dialogs: find, font, sendmessage, gatom properties, array # properties, iemgui properties, canvas properties, data structures # properties, Audio setup, and MIDI setup proc ::pd_bindings::dialog_bindings {mytoplevel dialogname} { variable modifier window_bindings $mytoplevel bind $mytoplevel "dialog_${dialogname}::cancel $mytoplevel" bind $mytoplevel "dialog_${dialogname}::ok $mytoplevel" bind $mytoplevel <$modifier-Key-w> "dialog_${dialogname}::cancel $mytoplevel" $mytoplevel configure -padx 10 -pady 5 wm group $mytoplevel . wm resizable $mytoplevel 0 0 wm protocol $mytoplevel WM_DELETE_WINDOW "dialog_${dialogname}::cancel $mytoplevel" catch { # not all platforms/Tcls versions have these options wm attributes $mytoplevel -topmost 1 #wm attributes $mytoplevel -transparent 1 #$mytoplevel configure -highlightthickness 1 } } proc ::pd_bindings::canvas_bindings {mytoplevel} { variable modifier set mycanvas $mytoplevel.c window_bindings $mytoplevel # key bindings ------------------------------------------------------------- bind $mytoplevel <$modifier-Key-1> "pdsend \"$mytoplevel obj\"" bind $mytoplevel <$modifier-Key-2> "pdsend \"$mytoplevel msg\"" bind $mytoplevel <$modifier-Key-3> "pdsend \"$mytoplevel floatatom\"" bind $mytoplevel <$modifier-Key-4> "pdsend \"$mytoplevel symbolatom\"" bind $mytoplevel <$modifier-Key-5> "pdsend \"$mytoplevel text\"" bind $mytoplevel <$modifier-Key-a> "pdsend \"$mytoplevel selectall\"" bind $mytoplevel <$modifier-Key-c> "pdsend \"$mytoplevel copy\"" bind $mytoplevel <$modifier-Key-d> "pdsend \"$mytoplevel duplicate\"" bind $mytoplevel <$modifier-Key-e> "pdsend \"$mytoplevel editmode 0\"" bind $mytoplevel <$modifier-Key-g> "pdsend \"$mytoplevel findagain\"" bind $mytoplevel <$modifier-Key-s> "pdsend \"$mytoplevel menusave\"" bind $mytoplevel <$modifier-Key-v> "pdsend \"$mytoplevel paste\"" bind $mytoplevel <$modifier-Key-w> "pdsend \"$mytoplevel menuclose 0\"" bind $mytoplevel <$modifier-Key-x> "pdsend \"$mytoplevel cut\"" bind $mytoplevel <$modifier-Key-z> "menu_undo $mytoplevel" # annoying, but Tk's bind needs uppercase letter to get the Shift bind $mytoplevel <$modifier-Shift-Key-B> "pdsend \"$mytoplevel bng 1\"" bind $mytoplevel <$modifier-Shift-Key-C> "pdsend \"$mytoplevel mycnv 1\"" bind $mytoplevel <$modifier-Shift-Key-D> "pdsend \"$mytoplevel vradio 1\"" bind $mytoplevel <$modifier-Shift-Key-H> "pdsend \"$mytoplevel hslider 1\"" bind $mytoplevel <$modifier-Shift-Key-I> "pdsend \"$mytoplevel hradio 1\"" bind $mytoplevel <$modifier-Shift-Key-N> "pdsend \"$mytoplevel numbox 1\"" bind $mytoplevel <$modifier-Shift-Key-S> "pdsend \"$mytoplevel menusaveas\"" bind $mytoplevel <$modifier-Shift-Key-T> "pdsend \"$mytoplevel toggle 1\"" bind $mytoplevel <$modifier-Shift-Key-U> "pdsend \"$mytoplevel vumeter 1\"" bind $mytoplevel <$modifier-Shift-Key-V> "pdsend \"$mytoplevel vslider 1\"" bind $mytoplevel <$modifier-Shift-Key-W> "pdsend \"$mytoplevel menuclose 1\"" bind $mytoplevel <$modifier-Shift-Key-Z> "menu_redo $mytoplevel" if {$::windowingsystem eq "aqua"} { bind $mytoplevel <$modifier-Key-m> "menu_minimize $mytoplevel" bind $mytoplevel <$modifier-Key-t> "menu_font_dialog $mytoplevel" bind $mytoplevel <$modifier-quoteleft> "menu_raisenextwindow" } else { bind $mytoplevel <$modifier-Key-m> "menu_message_dialog" bind $mytoplevel <$modifier-Key-t> "menu_texteditor" } bind $mytoplevel "::pd_bindings::sendkey %W 1 %K %A 0" bind $mytoplevel "::pd_bindings::sendkey %W 0 %K %A 0" bind $mytoplevel "::pd_bindings::sendkey %W 1 %K %A 1" bind $mytoplevel "::pd_bindings::sendkey %W 0 %K %A 1" # mouse bindings ----------------------------------------------------------- # these need to be bound to $mycanvas because %W will return $mytoplevel for # events over the window frame and $mytoplevel.c for events over the canvas bind $mycanvas "pdtk_canvas_motion %W %x %y 0" bind $mycanvas <$modifier-Motion> "pdtk_canvas_motion %W %x %y 2" bind $mycanvas "pdtk_canvas_mouse %W %x %y %b 0" bind $mycanvas "pdtk_canvas_mouseup %W %x %y %b" bind $mycanvas <$modifier-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 2" # TODO look into "virtual events' for a means for getting Shift-Button, etc. switch -- $::windowingsystem { "aqua" { bind $mycanvas "pdtk_canvas_rightclick %W %x %y %b" # on Mac OS X, make a rightclick with Ctrl-click for 1 button mice bind $mycanvas "pdtk_canvas_rightclick %W %x %y %b" # TODO try replacing the above with this #bind all {event generate %W \ # -x %x -y %y -rootx %X -rooty %Y \ # -button 2 -time %t} } "x11" { bind $mycanvas "pdtk_canvas_rightclick %W %x %y %b" # on X11, button 2 "pastes" from the X windows clipboard bind $mycanvas "pdtk_canvas_clickpaste %W %x %y %b" } "win32" { bind $mycanvas "pdtk_canvas_rightclick %W %x %y %b" } } #TODO bind $mytoplevel # window protocol bindings wm protocol $mytoplevel WM_DELETE_WINDOW "pdsend \"$mytoplevel menuclose 0\"" bind $mycanvas "::pd_bindings::window_destroy %W" } #------------------------------------------------------------------------------# # event handlers proc ::pd_bindings::window_configure {mytoplevel} { pdtk_canvas_getscroll $mytoplevel } proc ::pd_bindings::window_destroy {mycanvas} { set mytoplevel [winfo toplevel $mycanvas] unset ::editmode($mytoplevel) } # do tasks when changing focus (Window menu, scrollbars, etc.) proc ::pd_bindings::window_focusin {mytoplevel} { # pdtk_post "::pd_bindings::window_focusin $mytoplevel" set ::focused_window $mytoplevel ::dialog_find::set_canvas_to_search $mytoplevel ::pd_menucommands::set_menu_new_dir $mytoplevel ::dialog_font::update_font_dialog $mytoplevel if {$mytoplevel eq ".pdwindow"} { ::pd_menus::configure_for_pdwindow } else { ::pd_menus::configure_for_canvas $mytoplevel } # TODO handle enabling/disabling the Undo and Redo menu items in Edit # TODO handle enabling/disabling the Cut/Copy/Paste menu items in Edit # TODO enable menu items that the Pd window or dialogs might have disabled # TODO update "Open Recent" menu } proc ::pd_bindings::dialog_configure {mytoplevel} { } proc ::pd_bindings::dialog_focusin {mytoplevel} { # TODO disable things on the menus that don't work for dialogs ::pd_menus::configure_for_dialog $mytoplevel } # "map" event tells us when the canvas becomes visible, and "unmap", # invisible. Invisibility means the Window Manager has minimized us. We # don't get a final "unmap" event when we destroy the window. proc ::pd_bindings::map {mytoplevel} { pdsend "$mytoplevel map 1" } proc ::pd_bindings::unmap {mytoplevel} { pdsend "$mytoplevel map 0" } #------------------------------------------------------------------------------# # key usage proc ::pd_bindings::sendkey {mycanvas state key iso shift} { # TODO canvas_key on the C side should be refactored with this proc as well switch -- $key { "BackSpace" { set iso ""; set key 8 } "Tab" { set iso ""; set key 9 } "Return" { set iso ""; set key 10 } "Escape" { set iso ""; set key 27 } "Space" { set iso ""; set key 32 } "Delete" { set iso ""; set key 127 } "KP_Delete" { set iso ""; set key 127 } } if {$iso ne ""} { scan $iso %c key } puts "::pd_bindings::sendkey {%W:$mycanvas $state %K$key %A$iso $shift}" # $mycanvas might be a toplevel, but [winfo toplevel] does the right thing pdsend "[winfo toplevel $mycanvas] key $state $key $shift" }