Import LinuxCNC source tree
This commit is contained in:
297
lib/python/popupkeyboard.py
Executable file
297
lib/python/popupkeyboard.py
Executable file
@@ -0,0 +1,297 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Copyright: 2013
|
||||
# Author: Dewey Garrett <dgarrett@panix.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
# popup keyboard for use with touchscreen applications
|
||||
# used by pyngcgui.py
|
||||
# based on work of John Thornton's Buglump
|
||||
|
||||
Optional __init__() args:
|
||||
glade_file (default = 'popupkeyboard.ui')
|
||||
dialog_name (default = 'dialog') Main window
|
||||
num_entry_name (default = 'num_entry') Entry for display
|
||||
coord_buttons_name (default = 'coords') Box for coord buttons
|
||||
use_coord_buttons (default = True) Enable coord buttons
|
||||
|
||||
Required objects for glade_file:
|
||||
Gtk.Window (Main window)
|
||||
Gtk.Entry (Entry for display)
|
||||
|
||||
Optional objects for galde_file:
|
||||
Gtk.*Box: (Box for coord buttons)
|
||||
|
||||
All buttons use a single handler named 'on_click'.
|
||||
The PopupKeyboard class recognizes buttons by their LABEL.
|
||||
|
||||
Required button LABELS (case insensitive):
|
||||
0,1,2,3,4,5,6,7,8,9,. (numbers and decimal point)
|
||||
+/- (toggle sign)
|
||||
clear (clear)
|
||||
bs (back space)
|
||||
save (save)
|
||||
cancel (cancel)
|
||||
Optional button LABELS (case insensitive):
|
||||
x,y,z,a,b,c,u,v,w,d (9 axes plus d for diameter)
|
||||
|
||||
"""
|
||||
|
||||
import linuxcnc
|
||||
import sys
|
||||
import os
|
||||
import gi
|
||||
gi.require_version('Pango', '1.0')
|
||||
from gi.repository import Pango
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
g_ui_dir = linuxcnc.SHARE + "/linuxcnc"
|
||||
|
||||
class PopupKeyboard:
|
||||
def __init__(self
|
||||
,glade_file=None
|
||||
,dialog_name='dialog'
|
||||
,num_entry_name='num_entry'
|
||||
,coord_buttons_name='coords'
|
||||
,use_coord_buttons=True
|
||||
,theme_name=None
|
||||
):
|
||||
|
||||
if (glade_file is None):
|
||||
glade_file = os.path.join(g_ui_dir,'popupkeyboard.ui')
|
||||
|
||||
fontname ='sans 12 bold'
|
||||
self.use_coord_buttons = use_coord_buttons
|
||||
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.add_from_file(glade_file)
|
||||
self.builder.connect_signals(self)
|
||||
|
||||
self.dialog = self.builder.get_object(dialog_name)
|
||||
self.set_theme(theme_name)
|
||||
self.num_entry = self.builder.get_object(num_entry_name)
|
||||
try:
|
||||
self.coord_buttons = self.builder.get_object(coord_buttons_name)
|
||||
except:
|
||||
self.coord_buttons = None
|
||||
|
||||
self.result = None
|
||||
self.location = None
|
||||
|
||||
self.top = self.dialog.get_toplevel()
|
||||
self.top.set_title(glade_file)
|
||||
self.top.set_keep_above(True)
|
||||
|
||||
if (not self.use_coord_buttons):
|
||||
if self.coord_buttons:
|
||||
self.coord_buttons.hide()
|
||||
|
||||
# prevent closing of dialog by window manager, escape key , etc
|
||||
# http://faq.pygtk.org/index.py?file=faq10.013.htp&req=show
|
||||
self.top.connect("response", self.on_response) #reqd
|
||||
self.top.connect("delete-event",self.on_delete) #reqd
|
||||
self.top.connect("close", self.on_close) #probably not reqd
|
||||
|
||||
# find buttons with labels XYZABCUVW or D
|
||||
# and show iff corresponding axis is in axis_mask
|
||||
self.label_to_btn = {}
|
||||
for btn in self.builder.get_objects():
|
||||
if type(btn) is not Gtk.Button:
|
||||
continue
|
||||
self.label_to_btn[btn.get_label().upper()] = btn
|
||||
|
||||
#not working gtk3:
|
||||
#if isinstance(btn.child, Gtk.Label):
|
||||
# lbl = btn.child
|
||||
# lbl.modify_font(Pango.FontDescription(fontname))
|
||||
|
||||
if use_coord_buttons: self.support_coord_buttons()
|
||||
|
||||
# making it insensitive clears the initial selection region
|
||||
#deprecated in gtk3:
|
||||
#self.num_entry.set_state(Gtk.StateType.INSENSITIVE)
|
||||
#self.num_entry.modify_text(Gtk.StateType.INSENSITIVE
|
||||
# ,Gtk.gdk.color_parse('black'))
|
||||
#self.num_entry.modify_font(Pango.FontDescription(fontname))
|
||||
|
||||
def support_coord_buttons(self):
|
||||
try:
|
||||
self.stat = linuxcnc.stat()
|
||||
self.stat.poll()
|
||||
has_x = False
|
||||
for axno in range(0,9):
|
||||
axname = 'XYZABCUVW'[axno]
|
||||
if axname in self.label_to_btn:
|
||||
b = self.label_to_btn[axname]
|
||||
if bool(self.stat.axis_mask & (1 << axno)):
|
||||
b.show()
|
||||
if axno == 0: has_x = True
|
||||
else:
|
||||
b.hide()
|
||||
bdiam = None
|
||||
if 'D' in self.label_to_btn:
|
||||
bdiam = self.label_to_btn['D']
|
||||
if bdiam and has_x:
|
||||
bdiam.show()
|
||||
elif bdiam:
|
||||
bdiam.hide()
|
||||
except linuxcnc.error as msg:
|
||||
self.stat = None
|
||||
if self.coord_buttons is not None:
|
||||
self.coord_buttons.hide()
|
||||
print("linuxcnc must be running to use coordinate keys")
|
||||
# continue without buttons for testing when linuxnc not running
|
||||
except Exception as err:
|
||||
print('Exception:',Exception)
|
||||
print(sys.exc_info())
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def set_theme(self,tname=None):
|
||||
if tname is None:
|
||||
return
|
||||
screen = self.dialog.get_screen()
|
||||
#wip: gtk3 notworking
|
||||
#settings = Gtk.settings_get_for_screen(screen)
|
||||
#settings.set_string_property('gtk-theme-name',tname,"")
|
||||
#theme = settings.get_property('gtk-theme-name')
|
||||
|
||||
# prevent closing of dialog by window manager, escape key , etc
|
||||
def on_response(self,widget,response):
|
||||
if response < 0:
|
||||
GObject.signal_stop_emission_by_name(widget,'response')
|
||||
return True
|
||||
|
||||
def on_delete(self,widget,event): return True
|
||||
|
||||
def on_close(self,widget,event): return True
|
||||
|
||||
def run(self,initial_value='',title=None):
|
||||
if title is not None:
|
||||
self.top.set_title(title)
|
||||
self.num_entry.set_text(str(initial_value))
|
||||
if self.location:
|
||||
#Gtk3:deprecated:
|
||||
#self.dialog.parse_geometry('+%d+%d'
|
||||
# % (self.location[0],self.location[1]))
|
||||
pass
|
||||
self.num_entry.set_position(0)
|
||||
self.dialog.run()
|
||||
if self.result is None:
|
||||
return False #user canceled
|
||||
else:
|
||||
return True
|
||||
|
||||
def on_click(self, widget, data=None):
|
||||
l = widget.get_label()
|
||||
e = self.num_entry
|
||||
self.label_to_method(l)(e,l)
|
||||
|
||||
def label_to_method(self,l):
|
||||
ll = l.lower()
|
||||
if ll.find('clear') >= 0: return self.do_clear
|
||||
if ll.find('save') >= 0: return self.do_save
|
||||
if ll.find('cancel')>= 0: return self.do_cancel
|
||||
if ll.find('+/-') >= 0: return self.do_sign
|
||||
if ll.find('bs') >= 0: return self.do_backspace
|
||||
if ll in ('.0123456789'): return self.do_number
|
||||
if ll in ('xyzabcuvwd'): return self.do_axis_letter
|
||||
return self.do_unknown_label
|
||||
|
||||
def do_unknown_label(self,e,l):
|
||||
print('PopupKeyboard:do_unknown_label: <%s>' % l)
|
||||
|
||||
def do_number(self,e,l):
|
||||
# not needed if INSENSITIVE:
|
||||
# if e.get_selection_bounds(): e.delete_selection()
|
||||
e.set_text(e.get_text() + l)
|
||||
|
||||
def do_backspace(self,e,l):
|
||||
e.set_text(e.get_text()[:-1])
|
||||
|
||||
def do_sign(self,e,l):
|
||||
current = e.get_text()
|
||||
if current == '':
|
||||
current = '-'
|
||||
elif current[0] == '-':
|
||||
current = current[1:]
|
||||
else:
|
||||
current = '-' + current
|
||||
e.set_text(current)
|
||||
|
||||
def do_save(self,e,l):
|
||||
self.result = e.get_text()
|
||||
e.set_text('')
|
||||
self.location = self.dialog.get_position()
|
||||
self.dialog.hide() # tells dialog.run() to finish
|
||||
|
||||
def do_cancel(self,e,l):
|
||||
self.result = None # None means canceled
|
||||
self.dialog.hide() # tells dialog.run() to finish
|
||||
|
||||
def do_clear(self,e,l):
|
||||
e.set_text('')
|
||||
|
||||
def do_axis_letter(self,e,l):
|
||||
if self.stat:
|
||||
self.stat.poll()
|
||||
e.set_text("%.6g" % self.coord_value(l))
|
||||
else:
|
||||
print("linuxcnc must be running to use <%s> key" % l)
|
||||
|
||||
def get_result(self):
|
||||
return(self.result)
|
||||
|
||||
def coord_value(self,char):
|
||||
# offset calc copied from emc_interface.py
|
||||
# char = 'x' | 'y' | ...
|
||||
# 'd' is for diameter
|
||||
s = self.stat
|
||||
s.poll()
|
||||
p = s.position # tuple=(xvalue, yvalue, ...
|
||||
return {
|
||||
'x': p[0] - s.g5x_offset[0] - s.tool_offset[0],
|
||||
'y': p[1] - s.g5x_offset[1] - s.tool_offset[1],
|
||||
'z': p[2] - s.g5x_offset[2] - s.tool_offset[2],
|
||||
'a': p[3] - s.g5x_offset[3] - s.tool_offset[3],
|
||||
'b': p[4] - s.g5x_offset[4] - s.tool_offset[4],
|
||||
'c': p[5] - s.g5x_offset[5] - s.tool_offset[5],
|
||||
'u': p[6] - s.g5x_offset[6] - s.tool_offset[6],
|
||||
'v': p[7] - s.g5x_offset[7] - s.tool_offset[7],
|
||||
'w': p[8] - s.g5x_offset[8] - s.tool_offset[8],
|
||||
'd':(p[0] - s.g5x_offset[0] - s.tool_offset[0])* 2,#2*R
|
||||
}[char.lower()]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
m = PopupKeyboard()
|
||||
print("\nClear and Save to end test\n")
|
||||
ct = 100
|
||||
while True:
|
||||
m.run(initial_value=''
|
||||
,title=str(ct)
|
||||
)
|
||||
result = m.get_result()
|
||||
print('result = <%s>' % result)
|
||||
if result=='':
|
||||
sys.exit(0)
|
||||
ct += 1
|
||||
Gtk.main()
|
||||
# vim: sts=4 sw=4 et
|
||||
Reference in New Issue
Block a user