- merge v0.01 --> Añadido fileselector - Añadidas fuentes de Gem y Pure Data - pix2jpg incluído en Gem. Archivos de construcción de Gem modificados. - Añadido fichero ompiling.txt con instrucciones de compilación
270 lines
12 KiB
Tcl
270 lines
12 KiB
Tcl
package provide pd_bindings 0.1
|
|
|
|
package require pd_menucommands
|
|
package require dialog_find
|
|
|
|
namespace eval ::pd_bindings:: {
|
|
namespace export global_bindings
|
|
namespace export dialog_bindings
|
|
namespace export patch_bindings
|
|
}
|
|
|
|
# TODO rename pd_bindings to window_bindings after merge is done
|
|
|
|
# Some 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 most menu/bind commands here and in pd_menus.tcl, which use
|
|
# {} to force execution of any variables (i.e. $::focused_window) until later
|
|
|
|
|
|
# binding by class is not recursive, so its useful for window events
|
|
proc ::pd_bindings::class_bindings {} {
|
|
# and the Pd window is in a class to itself
|
|
bind PdWindow <FocusIn> "::pd_bindings::window_focusin %W"
|
|
# bind to all the windows dedicated to patch canvases
|
|
bind PatchWindow <FocusIn> "::pd_bindings::window_focusin %W"
|
|
bind PatchWindow <Map> "::pd_bindings::map %W"
|
|
bind PatchWindow <Unmap> "::pd_bindings::unmap %W"
|
|
bind PatchWindow <Configure> "::pd_bindings::patch_configure %W %w %h %x %y"
|
|
# dialog panel windows bindings, which behave differently than PatchWindows
|
|
bind DialogWindow <Configure> "::pd_bindings::dialog_configure %W"
|
|
bind DialogWindow <FocusIn> "::pd_bindings::dialog_focusin %W"
|
|
}
|
|
|
|
proc ::pd_bindings::global_bindings {} {
|
|
# we use 'bind all' everywhere to get as much of Tk's automatic binding
|
|
# behaviors as possible, things like not sending an event for 'O' when
|
|
# 'Control-O' is pressed.
|
|
bind all <$::modifier-Key-a> {menu_send %W selectall}
|
|
bind all <$::modifier-Key-b> {menu_helpbrowser}
|
|
bind all <$::modifier-Key-c> {menu_send %W copy}
|
|
bind all <$::modifier-Key-d> {menu_send %W duplicate}
|
|
bind all <$::modifier-Key-e> {menu_toggle_editmode}
|
|
bind all <$::modifier-Key-f> {menu_find_dialog}
|
|
bind all <$::modifier-Key-g> {menu_send %W findagain}
|
|
bind all <$::modifier-Key-n> {menu_new}
|
|
bind all <$::modifier-Key-o> {menu_open}
|
|
bind all <$::modifier-Key-p> {menu_print $::focused_window}
|
|
bind all <$::modifier-Key-q> {pdsend "pd verifyquit"}
|
|
bind all <$::modifier-Key-r> {menu_raise_pdwindow}
|
|
bind all <$::modifier-Key-s> {menu_send %W menusave}
|
|
bind all <$::modifier-Key-v> {menu_send %W paste}
|
|
bind all <$::modifier-Key-w> {menu_send_float %W menuclose 0}
|
|
bind all <$::modifier-Key-x> {menu_send %W cut}
|
|
bind all <$::modifier-Key-z> {menu_undo}
|
|
bind all <$::modifier-Key-1> {menu_send_float %W obj 0}
|
|
bind all <$::modifier-Key-2> {menu_send_float %W msg 0}
|
|
bind all <$::modifier-Key-3> {menu_send_float %W floatatom 0}
|
|
bind all <$::modifier-Key-4> {menu_send_float %W symbolatom 0}
|
|
bind all <$::modifier-Key-5> {menu_send_float %W text 0}
|
|
bind all <$::modifier-Key-slash> {pdsend "pd dsp 1"}
|
|
bind all <$::modifier-Key-period> {pdsend "pd dsp 0"}
|
|
bind all <$::modifier-greater> {menu_raisenextwindow}
|
|
bind all <$::modifier-less> {menu_raisepreviouswindow}
|
|
|
|
# annoying, but Tk's bind needs uppercase letter to get the Shift
|
|
bind all <$::modifier-Shift-Key-B> {menu_send %W bng}
|
|
bind all <$::modifier-Shift-Key-C> {menu_send %W mycnv}
|
|
bind all <$::modifier-Shift-Key-D> {menu_send %W vradio}
|
|
bind all <$::modifier-Shift-Key-H> {menu_send %W hslider}
|
|
bind all <$::modifier-Shift-Key-I> {menu_send %W hradio}
|
|
bind all <$::modifier-Shift-Key-L> {menu_clear_console}
|
|
bind all <$::modifier-Shift-Key-N> {menu_send %W numbox}
|
|
bind all <$::modifier-Shift-Key-Q> {pdsend "pd quit"}
|
|
bind all <$::modifier-Shift-Key-S> {menu_send %W menusaveas}
|
|
bind all <$::modifier-Shift-Key-T> {menu_send %W toggle}
|
|
bind all <$::modifier-Shift-Key-U> {menu_send %W vumeter}
|
|
bind all <$::modifier-Shift-Key-V> {menu_send %W vslider}
|
|
bind all <$::modifier-Shift-Key-W> {menu_send_float %W menuclose 1}
|
|
bind all <$::modifier-Shift-Key-Z> {menu_redo}
|
|
|
|
# OS-specific bindings
|
|
if {$::windowingsystem eq "aqua"} {
|
|
# Cmd-m = Minimize and Cmd-t = Font on Mac OS X for all apps
|
|
bind all <$::modifier-Key-m> {menu_minimize %W}
|
|
bind all <$::modifier-Key-t> {menu_font_dialog}
|
|
bind all <$::modifier-quoteleft> {menu_raisenextwindow}
|
|
bind all <$::modifier-Shift-Key-M> {menu_message_dialog}
|
|
} else {
|
|
bind all <$::modifier-Key-m> {menu_message_dialog}
|
|
#bind all <$::modifier-Key-t> {menu_texteditor}
|
|
bind all <$::modifier-Next> {menu_raisenextwindow} ;# PgUp
|
|
bind all <$::modifier-Prior> {menu_raisepreviouswindow};# PageDown
|
|
}
|
|
|
|
bind all <KeyPress> {::pd_bindings::sendkey %W 1 %K %A 0}
|
|
bind all <KeyRelease> {::pd_bindings::sendkey %W 0 %K %A 0}
|
|
bind all <Shift-KeyPress> {::pd_bindings::sendkey %W 1 %K %A 1}
|
|
bind all <Shift-KeyRelease> {::pd_bindings::sendkey %W 0 %K %A 1}
|
|
}
|
|
|
|
# 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
|
|
|
|
bind $mytoplevel <KeyPress-Escape> "dialog_${dialogname}::cancel $mytoplevel"
|
|
bind $mytoplevel <KeyPress-Return> "dialog_${dialogname}::ok $mytoplevel"
|
|
bind $mytoplevel <$::modifier-Key-w> "dialog_${dialogname}::cancel $mytoplevel"
|
|
# these aren't supported in the dialog, so alert the user, then break so
|
|
# that no other key bindings are run
|
|
bind $mytoplevel <$::modifier-Key-s> {bell; break}
|
|
bind $mytoplevel <$::modifier-Shift-Key-S> {bell; break}
|
|
bind $mytoplevel <$::modifier-Key-p> {bell; break}
|
|
|
|
wm protocol $mytoplevel WM_DELETE_WINDOW "dialog_${dialogname}::cancel $mytoplevel"
|
|
}
|
|
|
|
proc ::pd_bindings::patch_bindings {mytoplevel} {
|
|
variable modifier
|
|
set tkcanvas [tkcanvas_name $mytoplevel]
|
|
|
|
# TODO move mouse bindings to global and bind to 'all'
|
|
|
|
# mouse bindings -----------------------------------------------------------
|
|
# these need to be bound to $tkcanvas because %W will return $mytoplevel for
|
|
# events over the window frame and $tkcanvas for events over the canvas
|
|
bind $tkcanvas <Motion> "pdtk_canvas_motion %W %x %y 0"
|
|
bind $tkcanvas <$::modifier-Motion> "pdtk_canvas_motion %W %x %y 2"
|
|
bind $tkcanvas <ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 0"
|
|
bind $tkcanvas <ButtonRelease-1> "pdtk_canvas_mouseup %W %x %y %b"
|
|
bind $tkcanvas <$::modifier-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 2"
|
|
bind $tkcanvas <Shift-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 1"
|
|
|
|
if {$::windowingsystem eq "x11"} {
|
|
# from http://wiki.tcl.tk/3893
|
|
bind all <Button-4> \
|
|
{event generate [focus -displayof %W] <MouseWheel> -delta 1}
|
|
bind all <Button-5> \
|
|
{event generate [focus -displayof %W] <MouseWheel> -delta -1}
|
|
bind all <Shift-Button-4> \
|
|
{event generate [focus -displayof %W] <Shift-MouseWheel> -delta 1}
|
|
bind all <Shift-Button-5> \
|
|
{event generate [focus -displayof %W] <Shift-MouseWheel> -delta -1}
|
|
}
|
|
bind $tkcanvas <MouseWheel> {::pdtk_canvas::scroll %W y %D}
|
|
bind $tkcanvas <Shift-MouseWheel> {::pdtk_canvas::scroll %W x %D}
|
|
|
|
# "right clicks" are defined differently on each platform
|
|
switch -- $::windowingsystem {
|
|
"aqua" {
|
|
bind $tkcanvas <ButtonPress-2> "pdtk_canvas_rightclick %W %x %y %b"
|
|
# on Mac OS X, make a rightclick with Ctrl-click for 1 button mice
|
|
bind $tkcanvas <Control-Button-1> "pdtk_canvas_rightclick %W %x %y %b"
|
|
bind $tkcanvas <Option-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 3"
|
|
} "x11" {
|
|
bind $tkcanvas <ButtonPress-3> "pdtk_canvas_rightclick %W %x %y %b"
|
|
# on X11, button 2 "pastes" from the X windows clipboard
|
|
bind $tkcanvas <ButtonPress-2> "pdtk_canvas_clickpaste %W %x %y %b"
|
|
bind $tkcanvas <Alt-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 3"
|
|
} "win32" {
|
|
bind $tkcanvas <ButtonPress-3> "pdtk_canvas_rightclick %W %x %y %b"
|
|
bind $tkcanvas <Alt-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 3"
|
|
}
|
|
}
|
|
|
|
# window protocol bindings
|
|
wm protocol $mytoplevel WM_DELETE_WINDOW "pdsend \"$mytoplevel menuclose 0\""
|
|
bind $tkcanvas <Destroy> "::pd_bindings::window_destroy %W"
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
# event handlers
|
|
|
|
proc ::pd_bindings::patch_configure {mytoplevel width height x y} {
|
|
# for some reason, when we create a window, we get an event with a
|
|
# widthXheight of 1x1 first, then we get the right values, so filter it out
|
|
if {$width == 1 && $height == 1} {return}
|
|
pdtk_canvas_getscroll [tkcanvas_name $mytoplevel]
|
|
# send the size/location of the window and canvas to 'pd' in the form of:
|
|
# left top right bottom
|
|
pdsend "$mytoplevel setbounds $x $y [expr $x + $width] [expr $y + $height]"
|
|
}
|
|
|
|
proc ::pd_bindings::window_destroy {window} {
|
|
set mytoplevel [winfo toplevel $window]
|
|
unset ::editmode($mytoplevel)
|
|
unset ::editingtext($mytoplevel)
|
|
unset ::loaded($mytoplevel)
|
|
# unset my entries all of the window data tracking arrays
|
|
array unset ::windowname $mytoplevel
|
|
array unset ::parentwindows $mytoplevel
|
|
array unset ::childwindows $mytoplevel
|
|
}
|
|
|
|
# do tasks when changing focus (Window menu, scrollbars, etc.)
|
|
proc ::pd_bindings::window_focusin {mytoplevel} {
|
|
# focused_window is used throughout for sending bindings, menu commands,
|
|
# etc. to the correct patch receiver symbol.
|
|
set ::focused_window $mytoplevel
|
|
::dialog_find::set_window_to_search $mytoplevel
|
|
::pd_menucommands::set_filenewdir $mytoplevel
|
|
::dialog_font::update_font_dialog $mytoplevel
|
|
if {$mytoplevel eq ".pdwindow"} {
|
|
::pd_menus::configure_for_pdwindow
|
|
} else {
|
|
::pd_menus::configure_for_canvas $mytoplevel
|
|
}
|
|
if {[winfo exists .font]} {wm transient .font $::focused_window}
|
|
# if we regain focus from another app, make sure to editmode cursor is right
|
|
if {$::editmode($mytoplevel)} {
|
|
$mytoplevel configure -cursor hand2
|
|
}
|
|
# TODO handle enabling/disabling the Cut/Copy/Paste menu items in Edit
|
|
}
|
|
|
|
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"
|
|
::pdtk_canvas::finished_loading_file $mytoplevel
|
|
}
|
|
|
|
proc ::pd_bindings::unmap {mytoplevel} {
|
|
pdsend "$mytoplevel map 0"
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
# key usage
|
|
|
|
# canvas_key() expects to receive the patch's mytoplevel because key messages
|
|
# are local to each patch. Therefore, key messages are not send for the
|
|
# dialog panels, the Pd window, help browser, etc. so we need to filter those
|
|
# events out.
|
|
proc ::pd_bindings::sendkey {window 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
|
|
}
|
|
# some pop-up panels also bind to keys like the enter, but then disappear,
|
|
# so ignore their events. The inputbox in the Startup dialog does this.
|
|
if {! [winfo exists $window]} {return}
|
|
#$window might be a toplevel or canvas, [winfo toplevel] does the right thing
|
|
set mytoplevel [winfo toplevel $window]
|
|
if {[winfo class $mytoplevel] eq "PatchWindow"} {
|
|
pdsend "$mytoplevel key $state $key $shift"
|
|
}
|
|
# TODO send to 'pd key' for global key events in Pd?
|
|
}
|