# .../Plugins/shortcuts.rb - makes and pops up a web page showing your keyboard shortcuts
# Appendix AR (All Ruby) in Edges to Rubies - the Complete SketchUp Tutorial
# Copyright 2010, Martin Rinehart
# Version 1.0, March 10-11, 2010
require 'sketchup'
unless file_loaded?( 'shortcuts.rb' )
pathname = Sketchup.find_support_file( 'shortcuts.rb', 'Plugins' )
UI.menu( "Plugins" ).add_item( "Keyboard Shortcuts" ) {
load( pathname ) }
file_loaded( 'shortcuts.rb' )
else # this else ends at the bottom of the file
html_top = "
SketchUp (and My Own) Keyboard Shortcuts
| Key |
|
Shift+Key |
Ctrl+Key |
Alt+Key |
"
html_middle = ''
html_extra = '
Also:
' # for Ctrl+Shift+...
html_bottom = "
"
$Google_shortcuts = [
"Ctrl+A\tEdit/Select All",
"Ctrl+C\tEdit/Copy",
"Ctrl+X\tEdit/Cut",
"Ctrl+Y\tEdit/Redo",
"Ctrl+Z\tEdit/Undo",
"Ctrl+V\tEdit/Paste",
"Ctrl+Shift+E\tCamera/Zoom Extents",
"Ctrl+N\tFile/New",
"Ctrl+O\tFile/Open...",
"Ctrl+P\tFile/Print...",
"Ctrl+S\tFile/Save",
"Ctrl+T\tEdit/Select None",
"Alt+Backspace\tEdit/Undo",
"Delete\tEdit/Delete",
"Shift+Delete\tEdit/Cut",
"Shift+F1\tSketchUp/Context Help",
"Ctrl+Insert\tEdit/Copy",
"Shift+Insert\tEdit/Paste",
"PageDown\tView/Animation/Next Scene",
"PageUp\tView/Animation/Previous Scene",
"Ctrl+Shift+W\tCamera/Zoom Window",
"Space\tTools/Select",
"G\tEdit/Make Component...",
"L\tDraw/Line",
"E\tTools/Eraser",
"T\tTools/Tape Measure",
"B\tTools/Paint Bucket",
"R\tDraw/Rectangle",
"C\tDraw/Circle",
"A\tDraw/Arc",
"P\tTools/Push/Pull",
"M\tTools/Move",
"Q\tTools/Rotate",
"S\tTools/Scale",
"F\tTools/Offset",
"O\tCamera/Orbit",
"H\tCamera/Pan",
"Z\tCamera/Zoom",
"Shift+Z\tCamera/Zoom Extents"
]
def find( scuts, modi ) # in array of Shortcuts, find the one that has
# the given modifier (and no others)
for s in scuts
kc = s.keycombo()
case modi
when '' then return s unless
kc.shift || kc.ctrl || kc.alt
when 'Shift' then return s if
kc.shift && (!kc.ctrl) && (!kc.alt)
when 'Ctrl' then return s if
kc.ctrl && (!kc.shift) && (!kc.alt)
when 'Alt' then return s if
kc.alt && (!kc.shift) && (!kc.ctrl)
end # of case
end # of for loop
return nil
end # of find()
def not_google( s )
# sets (or not) class for non-Google keyboard shortcut
s
return s.google ? '' : " class='not_google'"
end # of not_google()
def write_extra( s ) # footnotes for complex modifier combinations
kc = s.keycombo
html = ''
html += 'Shift+' if kc.shift()
html += 'Ctrl+' if kc.ctrl()
html += 'Alt+' if kc.alt()
html += kc.key()
html += ': ' + s.description()
html += ' '
end
def write_html( shortcuts_arr, line )
mod6 = (line-1) % 6 # first group is empty
color = mod6 < 3 ? '#ffffff' : '#f0f0ff'
return '' if shortcuts_arr.length() == 0
html = ' | '
html += '| ' + shortcuts_arr[0].keycombo.key + ' | '
html += write_html_cell( shortcuts_arr, '' )
html += write_html_cell( shortcuts_arr, 'Shift' )
html += write_html_cell( shortcuts_arr, 'Ctrl' )
html += write_html_cell( shortcuts_arr, 'Alt' )
html += '
'
return html
end # of write_html()
def write_html_cell( scuts, modi )
s = find( scuts, modi )
return ' | ' if s == nil
return '' + s.description() + ' | '
end
class Keycombo
attr_reader :key, :shift, :ctrl, :alt
# distillation: removing "modifier+" from the left of the key combo until
# no modifiers remain.
def initialize( str )
@string = str
@key = @string
@shift = false
@ctrl = false
@alt = false
while !distilled()
distill()
end
end # of initialize
def complex?() # complex == more than one modifier
modis = 0
modis += 1 if @shift
modis += 1 if @ctrl
modis += 1 if @alt
return modis > 1
end # of complex()
def distill()
# $1 (from beginning up to, but not including first '+')
# $2 (all chars after first '+')
/(^[^+]*)\+(.*)/.match( @key )
qualifier = $1
@key = $2
case qualifier
when 'Shift' then @shift = true
when 'Ctrl' then @ctrl = true
when 'Alt' then @alt = true
end
end
def distilled()
return @key.index( '+' ) == nil
end
def to_s()
ret = "{Keycombo: " + @key
ret += ' Shift' if @shift
ret += ' Ctrl' if @ctrl
ret += ' Alt' if @alt
return ret + '}'
end
end # of class Keycombo
class Shortcut # a Keycombo plus its description
attr_reader :google, :keycombo, :description
def initialize( str )
@string = str
@google = $Google_shortcuts.include?( str )
# $1 (from beginning up to, but not including a tab),
# $2 (then any number of chars after the first tab)
/^([^\t]*)\t(.*)/.match( str )
@keycombo = Keycombo.new( $1 )
@description = $2
end
def <=>( other )
@keycombo.key <=> other.keycombo.key
end
def to_s()
return '{Shortcut: @keycombo=' + ( @keycombo.to_s() ) +
', @description=' + @description + '}'
end
end # of class Shortcut
# mainline -------------------------------------------------------
scuts = Sketchup.get_shortcuts()
shortcuts = []
for s in scuts do shortcuts.push( Shortcut.new(s) ) end
shortcuts.sort!()
# sorted array of Shortcut objects now ready
group_key = ''
group_arr = []
i = 0
for s in shortcuts
if s.keycombo.key != group_key
html_middle += write_html( group_arr, i )
i += 1
group_key = s.keycombo.key
group_arr = []
end
group_arr.push( s )
end
html_middle += write_html( group_arr, i ) # final group not written until this
# individual rows written for each Key
for s in shortcuts
html_extra += write_extra( s ) if s.keycombo().complex?()
end
# extras (Ctrl+Shift+...) written as footnotes
# time to rock and roll!
wd = UI::WebDialog.new( "Keyboard Shortcuts", true, 'keyboard_shortcuts',
640, 480, 0, 0, true )
wd.set_html( html_top + html_middle + html_extra + html_bottom )
wd.add_action_callback( "done" ) { | dlg, msg | wd.close() }
wd.show()
end # of unless file_loaded?() (from top of file)
# end of .../Plugins/shortcuts.rb