commit
3d2054bf06
|
@ -0,0 +1,117 @@
|
||||||
|
"""
|
||||||
|
BufferedCanvas -- flicker-free canvas widget
|
||||||
|
Copyright (C) 2005, 2006 Daniel Keep, 2011 Duane Johnson
|
||||||
|
|
||||||
|
To use this widget, just override or replace the draw method.
|
||||||
|
This will be called whenever the widget size changes, or when
|
||||||
|
the update method is explicitly called.
|
||||||
|
|
||||||
|
Please submit any improvements/bugfixes/ideas to the following
|
||||||
|
url:
|
||||||
|
|
||||||
|
http://wiki.wxpython.org/index.cgi/BufferedCanvas
|
||||||
|
|
||||||
|
2006-04-29: Added bugfix for a crash on Mac provided by Marc Jans.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Hint: try removing '.sp4msux0rz'
|
||||||
|
__author__ = 'Daniel Keep <daniel.keep.sp4msux0rz@gmail.com>'
|
||||||
|
|
||||||
|
__license__ = """
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
As a special exception, the copyright holders of this library
|
||||||
|
hereby recind Section 3 of the GNU Lesser General Public License. This
|
||||||
|
means that you MAY NOT apply the terms of the ordinary GNU General
|
||||||
|
Public License instead of this License to any given copy of the
|
||||||
|
Library. This has been done to prevent users of the Library from being
|
||||||
|
denied access or the ability to use future improvements.
|
||||||
|
|
||||||
|
This library 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 Lesser
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['BufferedCanvas']
|
||||||
|
|
||||||
|
import wx
|
||||||
|
|
||||||
|
class BufferedCanvas(wx.Panel):
|
||||||
|
"""
|
||||||
|
Implements a flicker-free canvas widget.
|
||||||
|
|
||||||
|
Standard usage is to subclass this class, and override the
|
||||||
|
draw method. The draw method is passed a device context, which
|
||||||
|
should be used to do your drawing.
|
||||||
|
|
||||||
|
If you want to force a redraw (for whatever reason), you should
|
||||||
|
call the update method. This is because the draw method is never
|
||||||
|
called as a result of an EVT_PAINT event.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# These are our two buffers. Just be aware that when the buffers
|
||||||
|
# are flipped, the REFERENCES are swapped. So I wouldn't want to
|
||||||
|
# try holding onto explicit references to one or the other ;)
|
||||||
|
buffer = None
|
||||||
|
backbuffer = None
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
parent,
|
||||||
|
ID=-1,
|
||||||
|
pos=wx.DefaultPosition,
|
||||||
|
size=wx.DefaultSize,
|
||||||
|
style=wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS):
|
||||||
|
wx.Panel.__init__(self,parent,ID,pos,size,style)
|
||||||
|
|
||||||
|
# Bind events
|
||||||
|
self.Bind(wx.EVT_PAINT, self.onPaint)
|
||||||
|
|
||||||
|
# Disable background erasing (flicker-licious)
|
||||||
|
def disable_event(*pargs,**kwargs):
|
||||||
|
pass # the sauce, please
|
||||||
|
self.Bind(wx.EVT_ERASE_BACKGROUND, disable_event)
|
||||||
|
|
||||||
|
##
|
||||||
|
## General methods
|
||||||
|
##
|
||||||
|
|
||||||
|
def draw(self,dc):
|
||||||
|
"""
|
||||||
|
Stub: called when the canvas needs to be re-drawn.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""
|
||||||
|
Causes the canvas to be updated.
|
||||||
|
"""
|
||||||
|
self.Refresh()
|
||||||
|
|
||||||
|
def getWidthHeight(self):
|
||||||
|
width,height = self.GetClientSizeTuple()
|
||||||
|
if width == 0:
|
||||||
|
width = 1
|
||||||
|
if height == 0:
|
||||||
|
height = 1
|
||||||
|
return (width, height)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Event handlers
|
||||||
|
##
|
||||||
|
|
||||||
|
def onPaint(self, event):
|
||||||
|
# Blit the front buffer to the screen
|
||||||
|
w, h = self.GetClientSizeTuple()
|
||||||
|
if not w or not h:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
dc = wx.BufferedPaintDC(self)
|
||||||
|
self.draw(dc, w, h)
|
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
118
pronterface.py
118
pronterface.py
|
@ -30,6 +30,8 @@ if os.name=="nt":
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
from xybuttons import XYButtons
|
||||||
|
from zbuttons import ZButtons
|
||||||
import pronsole
|
import pronsole
|
||||||
|
|
||||||
def dosify(name):
|
def dosify(name):
|
||||||
|
@ -65,6 +67,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
wx.Frame.__init__(self,None,title=_("Printer Interface"),size=size);
|
wx.Frame.__init__(self,None,title=_("Printer Interface"),size=size);
|
||||||
self.SetIcon(wx.Icon("P-face.ico",wx.BITMAP_TYPE_ICO))
|
self.SetIcon(wx.Icon("P-face.ico",wx.BITMAP_TYPE_ICO))
|
||||||
self.panel=wx.Panel(self,-1,size=size)
|
self.panel=wx.Panel(self,-1,size=size)
|
||||||
|
self.panel.SetBackgroundColour("white")
|
||||||
self.statuscheck=False
|
self.statuscheck=False
|
||||||
self.tempreport=""
|
self.tempreport=""
|
||||||
self.monitor=0
|
self.monitor=0
|
||||||
|
@ -74,36 +77,10 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
ycol=(180,180,255)
|
ycol=(180,180,255)
|
||||||
zcol=(180,255,180)
|
zcol=(180,255,180)
|
||||||
self.cpbuttons=[
|
self.cpbuttons=[
|
||||||
[_("X+100"),("move X 100"),(2,0),xcol,(1,3)],
|
[_("Motors off"),("M84"),(1,0),(250,250,250),(1,2)],
|
||||||
[_("X+10"),("move X 10"),(3,0),xcol,(1,3)],
|
[_("Check temp"),("M105"),(3,5),(225,200,200),(1,3)],
|
||||||
[_("X+1"),("move X 1"),(4,0),xcol,(1,3)],
|
[_("Extrude"),("extrude"),(5,0),(225,200,200),(1,2)],
|
||||||
[_("X+0.1"),("move X 0.1"),(5,0),xcol,(1,3)],
|
[_("Reverse"),("reverse"),(6,0),(225,200,200),(1,2)],
|
||||||
[_("HomeX"),("home X"),(6,0),(205,205,78),(1,3)],
|
|
||||||
[_("X-0.1"),("move X -0.1"),(7,0),xcol,(1,3)],
|
|
||||||
[_("X-1"),("move X -1"),(8,0),xcol,(1,3)],
|
|
||||||
[_("X-10"),("move X -10"),(9,0),xcol,(1,3)],
|
|
||||||
[_("X-100"),("move X -100"),(10,0),xcol,(1,3)],
|
|
||||||
[_("Y+100"),("move Y 100"),(2,3),ycol,(1,3)],
|
|
||||||
[_("Y+10"),("move Y 10"),(3,3),ycol,(1,3)],
|
|
||||||
[_("Y+1"),("move Y 1"),(4,3),ycol,(1,3)],
|
|
||||||
[_("Y+0.1"),("move Y 0.1"),(5,3),ycol,(1,3)],
|
|
||||||
[_("HomeY"),("home Y"),(6,3),(150,150,205),(1,3)],
|
|
||||||
[_("Y-0.1"),("move Y -0.1"),(7,3),ycol,(1,3)],
|
|
||||||
[_("Y-1"),("move Y -1"),(8,3),ycol,(1,3)],
|
|
||||||
[_("Y-10"),("move Y -10"),(9,3),ycol,(1,3)],
|
|
||||||
[_("Y-100"),("move Y -100"),(10,3),ycol,(1,3)],
|
|
||||||
[_("Motors off"),("M84"),(2,6),(250,250,250),(1,3)],
|
|
||||||
[_("Z+10"),("move Z 10"),(3,6),zcol,(1,3)],
|
|
||||||
[_("Z+1"),("move Z 1"),(4,6),zcol,(1,3)],
|
|
||||||
[_("Z+0.1"),("move Z 0.1"),(5,6),zcol,(1,3)],
|
|
||||||
[_("HomeZ"),("home Z"),(6,6),(150,205,150),(1,3)],
|
|
||||||
[_("Z-0.1"),("move Z -0.1"),(7,6),zcol,(1,3)],
|
|
||||||
[_("Z-1"),("move Z -1"),(8,6),zcol,(1,3)],
|
|
||||||
[_("Z-10"),("move Z -10"),(9,6),zcol,(1,3)],
|
|
||||||
[_("Home"),("home"),(10,6),(250,250,250),(1,3)],
|
|
||||||
[_("Check temp"),("M105"),(11,6),(225,200,200),(1,3)],
|
|
||||||
[_("Extrude"),("extrude"),(13,0),(225,200,200),(1,2)],
|
|
||||||
[_("Reverse"),("reverse"),(14,0),(225,200,200),(1,2)],
|
|
||||||
]
|
]
|
||||||
self.custombuttons=[]
|
self.custombuttons=[]
|
||||||
self.btndict={}
|
self.btndict={}
|
||||||
|
@ -158,6 +135,11 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
wx.CallAfter(self.connectbtn.Disable)
|
wx.CallAfter(self.connectbtn.Disable)
|
||||||
for i in self.printerControls:
|
for i in self.printerControls:
|
||||||
wx.CallAfter(i.Enable)
|
wx.CallAfter(i.Enable)
|
||||||
|
|
||||||
|
# Enable XYButtons and ZButtons
|
||||||
|
self.xyb.enable()
|
||||||
|
self.zb.enable()
|
||||||
|
|
||||||
if self.filename:
|
if self.filename:
|
||||||
wx.CallAfter(self.printbtn.Enable)
|
wx.CallAfter(self.printbtn.Enable)
|
||||||
|
|
||||||
|
@ -417,7 +399,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
portslist += [self.settings.port]
|
portslist += [self.settings.port]
|
||||||
self.serialport = wx.ComboBox(self.panel, -1,
|
self.serialport = wx.ComboBox(self.panel, -1,
|
||||||
choices=portslist,
|
choices=portslist,
|
||||||
style=wx.CB_DROPDOWN|wx.CB_SORT, pos=(50,0))
|
style=wx.CB_DROPDOWN|wx.CB_SORT|wx.CB_READONLY, pos=(50,0))
|
||||||
try:
|
try:
|
||||||
if self.settings.port in scan:
|
if self.settings.port in scan:
|
||||||
self.serialport.SetValue(self.settings.port)
|
self.serialport.SetValue(self.settings.port)
|
||||||
|
@ -428,8 +410,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
uts.Add(self.serialport)
|
uts.Add(self.serialport)
|
||||||
uts.Add(wx.StaticText(self.panel,-1,"@",pos=(250,5)),wx.RIGHT,5)
|
uts.Add(wx.StaticText(self.panel,-1,"@",pos=(250,5)),wx.RIGHT,5)
|
||||||
self.baud = wx.ComboBox(self.panel, -1,
|
self.baud = wx.ComboBox(self.panel, -1,
|
||||||
choices=["2400", "9600", "19200", "38400", "57600", "115200"],
|
choices=["2400", "9600", "19200", "38400", "57600", "115200", "250000"],
|
||||||
style=wx.CB_DROPDOWN|wx.CB_SORT, size=(110,30),pos=(275,0))
|
style=wx.CB_DROPDOWN|wx.CB_SORT|wx.CB_READONLY, size=(110,30),pos=(275,0))
|
||||||
try:
|
try:
|
||||||
self.baud.SetValue("115200")
|
self.baud.SetValue("115200")
|
||||||
self.baud.SetValue(str(self.settings.baudrate))
|
self.baud.SetValue(str(self.settings.baudrate))
|
||||||
|
@ -510,14 +492,20 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
lls=self.lowerlsizer=wx.GridBagSizer()
|
lls=self.lowerlsizer=wx.GridBagSizer()
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(60,69)),pos=(0,4),span=(1,4))
|
lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(60,69)),pos=(0,4),span=(1,4))
|
||||||
self.xyfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.xy_feedrate),min=0,max=50000,size=(70,25),pos=(25,83))
|
self.xyfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.xy_feedrate),min=0,max=50000,size=(70,25),pos=(25,83))
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("XY:"),pos=(2,90-2)),pos=(1,0),span=(1,2))
|
lls.Add(wx.StaticText(self.panel,-1,_("XY:"),pos=(2,90-2)),pos=(1,3),span=(1,1), flag=wx.ALIGN_CENTER)
|
||||||
lls.Add(self.xyfeedc,pos=(1,2),span=(1,4))
|
lls.Add(self.xyfeedc,pos=(1,4),span=(1,2))
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("Z:"),pos=(90,90-2)),pos=(1,6),span=(1,2))
|
lls.Add(wx.StaticText(self.panel,-1,_("Z:"),pos=(90,90-2)),pos=(1,6),span=(1,1), flag=wx.ALIGN_CENTER)
|
||||||
self.zfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.z_feedrate),min=0,max=50000,size=(70,25),pos=(105,83))
|
self.zfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.z_feedrate),min=0,max=50000,size=(70,25),pos=(105,83))
|
||||||
lls.Add(self.zfeedc,pos=(1,8),span=(1,4))
|
lls.Add(self.zfeedc,pos=(1,7),span=(1,3))
|
||||||
|
|
||||||
#lls.Add((200,375))
|
#lls.Add((200,375))
|
||||||
|
|
||||||
|
self.xyb = XYButtons(self.panel, self.moveXY, self.homeButtonClicked)
|
||||||
|
lls.Add(self.xyb, pos=(2,0), span=(1,6), flag=wx.ALIGN_CENTER)
|
||||||
|
self.zb = ZButtons(self.panel, self.moveZ)
|
||||||
|
lls.Add(self.zb, pos=(2,7), span=(1,2), flag=wx.ALIGN_CENTER)
|
||||||
|
wx.CallAfter(self.xyb.SetFocus)
|
||||||
|
|
||||||
for i in self.cpbuttons:
|
for i in self.cpbuttons:
|
||||||
btn=wx.Button(self.panel,-1,i[0])#,size=(60,-1))
|
btn=wx.Button(self.panel,-1,i[0])#,size=(60,-1))
|
||||||
btn.SetBackgroundColour(i[3])
|
btn.SetBackgroundColour(i[3])
|
||||||
|
@ -529,45 +517,45 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
lls.Add(btn,pos=i[2],span=i[4])
|
lls.Add(btn,pos=i[2],span=i[4])
|
||||||
|
|
||||||
|
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("Heater:"),pos=(0,343)),pos=(11,0),span=(1,1))
|
lls.Add(wx.StaticText(self.panel,-1,_("Heater:"),pos=(0,343)),pos=(3,0),span=(1,1),flag=wx.ALIGN_CENTER)
|
||||||
htemp_choices=[self.temps[i]+" ("+i+")" for i in sorted(self.temps.keys(),key=lambda x:self.temps[x])]
|
htemp_choices=[self.temps[i]+" ("+i+")" for i in sorted(self.temps.keys(),key=lambda x:self.temps[x])]
|
||||||
|
|
||||||
self.settoff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),pos=(45,335))
|
self.settoff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),pos=(45,335))
|
||||||
self.settoff.Bind(wx.EVT_BUTTON,lambda e:self.do_settemp("off"))
|
self.settoff.Bind(wx.EVT_BUTTON,lambda e:self.do_settemp("off"))
|
||||||
self.printerControls.append(self.settoff)
|
self.printerControls.append(self.settoff)
|
||||||
lls.Add(self.settoff,pos=(11,1),span=(1,1))
|
lls.Add(self.settoff,pos=(3,1),span=(1,1))
|
||||||
|
|
||||||
if self.settings.last_temperature not in map(float,self.temps.values()):
|
if self.settings.last_temperature not in map(float,self.temps.values()):
|
||||||
htemp_choices = [str(self.settings.last_temperature)] + htemp_choices
|
htemp_choices = [str(self.settings.last_temperature)] + htemp_choices
|
||||||
self.htemp=wx.ComboBox(self.panel, -1,
|
self.htemp=wx.ComboBox(self.panel, -1,
|
||||||
choices=htemp_choices,style=wx.CB_DROPDOWN, size=(60,25),pos=(45,337))
|
choices=htemp_choices,style=wx.CB_DROPDOWN, size=(60,25),pos=(45,337))
|
||||||
self.htemp.Bind(wx.EVT_COMBOBOX,self.htemp_change)
|
self.htemp.Bind(wx.EVT_COMBOBOX,self.htemp_change)
|
||||||
lls.Add(self.htemp,pos=(11,2),span=(1,2))
|
|
||||||
|
|
||||||
|
lls.Add(self.htemp,pos=(3,2),span=(1,2))
|
||||||
self.settbtn=wx.Button(self.panel,-1,_("Set"),size=(36,-1),pos=(125,335))
|
self.settbtn=wx.Button(self.panel,-1,_("Set"),size=(36,-1),pos=(125,335))
|
||||||
self.settbtn.Bind(wx.EVT_BUTTON,self.do_settemp)
|
self.settbtn.Bind(wx.EVT_BUTTON,self.do_settemp)
|
||||||
self.printerControls.append(self.settbtn)
|
self.printerControls.append(self.settbtn)
|
||||||
lls.Add(self.settbtn,pos=(11,4),span=(1,2))
|
lls.Add(self.settbtn,pos=(3,4),span=(1,1))
|
||||||
|
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("Bed:"),pos=(0,343)),pos=(12,0),span=(1,1))
|
lls.Add(wx.StaticText(self.panel,-1,_("Bed:"),pos=(0,343)),pos=(4,0),span=(1,1),flag=wx.ALIGN_CENTER)
|
||||||
btemp_choices=[self.bedtemps[i]+" ("+i+")" for i in sorted(self.bedtemps.keys(),key=lambda x:self.temps[x])]
|
btemp_choices=[self.bedtemps[i]+" ("+i+")" for i in sorted(self.bedtemps.keys(),key=lambda x:self.temps[x])]
|
||||||
|
|
||||||
self.setboff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),pos=(135,335))
|
self.setboff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),pos=(135,335))
|
||||||
self.setboff.Bind(wx.EVT_BUTTON,lambda e:self.do_bedtemp("off"))
|
self.setboff.Bind(wx.EVT_BUTTON,lambda e:self.do_bedtemp("off"))
|
||||||
self.printerControls.append(self.setboff)
|
self.printerControls.append(self.setboff)
|
||||||
lls.Add(self.setboff,pos=(12,1),span=(1,1))
|
lls.Add(self.setboff,pos=(4,1),span=(1,1))
|
||||||
|
|
||||||
if self.settings.last_bed_temperature not in map(float,self.bedtemps.values()):
|
if self.settings.last_bed_temperature not in map(float,self.bedtemps.values()):
|
||||||
btemp_choices = [str(self.settings.last_bed_temperature)] + btemp_choices
|
btemp_choices = [str(self.settings.last_bed_temperature)] + btemp_choices
|
||||||
self.btemp=wx.ComboBox(self.panel, -1,
|
self.btemp=wx.ComboBox(self.panel, -1,
|
||||||
choices=btemp_choices,style=wx.CB_DROPDOWN, size=(60,25),pos=(135,367))
|
choices=btemp_choices,style=wx.CB_DROPDOWN, size=(60,25),pos=(135,367))
|
||||||
self.btemp.Bind(wx.EVT_COMBOBOX,self.btemp_change)
|
self.btemp.Bind(wx.EVT_COMBOBOX,self.btemp_change)
|
||||||
lls.Add(self.btemp,pos=(12,2),span=(1,2))
|
lls.Add(self.btemp,pos=(4,2),span=(1,2))
|
||||||
|
|
||||||
self.setbbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),pos=(135,365))
|
self.setbbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),pos=(135,365))
|
||||||
self.setbbtn.Bind(wx.EVT_BUTTON,self.do_bedtemp)
|
self.setbbtn.Bind(wx.EVT_BUTTON,self.do_bedtemp)
|
||||||
self.printerControls.append(self.setbbtn)
|
self.printerControls.append(self.setbbtn)
|
||||||
lls.Add(self.setbbtn,pos=(12,4),span=(1,2))
|
lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
|
||||||
|
|
||||||
self.btemp.SetValue(str(self.settings.last_bed_temperature))
|
self.btemp.SetValue(str(self.settings.last_bed_temperature))
|
||||||
self.htemp.SetValue(str(self.settings.last_temperature))
|
self.htemp.SetValue(str(self.settings.last_temperature))
|
||||||
|
@ -588,25 +576,27 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
if( '(' not in self.htemp.Value):
|
if( '(' not in self.htemp.Value):
|
||||||
self.htemp.SetValue(self.htemp.Value + ' (user)')
|
self.htemp.SetValue(self.htemp.Value + ' (user)')
|
||||||
|
|
||||||
|
#lls.Add(self.btemp,pos=(4,1),span=(1,3))
|
||||||
|
#lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
|
||||||
self.tempdisp=wx.StaticText(self.panel,-1,"")
|
self.tempdisp=wx.StaticText(self.panel,-1,"")
|
||||||
lls.Add(self.tempdisp,pos=(12,6),span=(1,3))
|
lls.Add(self.tempdisp,pos=(4,6),span=(1,3))
|
||||||
|
|
||||||
self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,25),pos=(70,398))
|
self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,25),pos=(70,398))
|
||||||
self.edist.SetBackgroundColour((225,200,200))
|
self.edist.SetBackgroundColour((225,200,200))
|
||||||
self.edist.SetForegroundColour("black")
|
self.edist.SetForegroundColour("black")
|
||||||
lls.Add(self.edist,pos=(13,3),span=(1,2))
|
lls.Add(self.edist,pos=(5,2),span=(1,1))
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("mm"),pos=(130,407)),pos=(13,5),span=(1,2))
|
lls.Add(wx.StaticText(self.panel,-1,_("mm"),pos=(130,407)),pos=(5,3),span=(1,2))
|
||||||
self.efeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.e_feedrate),min=0,max=50000,size=(60,25),pos=(70,397+28))
|
self.efeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.e_feedrate),min=0,max=50000,size=(60,25),pos=(70,397+28))
|
||||||
self.efeedc.SetBackgroundColour((225,200,200))
|
self.efeedc.SetBackgroundColour((225,200,200))
|
||||||
self.efeedc.SetForegroundColour("black")
|
self.efeedc.SetForegroundColour("black")
|
||||||
self.efeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
|
self.efeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
|
||||||
lls.Add(self.efeedc,pos=(14,3),span=(1,2))
|
lls.Add(self.efeedc,pos=(6,2),span=(1,1))
|
||||||
lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(130,407+27)),pos=(14,5),span=(1,2))
|
lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(130,407+27)),pos=(6,3),span=(1,2))
|
||||||
self.xyfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
|
self.xyfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
|
||||||
self.zfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
|
self.zfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
|
||||||
self.zfeedc.SetBackgroundColour((180,255,180))
|
self.zfeedc.SetBackgroundColour((180,255,180))
|
||||||
self.zfeedc.SetForegroundColour("black")
|
self.zfeedc.SetForegroundColour("black")
|
||||||
lls.Add((10,0),pos=(0,11),span=(1,1))
|
# lls.Add((10,0),pos=(0,11),span=(1,1))
|
||||||
self.gviz=gviz.gviz(self.panel,(300,300),
|
self.gviz=gviz.gviz(self.panel,(300,300),
|
||||||
bedsize=(self.settings.bed_size_x,self.settings.bed_size_y),
|
bedsize=(self.settings.bed_size_x,self.settings.bed_size_y),
|
||||||
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
|
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
|
||||||
|
@ -620,7 +610,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
self.gwindow.Bind(wx.EVT_CLOSE,lambda x:self.gwindow.Hide())
|
self.gwindow.Bind(wx.EVT_CLOSE,lambda x:self.gwindow.Hide())
|
||||||
cs=self.centersizer=wx.GridBagSizer()
|
cs=self.centersizer=wx.GridBagSizer()
|
||||||
cs.Add(self.gviz,pos=(0,0),span=(1,3))
|
cs.Add(self.gviz,pos=(0,0),span=(1,3))
|
||||||
lls.Add(cs,pos=(0,10),span=(15,1))
|
lls.Add(cs,pos=(0,10),span=(8,1))
|
||||||
|
|
||||||
self.uppersizer=wx.BoxSizer(wx.VERTICAL)
|
self.uppersizer=wx.BoxSizer(wx.VERTICAL)
|
||||||
self.uppersizer.Add(self.uppertopsizer)
|
self.uppersizer.Add(self.uppertopsizer)
|
||||||
|
@ -973,6 +963,26 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
else:
|
else:
|
||||||
e.Skip()
|
e.Skip()
|
||||||
|
|
||||||
|
def homeButtonClicked(self, corner):
|
||||||
|
if corner == 0: # upper-left
|
||||||
|
self.onecmd('home X')
|
||||||
|
if corner == 1: # upper-right
|
||||||
|
self.onecmd('home Y')
|
||||||
|
if corner == 2: # lower-right
|
||||||
|
self.onecmd('home Z')
|
||||||
|
if corner == 3: # lower-left
|
||||||
|
self.onecmd('home')
|
||||||
|
|
||||||
|
def moveXY(self, x, y):
|
||||||
|
if x != 0:
|
||||||
|
self.onecmd('move X %s' % x)
|
||||||
|
if y != 0:
|
||||||
|
self.onecmd('move Y %s' % y)
|
||||||
|
|
||||||
|
def moveZ(self, z):
|
||||||
|
if z != 0:
|
||||||
|
self.onecmd('move Z %s' % z)
|
||||||
|
|
||||||
def procbutton(self,e):
|
def procbutton(self,e):
|
||||||
try:
|
try:
|
||||||
if hasattr(e.GetEventObject(),"custombutton"):
|
if hasattr(e.GetEventObject(),"custombutton"):
|
||||||
|
@ -1380,6 +1390,10 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
|
||||||
for i in self.printerControls:
|
for i in self.printerControls:
|
||||||
wx.CallAfter(i.Disable)
|
wx.CallAfter(i.Disable)
|
||||||
|
|
||||||
|
# Disable XYButtons and ZButtons
|
||||||
|
self.xyb.disable()
|
||||||
|
self.zb.disable()
|
||||||
|
|
||||||
if self.paused:
|
if self.paused:
|
||||||
self.p.paused=0
|
self.p.paused=0
|
||||||
self.p.printing=0
|
self.p.printing=0
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import wx, os, math
|
||||||
|
from bufferedcanvas import *
|
||||||
|
|
||||||
|
from xybuttons import XYButtons
|
||||||
|
from zbuttons import ZButtons
|
||||||
|
|
||||||
|
class MyFrame(wx.Frame):
|
||||||
|
def __init__(self, parent, id, title):
|
||||||
|
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(600, 400))
|
||||||
|
sizer = wx.BoxSizer()
|
||||||
|
self.xy = XYButtons(self, moveCallback=self.moveXY)
|
||||||
|
sizer.Add(self.xy, flag=wx.ALIGN_CENTER)
|
||||||
|
self.z = ZButtons(self, moveCallback=self.moveZ)
|
||||||
|
sizer.Add(self.z, flag=wx.ALIGN_CENTER)
|
||||||
|
|
||||||
|
self.SetSizer(sizer)
|
||||||
|
self.SetBackgroundColour("white")
|
||||||
|
|
||||||
|
def moveXY(self, x, y):
|
||||||
|
print "got x", x, 'y', y
|
||||||
|
|
||||||
|
def moveZ(self, z):
|
||||||
|
print "got z", z
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(wx.App):
|
||||||
|
def OnInit(self):
|
||||||
|
frame = MyFrame(None, -1, 'test.py')
|
||||||
|
frame.Show(True)
|
||||||
|
frame.Centre()
|
||||||
|
return True
|
||||||
|
|
||||||
|
app = MyApp(0)
|
||||||
|
app.MainLoop()
|
|
@ -0,0 +1,330 @@
|
||||||
|
import wx, os, math
|
||||||
|
from bufferedcanvas import *
|
||||||
|
|
||||||
|
def imagefile(filename):
|
||||||
|
return os.path.join(os.path.dirname(__file__), "images", filename)
|
||||||
|
|
||||||
|
def sign(n):
|
||||||
|
if n < 0: return -1
|
||||||
|
elif n > 0: return 1
|
||||||
|
else: return 0
|
||||||
|
|
||||||
|
class XYButtons(BufferedCanvas):
|
||||||
|
keypad_positions = {
|
||||||
|
0: (105, 102),
|
||||||
|
1: (86, 83),
|
||||||
|
2: (68, 65),
|
||||||
|
3: (53, 50)
|
||||||
|
}
|
||||||
|
corner_size = (49, 49)
|
||||||
|
corner_inset = (8, 6)
|
||||||
|
label_overlay_positions = {
|
||||||
|
0: (142, 105, 11),
|
||||||
|
1: (160, 85, 13),
|
||||||
|
2: (179, 65, 15),
|
||||||
|
3: (201, 42, 16)
|
||||||
|
}
|
||||||
|
concentric_circle_radii = [11, 45, 69, 94, 115]
|
||||||
|
center = (124, 121)
|
||||||
|
spacer = 7
|
||||||
|
|
||||||
|
def __init__(self, parent, moveCallback=None, cornerCallback=None, ID=-1):
|
||||||
|
self.bg_bmp = wx.Image(imagefile("control_xy.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
||||||
|
self.keypad_bmp = wx.Image(imagefile("arrow_keys.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
||||||
|
self.keypad_idx = -1
|
||||||
|
self.quadrant = None
|
||||||
|
self.concentric = None
|
||||||
|
self.corner = None
|
||||||
|
self.moveCallback = moveCallback
|
||||||
|
self.cornerCallback = cornerCallback
|
||||||
|
self.enabled = False
|
||||||
|
|
||||||
|
BufferedCanvas.__init__(self, parent, ID)
|
||||||
|
|
||||||
|
self.SetSize(self.bg_bmp.GetSize())
|
||||||
|
|
||||||
|
# Set up mouse and keyboard event capture
|
||||||
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
||||||
|
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
|
||||||
|
self.Bind(wx.EVT_MOTION, self.OnMotion)
|
||||||
|
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
|
||||||
|
self.Bind(wx.EVT_KEY_UP, self.OnKey)
|
||||||
|
wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey)
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
self.enabled = False
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
self.enabled = True
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def distanceToLine(self, pos, x1, y1, x2, y2):
|
||||||
|
xlen = x2 - x1
|
||||||
|
ylen = y2 - y1
|
||||||
|
pxlen = x1 - pos.x
|
||||||
|
pylen = y1 - pos.y
|
||||||
|
return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2)
|
||||||
|
|
||||||
|
def distanceToPoint(self, x1, y1, x2, y2):
|
||||||
|
return math.sqrt((x1-x2)**2 + (y1-y2)**2)
|
||||||
|
|
||||||
|
def cycleKeypadIndex(self):
|
||||||
|
idx = self.keypad_idx + 1
|
||||||
|
if idx > 2: idx = 0
|
||||||
|
return idx
|
||||||
|
|
||||||
|
def setKeypadIndex(self, idx):
|
||||||
|
self.keypad_idx = idx
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def getMovement(self):
|
||||||
|
xdir = [1, 0, -1, 0][self.quadrant]
|
||||||
|
ydir = [0, 1, 0, -1][self.quadrant]
|
||||||
|
magnitude = math.pow(10, self.concentric-1)
|
||||||
|
return (magnitude * xdir, magnitude * ydir)
|
||||||
|
|
||||||
|
def lookupConcentric(self, radius):
|
||||||
|
idx = 0
|
||||||
|
for r in XYButtons.concentric_circle_radii[1:]:
|
||||||
|
if radius < r:
|
||||||
|
return idx
|
||||||
|
idx += 1
|
||||||
|
return len(XYButtons.concentric_circle_radii)
|
||||||
|
|
||||||
|
def getQuadrantConcentricFromPosition(self, pos):
|
||||||
|
rel_x = pos[0] - XYButtons.center[0]
|
||||||
|
rel_y = pos[1] - XYButtons.center[1]
|
||||||
|
radius = math.sqrt(rel_x**2 + rel_y**2)
|
||||||
|
if rel_x > rel_y and rel_x > -rel_y:
|
||||||
|
quadrant = 0 # Right
|
||||||
|
elif rel_x <= rel_y and rel_x > -rel_y:
|
||||||
|
quadrant = 3 # Down
|
||||||
|
elif rel_x > rel_y and rel_x < -rel_y:
|
||||||
|
quadrant = 1 # Up
|
||||||
|
else:
|
||||||
|
quadrant = 2 # Left
|
||||||
|
|
||||||
|
idx = self.lookupConcentric(radius)
|
||||||
|
return (quadrant, idx)
|
||||||
|
|
||||||
|
def mouseOverKeypad(self, mpos):
|
||||||
|
for idx, kpos in XYButtons.keypad_positions.items():
|
||||||
|
radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1])
|
||||||
|
if radius < 9:
|
||||||
|
return idx
|
||||||
|
return None
|
||||||
|
|
||||||
|
def drawPartialPie(self, gc, center, r1, r2, angle1, angle2):
|
||||||
|
p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1))
|
||||||
|
|
||||||
|
path = gc.CreatePath()
|
||||||
|
path.MoveToPoint(p1.x, p1.y)
|
||||||
|
path.AddArc(center.x, center.y, r1, angle1, angle2, True)
|
||||||
|
path.AddArc(center.x, center.y, r2, angle2, angle1, False)
|
||||||
|
path.AddLineToPoint(p1.x, p1.y)
|
||||||
|
gc.DrawPath(path)
|
||||||
|
|
||||||
|
def highlightQuadrant(self, gc, quadrant, concentric):
|
||||||
|
assert(quadrant >= 0 and quadrant <= 3)
|
||||||
|
assert(concentric >= 0 and concentric <= 3)
|
||||||
|
|
||||||
|
inner_ring_radius = XYButtons.concentric_circle_radii[0]
|
||||||
|
# fudge = math.pi*0.002
|
||||||
|
fudge = -0.02
|
||||||
|
center = wx.Point(XYButtons.center[0], XYButtons.center[1])
|
||||||
|
if quadrant == 0:
|
||||||
|
a1, a2 = (-math.pi*0.25, math.pi*0.25)
|
||||||
|
center.x += inner_ring_radius
|
||||||
|
elif quadrant == 1:
|
||||||
|
a1, a2 = (math.pi*1.25, math.pi*1.75)
|
||||||
|
center.y -= inner_ring_radius
|
||||||
|
elif quadrant == 2:
|
||||||
|
a1, a2 = (math.pi*0.75, math.pi*1.25)
|
||||||
|
center.x -= inner_ring_radius
|
||||||
|
elif quadrant == 3:
|
||||||
|
a1, a2 = (math.pi*0.25, math.pi*0.75)
|
||||||
|
center.y += inner_ring_radius
|
||||||
|
|
||||||
|
r1 = XYButtons.concentric_circle_radii[concentric]
|
||||||
|
r2 = XYButtons.concentric_circle_radii[concentric+1]
|
||||||
|
|
||||||
|
self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
|
||||||
|
|
||||||
|
def drawCorner(self, gc, x, y, angle=0.0):
|
||||||
|
w, h = XYButtons.corner_size
|
||||||
|
|
||||||
|
gc.PushState()
|
||||||
|
gc.Translate(x, y)
|
||||||
|
gc.Rotate(angle)
|
||||||
|
path = gc.CreatePath()
|
||||||
|
path.MoveToPoint(-w/2, -h/2)
|
||||||
|
path.AddLineToPoint(w/2, -h/2)
|
||||||
|
path.AddLineToPoint(w/2, -h/2+h/3)
|
||||||
|
path.AddLineToPoint(-w/2+w/3, h/2)
|
||||||
|
path.AddLineToPoint(-w/2, h/2)
|
||||||
|
path.AddLineToPoint(-w/2, -h/2)
|
||||||
|
gc.DrawPath(path)
|
||||||
|
gc.PopState()
|
||||||
|
|
||||||
|
def highlightCorner(self, gc, corner=0):
|
||||||
|
w, h = XYButtons.corner_size
|
||||||
|
cx, cy = XYButtons.center
|
||||||
|
ww, wh = self.GetSizeTuple()
|
||||||
|
|
||||||
|
inset = 10
|
||||||
|
if corner == 0:
|
||||||
|
x, y = (cx - ww/2 + inset, cy - wh/2 + inset)
|
||||||
|
self.drawCorner(gc, x+w/2, y+h/2, 0)
|
||||||
|
elif corner == 1:
|
||||||
|
x, y = (cx + ww/2 - inset, cy - wh/2 + inset)
|
||||||
|
self.drawCorner(gc, x-w/2, y+h/2, math.pi/2)
|
||||||
|
elif corner == 2:
|
||||||
|
x, y = (cx + ww/2 - inset, cy + wh/2 - inset)
|
||||||
|
self.drawCorner(gc, x-w/2, y-h/2, math.pi)
|
||||||
|
elif corner == 3:
|
||||||
|
x, y = (cx - ww/2 + inset, cy + wh/2 - inset)
|
||||||
|
self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2)
|
||||||
|
|
||||||
|
|
||||||
|
def draw(self, dc, w, h):
|
||||||
|
dc.Clear()
|
||||||
|
gc = wx.GraphicsContext.Create(dc)
|
||||||
|
|
||||||
|
center = wx.Point(XYButtons.center[0], XYButtons.center[1])
|
||||||
|
w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
|
||||||
|
gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
|
||||||
|
|
||||||
|
if self.enabled:
|
||||||
|
# Brush and pen for grey overlay when mouse hovers over
|
||||||
|
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
|
||||||
|
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128)))
|
||||||
|
|
||||||
|
if self.concentric != None:
|
||||||
|
if self.concentric < len(XYButtons.concentric_circle_radii):
|
||||||
|
if self.quadrant != None:
|
||||||
|
self.highlightQuadrant(gc, self.quadrant, self.concentric)
|
||||||
|
elif self.corner != None:
|
||||||
|
self.highlightCorner(gc, self.corner)
|
||||||
|
|
||||||
|
if self.keypad_idx >= 0:
|
||||||
|
padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight())
|
||||||
|
pos = XYButtons.keypad_positions[self.keypad_idx]
|
||||||
|
pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3)
|
||||||
|
gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh)
|
||||||
|
|
||||||
|
# Draw label overlays
|
||||||
|
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1))
|
||||||
|
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64)))
|
||||||
|
for idx, kpos in XYButtons.label_overlay_positions.items():
|
||||||
|
if idx != self.concentric:
|
||||||
|
r = kpos[2]
|
||||||
|
gc.DrawEllipse(kpos[0]-r, kpos[1]-r, r*2, r*2)
|
||||||
|
else:
|
||||||
|
gc.SetPen(wx.Pen(wx.Colour(255,255,255,0), 4))
|
||||||
|
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128)))
|
||||||
|
gc.DrawRectangle(0, 0, w, h)
|
||||||
|
|
||||||
|
|
||||||
|
# Used to check exact position of keypad dots, should we ever resize the bg image
|
||||||
|
# for idx, kpos in XYButtons.label_overlay_positions.items():
|
||||||
|
# dc.DrawCircle(kpos[0], kpos[1], kpos[2])
|
||||||
|
|
||||||
|
## ------ ##
|
||||||
|
## Events ##
|
||||||
|
## ------ ##
|
||||||
|
|
||||||
|
def OnTopLevelKey(self, evt):
|
||||||
|
# Let user press escape on any control, and return focus here
|
||||||
|
if evt.GetKeyCode() == wx.WXK_ESCAPE:
|
||||||
|
self.SetFocus()
|
||||||
|
evt.Skip()
|
||||||
|
|
||||||
|
def OnKey(self, evt):
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
if self.keypad_idx >= 0:
|
||||||
|
if evt.GetKeyCode() == wx.WXK_TAB:
|
||||||
|
self.setKeypadIndex(self.cycleKeypadIndex())
|
||||||
|
elif evt.GetKeyCode() == wx.WXK_UP:
|
||||||
|
self.quadrant = 1
|
||||||
|
elif evt.GetKeyCode() == wx.WXK_DOWN:
|
||||||
|
self.quadrant = 3
|
||||||
|
elif evt.GetKeyCode() == wx.WXK_LEFT:
|
||||||
|
self.quadrant = 2
|
||||||
|
elif evt.GetKeyCode() == wx.WXK_RIGHT:
|
||||||
|
self.quadrant = 0
|
||||||
|
else:
|
||||||
|
evt.Skip()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.moveCallback:
|
||||||
|
self.concentric = self.keypad_idx
|
||||||
|
x, y = self.getMovement()
|
||||||
|
self.moveCallback(x, y)
|
||||||
|
|
||||||
|
def OnMotion(self, event):
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
oldcorner = self.corner
|
||||||
|
oldq, oldc = self.quadrant, self.concentric
|
||||||
|
|
||||||
|
mpos = event.GetPosition()
|
||||||
|
idx = self.mouseOverKeypad(mpos)
|
||||||
|
self.quadrant = None
|
||||||
|
self.concentric = None
|
||||||
|
if idx == None:
|
||||||
|
center = wx.Point(XYButtons.center[0], XYButtons.center[1])
|
||||||
|
riseDist = self.distanceToLine(mpos, center.x-1, center.y-1, center.x+1, center.y+1)
|
||||||
|
fallDist = self.distanceToLine(mpos, center.x-1, center.y+1, center.x+1, center.y-1)
|
||||||
|
self.quadrant, self.concentric = self.getQuadrantConcentricFromPosition(mpos)
|
||||||
|
|
||||||
|
# If mouse hovers in space between quadrants, don't commit to a quadrant
|
||||||
|
if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer:
|
||||||
|
self.quadrant = None
|
||||||
|
|
||||||
|
cx, cy = XYButtons.center
|
||||||
|
if mpos.x < cx and mpos.y < cy:
|
||||||
|
self.corner = 0
|
||||||
|
if mpos.x >= cx and mpos.y < cy:
|
||||||
|
self.corner = 1
|
||||||
|
if mpos.x >= cx and mpos.y >= cy:
|
||||||
|
self.corner = 2
|
||||||
|
if mpos.x < cx and mpos.y >= cy:
|
||||||
|
self.corner = 3
|
||||||
|
|
||||||
|
if oldq != self.quadrant or oldc != self.concentric or oldcorner != self.corner:
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def OnLeftDown(self, event):
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Take focus when clicked so that arrow keys can control movement
|
||||||
|
self.SetFocus()
|
||||||
|
|
||||||
|
mpos = event.GetPosition()
|
||||||
|
|
||||||
|
idx = self.mouseOverKeypad(mpos)
|
||||||
|
if idx == None:
|
||||||
|
self.quadrant, self.concentric = self.getQuadrantConcentricFromPosition(mpos)
|
||||||
|
if self.concentric != None:
|
||||||
|
if self.concentric < len(XYButtons.concentric_circle_radii):
|
||||||
|
if self.quadrant != None:
|
||||||
|
x, y = self.getMovement()
|
||||||
|
if self.moveCallback:
|
||||||
|
self.moveCallback(x, y)
|
||||||
|
elif self.corner != None:
|
||||||
|
if self.cornerCallback:
|
||||||
|
self.cornerCallback(self.corner)
|
||||||
|
else:
|
||||||
|
if self.keypad_idx == idx:
|
||||||
|
self.setKeypadIndex(-1)
|
||||||
|
else:
|
||||||
|
self.setKeypadIndex(idx)
|
||||||
|
|
||||||
|
def OnLeaveWindow(self, evt):
|
||||||
|
self.quadrant = None
|
||||||
|
self.concentric = None
|
||||||
|
self.update()
|
|
@ -0,0 +1,131 @@
|
||||||
|
import wx, os, math
|
||||||
|
from bufferedcanvas import *
|
||||||
|
|
||||||
|
def imagefile(filename):
|
||||||
|
return os.path.join(os.path.dirname(__file__), "images", filename)
|
||||||
|
|
||||||
|
def sign(n):
|
||||||
|
if n < 0: return -1
|
||||||
|
elif n > 0: return 1
|
||||||
|
else: return 0
|
||||||
|
|
||||||
|
class ZButtons(BufferedCanvas):
|
||||||
|
button_ydistances = [7, 30, 55, 83, 112]
|
||||||
|
center = (30, 118)
|
||||||
|
label_overlay_positions = {
|
||||||
|
0: (1, 18, 11),
|
||||||
|
1: (1, 41, 13),
|
||||||
|
2: (1, 67, 15),
|
||||||
|
3: None
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, parent, moveCallback=None, ID=-1):
|
||||||
|
self.bg_bmp = wx.Image(imagefile("control_z.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
||||||
|
self.range = None
|
||||||
|
self.direction = None
|
||||||
|
self.orderOfMagnitudeIdx = 0 # 0 means '1', 1 means '10', 2 means '100', etc.
|
||||||
|
self.moveCallback = moveCallback
|
||||||
|
self.enabled = False
|
||||||
|
|
||||||
|
BufferedCanvas.__init__(self, parent, ID)
|
||||||
|
|
||||||
|
self.SetSize(wx.Size(59, 244))
|
||||||
|
|
||||||
|
# Set up mouse and keyboard event capture
|
||||||
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
||||||
|
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
|
||||||
|
self.Bind(wx.EVT_MOTION, self.OnMotion)
|
||||||
|
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
self.enabled = False
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
self.enabled = True
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def lookupRange(self, ydist):
|
||||||
|
idx = -1
|
||||||
|
for d in ZButtons.button_ydistances:
|
||||||
|
if ydist < d:
|
||||||
|
return idx
|
||||||
|
idx += 1
|
||||||
|
return None
|
||||||
|
|
||||||
|
def highlight(self, gc, rng, dir):
|
||||||
|
assert(rng >= -1 and rng <= 3)
|
||||||
|
assert(dir >= -1 and dir <= 1)
|
||||||
|
|
||||||
|
fudge = 11
|
||||||
|
x = 0 + fudge
|
||||||
|
w = 59 - fudge*2
|
||||||
|
if rng >= 0:
|
||||||
|
k = 1 if dir > 0 else 0
|
||||||
|
y = ZButtons.center[1] - (dir * ZButtons.button_ydistances[rng+k])
|
||||||
|
h = ZButtons.button_ydistances[rng+1] - ZButtons.button_ydistances[rng]
|
||||||
|
gc.DrawRoundedRectangle(x, y, w, h, 4)
|
||||||
|
# gc.DrawRectangle(x, y, w, h)
|
||||||
|
# self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
|
||||||
|
|
||||||
|
def getRangeDir(self, pos):
|
||||||
|
ydelta = ZButtons.center[1] - pos[1]
|
||||||
|
return (self.lookupRange(abs(ydelta)), sign(ydelta))
|
||||||
|
|
||||||
|
def draw(self, dc, w, h):
|
||||||
|
dc.Clear()
|
||||||
|
gc = wx.GraphicsContext.Create(dc)
|
||||||
|
w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
|
||||||
|
|
||||||
|
gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
|
||||||
|
|
||||||
|
if self.enabled:
|
||||||
|
# Draw label overlays
|
||||||
|
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1))
|
||||||
|
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64)))
|
||||||
|
for idx, kpos in ZButtons.label_overlay_positions.items():
|
||||||
|
if kpos and idx != self.range:
|
||||||
|
r = kpos[2]
|
||||||
|
gc.DrawEllipse(ZButtons.center[0]-kpos[0]-r, ZButtons.center[1]-kpos[1]-r, r*2, r*2)
|
||||||
|
|
||||||
|
# Top 'layer' is the mouse-over highlights
|
||||||
|
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
|
||||||
|
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128)))
|
||||||
|
if self.range != None and self.direction != None:
|
||||||
|
self.highlight(gc, self.range, self.direction)
|
||||||
|
else:
|
||||||
|
gc.SetPen(wx.Pen(wx.Colour(255,255,255,0), 4))
|
||||||
|
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128)))
|
||||||
|
gc.DrawRectangle(0, 0, w, h)
|
||||||
|
|
||||||
|
## ------ ##
|
||||||
|
## Events ##
|
||||||
|
## ------ ##
|
||||||
|
|
||||||
|
def OnMotion(self, event):
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
oldr, oldd = self.range, self.direction
|
||||||
|
|
||||||
|
mpos = event.GetPosition()
|
||||||
|
self.range, self.direction = self.getRangeDir(mpos)
|
||||||
|
|
||||||
|
if oldr != self.range or oldd != self.direction:
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def OnLeftDown(self, event):
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
mpos = event.GetPosition()
|
||||||
|
r, d = self.getRangeDir(mpos)
|
||||||
|
if r >= 0:
|
||||||
|
value = math.pow(10, self.orderOfMagnitudeIdx) * math.pow(10, r - 1) * d
|
||||||
|
if self.moveCallback:
|
||||||
|
self.moveCallback(value)
|
||||||
|
|
||||||
|
def OnLeaveWindow(self, evt):
|
||||||
|
self.range = None
|
||||||
|
self.direction = None
|
||||||
|
self.update()
|
Loading…
Reference in New Issue