Commit 48f82b90 authored by unknown's avatar unknown

Merge Complete

parents 94b5ddeb 97964293
# create a simple image slide show using the
# wx.PaintDC surface as a canvas and
# DrawBitmap(bitmap, x, y, bool transparent)
# Source: vegaseat
import wx
import os
import zipfile
import tempfile
import shutil
class MyFrame(wx.Frame):
def __init__(self, parent, mysize):
wx.Frame.__init__(self, parent, wx.ID_ANY, size=mysize)
self.SetBackgroundColour('black')
# milliseconds per frame
self.delay = 60
# number of loops
self.loops = 1
zipfilename = 'images/out.3dlp.zip'
if not zipfile.is_zipfile(zipfilename):
raise Exception(zipfilename + " is not a zip file!")
zip = zipfile.ZipFile(zipfilename, 'r')
self.mytmpdir = tempfile.mkdtemp()
zip.extractall(self.mytmpdir)
image_type = ".bmp"
image_dir = self.mytmpdir
file_list = []
self.name_list = []
for file in os.listdir(image_dir):
path = os.path.join(image_dir, file)
if os.path.isfile(path) and path.endswith(image_type):
# just the file name
self.name_list.append(file)
# full path name
file_list.append(path)
# create a list of image objects
self.image_list = []
for image_file in file_list:
self.image_list.append(wx.Bitmap(image_file))
# bind the panel to the paint event
wx.EVT_PAINT(self, self.onPaint)
def __del__(self):
if self.mytmpdir:
shutil.rmtree(self.mytmpdir)
def onPaint(self, event=None):
# this is the wxPython drawing surface/canvas
dc = wx.PaintDC(self)
while self.loops:
self.loops -= 1
for ix, bmp in enumerate(self.image_list):
# optionally show some image information
w, h = bmp.GetSize()
info = "%s %dx%d" % (self.name_list[ix], w, h)
self.SetTitle(info)
#self.SetSize((w,h))
# draw the image
dc.DrawBitmap(bmp, 0, 0, True)
wx.MilliSleep(self.delay)
# don't clear on fast slide shows to avoid flicker
if self.delay > 200:
dc.Clear()
app = wx.App()
width = 800
frameoffset = 35
height = 600 + frameoffset
MyFrame(None, (width, height)).Show()
app.MainLoop()
\ No newline at end of file
......@@ -30,7 +30,7 @@ class Graph(BufferedCanvas):
#super(Graph, self).__init__(parent, id, pos, size, style)
BufferedCanvas.__init__(self, parent, id)
self.SetSize(wx.Size(170, 100))
self.SetSize(wx.Size(150, 80))
self.extruder0temps = [0]
self.extruder0targettemps = [0]
......
......@@ -13,26 +13,73 @@
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx,time
ID_ABOUT = 101
ID_EXIT = 110
class window(wx.Frame):
def __init__(self,f,size=(600,600),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1]))
self.p=gviz(self,size=size,build_dimensions=build_dimensions,grid=grid,extrusion_width=extrusion_width)
# Set up a status bar for displaying info (Jezmy)
vbox = wx.BoxSizer(wx.VERTICAL)
toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
toolbar.AddSimpleTool(1, wx.Image('./images/zoom_in.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '')
toolbar.AddSimpleTool(2, wx.Image('./images/zoom_out.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom Out [-]', '')
toolbar.AddSeparator()
toolbar.AddSimpleTool(3, wx.Image('./images/arrow_up.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Up a Layer [U]', '')
toolbar.AddSimpleTool(4, wx.Image('./images/arrow_down.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Down a Layer [D]', '')
toolbar.AddSimpleTool(5, wx.EmptyBitmap(16,16), 'Reset view', '')
toolbar.AddSeparator()
#toolbar.AddSimpleTool(5, wx.Image('./images/inject.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Insert Code at start of this layer', '')
toolbar.Realize()
vbox.Add(toolbar, 0, border=5)
self.SetSizer(vbox)
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200,200,1.2), id=1)
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200,200,1/1.2), id=2)
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerup(), id=3)
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id=4)
self.Bind(wx.EVT_TOOL, self.resetview, id=5)
#self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id=5)
self.CreateStatusBar(1);
self.SetStatusText("Layer number and Z position show here when you scroll");
#self.bu=wx.Button(self.p,-1,"U",pos=(0,100),size=(40,140))
#self.bd=wx.Button(self.p,-1,"D",pos=(0,140),size=(40,140))
#self.bi=wx.Button(self.p,-1,"+",pos=(40,100),size=(40,140))
#self.bo=wx.Button(self.p,-1,"-",pos=(40,140),size=(40,140))
#self.bs=wx.Button(self.p, -1, "Inject", pos=(85, 103), size=(50, 20))
#self.bu.SetToolTip(wx.ToolTip("Move up one layer"))
#self.bd.SetToolTip(wx.ToolTip("Move down one layer"))
#self.bi.SetToolTip(wx.ToolTip("Zoom view in"))
#self.bo.SetToolTip(wx.ToolTip("Zoom view out"))
#self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer"))
#self.bu.Bind(wx.EVT_BUTTON,lambda x:self.p.layerup())
#self.bd.Bind(wx.EVT_BUTTON,lambda x:self.p.layerdown())
#self.bi.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1.2))
#self.bo.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1/1.2))
#self.bs.Bind(wx.EVT_BUTTON,lambda x:self.p.inject())
s=time.time()
#print time.time()-s
self.initpos=[0,0]
self.p.Bind(wx.EVT_KEY_DOWN,self.key)
#self.bu.Bind(wx.EVT_KEY_DOWN,self.key)
#self.bd.Bind(wx.EVT_KEY_DOWN,self.key)
#self.bi.Bind(wx.EVT_KEY_DOWN,self.key)
#self.bo.Bind(wx.EVT_KEY_DOWN,self.key)
self.Bind(wx.EVT_KEY_DOWN,self.key)
self.p.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
self.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
def resetview(self,event):
self.p.translate=[0.0,0.0]
self.p.scale=self.p.basescale
self.p.zoom(0,0,1.0)
def mouse(self,event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT):
if(self.initpos is not None):
......@@ -51,21 +98,33 @@ class window(wx.Frame):
else:
event.Skip()
def key(self, event):
# Keycode definitions
kup=[85, 315] # Up keys
kdo=[68, 317] # Down Keys
kzi=[388, 316, 61] # Zoom In Keys
kzo=[390, 314, 45] # Zoom Out Keys
x=event.GetKeyCode()
if event.ShiftDown():
#print "Key event - "+str(x)
#if event.ShiftDown():
cx,cy=self.p.translate
if x==wx.WXK_UP:
self.p.zoom(cx,cy,1.2)
if x==wx.WXK_DOWN:
self.p.zoom(cx,cy,1/1.2)
else:
if x==wx.WXK_UP:
# if x==wx.WXK_UP:
# self.p.zoom(cx,cy,1.2)
# if x==wx.WXK_DOWN:
# self.p.zoom(cx,cy,1/1.2)
#else:
# if x==wx.WXK_UP:
# self.p.layerup()
# if x==wx.WXK_DOWN:
# self.p.layerdown()
if x in kup:
self.p.layerup()
if x==wx.WXK_DOWN:
if x in kdo:
self.p.layerdown()
#print x
if x in kzi:
self.p.zoom(cx,cy,1.2)
if x in kzo:
self.p.zoom(cx, cy, 1/1.2)
#print p.lines.keys()
def zoom(self, event):
......@@ -111,6 +170,11 @@ class gviz(wx.Panel):
self.dirty=1
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
def inject(self):
#import pdb; pdb.set_trace()
print"Inject code here..."
print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm"
def clear(self):
self.lastpos=[0,0,0,0,0,0,0]
self.lines={}
......@@ -259,6 +323,8 @@ class gviz(wx.Panel):
def _readgcode():
target=self.lastpos[:]
target[5]=0.0
target[6]=0.0
if hilight:
target=self.hilightpos[:]
for i in gcode:
......
......@@ -248,7 +248,7 @@ class stlwin(wx.Frame):
self.SetIcon(wx.Icon("plater.ico", wx.BITMAP_TYPE_ICO))
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.panel = wx.Panel(self, -1, size=(150, 600), pos=(0, 0))
self.panel.SetBackgroundColour((10, 10, 10))
#self.panel.SetBackgroundColour((10, 10, 10))
self.l = wx.ListBox(self.panel, size=(300, 180), pos=(0, 30))
self.cl = wx.Button(self.panel, label=_("Clear"), pos=(0, 205))
self.lb = wx.Button(self.panel, label=_("Load"), pos=(0, 0))
......@@ -274,7 +274,7 @@ class stlwin(wx.Frame):
self.ab.Bind(wx.EVT_BUTTON, self.autoplate)
self.basedir = "."
self.models = {}
self.SetBackgroundColour((10, 10, 10))
#self.SetBackgroundColour((10, 10, 10))
self.mainsizer.Add(self.panel)
#self.mainsizer.AddSpacer(10)
if glview:
......
......@@ -226,6 +226,7 @@ class printcore():
pass
while(self.printing and self.printer and self.online):
self._sendnext()
self.sentlines={}
self.log=[]
self.sent=[]
if self.endcb is not None:
......@@ -248,7 +249,6 @@ class printcore():
self._send(self.sentlines[self.resendfrom],self.resendfrom,False)
self.resendfrom+=1
return
self.sentlines={}
self.resendfrom=-1
for i in self.priqueue[:]:
self._send(i)
......
This diff is collapsed.
......@@ -145,7 +145,7 @@ def estimate_duration(g):
y = get_coordinate_value("Y", parts[1:])
if y is None: y=lasty
z = get_coordinate_value("Z", parts[1:])
if z is None: z=lastz
if (z is None) or (z<lastz): z=lastz # Do not increment z if it's below the previous (Lift z on move fix)
e = get_coordinate_value("E", parts[1:])
if e is None: e=laste
f = get_coordinate_value("F", parts[1:])
......@@ -201,6 +201,7 @@ class Settings:
self.e_feedrate = 300
self.slicecommand="python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s"
self.sliceoptscommand="python skeinforge/skeinforge_application/skeinforge.py"
self.final_command = ""
def _set(self,key,value):
try:
......@@ -274,6 +275,7 @@ class pronsole(cmd.Cmd):
self.helpdict["temperature_pla"] = _("Extruder temp for PLA (default: 185 deg C)")
self.helpdict["xy_feedrate"] = _("Feedrate for Control Panel Moves in X and Y (default: 3000mm/min)")
self.helpdict["z_feedrate"] = _("Feedrate for Control Panel Moves in Z (default: 200mm/min)")
self.helpdict["final_command"] = _("Executable to run when the print is finished")
self.commandprefixes='MGT$'
def set_temp_preset(self,key,value):
......@@ -1114,7 +1116,7 @@ class pronsole(cmd.Cmd):
if(self.sdprinting):
self.p.send_now("M27")
time.sleep(interval)
print (self.tempreadings.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ",""))
#print (self.tempreadings.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ",""))
if(self.p.printing):
print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%"
......@@ -1151,14 +1153,14 @@ class pronsole(cmd.Cmd):
import shlex
if(settings):
param = self.expandcommand(self.settings.sliceoptscommand).replace("\\","\\\\").encode()
print "Entering skeinforge settings: ",param
print "Entering slicer settings: ",param
subprocess.call(shlex.split(param))
else:
param = self.expandcommand(self.settings.slicecommand).encode()
print "Slicing: ",param
params=[i.replace("$s",l[0]).replace("$o",l[0].replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() for i in shlex.split(param.replace("\\","\\\\").encode())]
subprocess.call(params)
print "Loading skeined file."
print "Loading sliced file."
self.do_load(l[0].replace(".stl","_export.gcode"))
except Exception,e:
print "Skeinforge execution failed: ",e
......@@ -1174,10 +1176,10 @@ class pronsole(cmd.Cmd):
return glob.glob("*/")+glob.glob("*.stl")
def help_skein(self):
print "Creates a gcode file from an stl model using skeinforge (with tab-completion)"
print "Creates a gcode file from an stl model using the slicer (with tab-completion)"
print "skein filename.stl - create gcode file"
print "skein filename.stl view - create gcode file and view using skeiniso"
print "skein set - adjust skeinforge settings"
print "skein set - adjust slicer settings"
def do_home(self,l):
......
This diff is collapsed.
......@@ -489,8 +489,8 @@ class TestGlPanel(GLPanel):
v = map(lambda m, w, b: b * m / w, p, sz, self.bedsize)
v[1] = self.bedsize[1] - v[1]
v += [300]
print v
self.add_file("../prusa/metric-prusa/x-end-idler.stl", v)
print "Double-click at "+str(v)+" in "
print self
def forceresize(self):
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
......
"""
"""
import wx
def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
""" Draws an arc of an ellipse within bounding rect (x,y,w,h)
from startArc to endArc (in radians, relative to the horizontal line of the eclipse)"""
if True:
import warnings
warnings.warn("elliptical arcs are not supported")
w = w/2.0
h = h/2.0
self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise)
return
else:
#implement in terms of AddArc by applying a transformation matrix
#Sigh this can't work, still need to patch wx to allow
#either a) AddPath that's not a closed path or
#b) allow pushing and popping of states on a path, not just on a context
#a) is possible in GDI+, need to investigate other renderers.
#b) is possible in Quartz and Cairo, but not in GDI+. It could
#possibly be simulated by combining the current transform with option a.
mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix()
path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
mtx.Translate(x+(w/2.0), y+(h/2.0))
mtx.Scale(w/2.0, y/2.0)
path.AddArc(0, 0, 1, startAngle, endAngle, clockwise)
path.Transform(mtx)
self.AddPath(path)
self.MoveToPoint(path.GetCurrentPoint())
self.CloseSubpath()
if not hasattr(wx.GraphicsPath, "AddEllipticalArc"):
wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc
del AddEllipticalArc
\ No newline at end of file
"""
Parsers for specific attributes
"""
import urlparse
from pyparsing import (Literal,
Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums,
CaselessLiteral, SkipTo
)
from css.colour import colourValue
import string
##Paint values
none = CaselessLiteral("none").setParseAction(lambda t: ["NONE", ()])
currentColor = CaselessLiteral("currentColor").setParseAction(lambda t: ["CURRENTCOLOR", ()])
def parsePossibleURL(t):
possibleURL, fallback = t[0]
return [urlparse.urlsplit(possibleURL), fallback]
#Normal color declaration
colorDeclaration = none | currentColor | colourValue
urlEnd = (
Literal(")").suppress() +
Optional(Group(colorDeclaration), default=()) +
StringEnd()
)
url = (
CaselessLiteral("URL")
+
Literal("(").suppress()+
Group(SkipTo(urlEnd, include=True).setParseAction(parsePossibleURL))
)
#paint value will parse into a (type, details) tuple.
#For none and currentColor, the details tuple will be the empty tuple
#for CSS color declarations, it will be (type, (R,G,B))
#for URLs, it will be ("URL", ((url tuple), fallback))
#The url tuple will be as returned by urlparse.urlsplit, and can be
#an empty tuple if the parser has an error
#The fallback will be another (type, details) tuple as a parsed
#colorDeclaration, but may be the empty tuple if it is not present
paintValue = url | colorDeclaration
from __future__ import absolute_import
from .transform import transformList
from .inline import inlineStyle
""" CSS at-rules"""
from pyparsing import Literal, Combine
from .identifier import identifier
atkeyword = Combine(Literal("@") + identifier)
\ No newline at end of file
"""
CSS blocks
"""
from pyparsing import nestedExpr
block = nestedExpr(opener="{", closer="}")
"""
Parsing for CSS colour values.
Supported formats:
hex literal short: #fff
hex literal long: #fafafa
rgb bytes: rgb(255,100,0)
rgb percent: rgb(100%,100%,0%)
named color: black
"""
import wx
import string
import urlparse
from pyparsing import nums, Literal, Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums
from ..pathdata import number, sign
number = number.copy()
integerConstant = Word(nums+"+-").setParseAction(lambda t:int(t[0]))
#rgb format parser
comma = Literal(",").suppress()
def clampColourByte(val):
val = int(val)
return min(max(0,val), 255)
def clampColourPerc(val):
val = float(val)
return min(max(0,val), 100)
def parseColorPerc(token):
val = token[0]
val = clampColourPerc(val)
#normalize to bytes
return int(255 * (val / 100.0))
colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0]))
colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress()
rgb = (
Literal("rgb(").setParseAction(lambda t: "RGB") +
(
#integer constants, ie 255,255,255
Group(colorByte + comma + colorByte + comma + colorByte) ^
#percentage values, ie 100%, 50%
Group(colorPerc + comma + colorPerc + comma + colorPerc)
)
+
Literal(")").suppress() + StringEnd()
)
def parseShortHex(t):
return tuple(int(x*2, 16) for x in t[0])
doubleHex = Word(hexnums, exact=2).setParseAction(lambda t: int(t[0], 16))
hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") +
(
Group(doubleHex + doubleHex + doubleHex) |
Word(hexnums, exact=3).setParseAction(parseShortHex)
) + StringEnd()
)
def parseNamedColour(t):
try:
return ["RGB", NamedColours[t[0].lower()]]
except KeyError:
return ["RGB", (0,0,0)]
namedColour = Word(alphas).setParseAction(parseNamedColour)
colourValue = rgb | hexLiteral | namedColour
##constants
NamedColours = {
#~ #html named colours
#~ "black":(0,0,0),
#~ "silver": (0xc0, 0xc0, 0xc0, 255),
#~ "gray": (0x80, 0x80, 0x80),
#~ "white":(255,255,255),
#~ "maroon":(0x80, 0, 0),
#~ "red":(0xff, 0, 0),
#~ "purple":(0x80, 0, 0x80),
#~ "fuchsia":(0xff, 0, 0xff),
#~ "green": (0, 0x80, 0),
#~ "lime": (0, 0xff, 0),
#~ "olive": (0x80, 0x80, 00),
#~ "yellow":(0xff, 0xff, 00),
#~ "navy": (0, 0, 0x80),
#~ "blue": (0, 0, 0xff),
#~ "teal": (0, 0x80, 0x80),
#~ "aqua": (0, 0xff, 0xff),
#expanded named colors from SVG spc
'aliceblue' : (240, 248, 255) ,
'antiquewhite' : (250, 235, 215) ,
'aqua' : ( 0, 255, 255) ,
'aquamarine' : (127, 255, 212) ,
'azure' : (240, 255, 255) ,
'beige' : (245, 245, 220) ,
'bisque' : (255, 228, 196) ,
'black' : ( 0, 0, 0) ,
'blanchedalmond' : (255, 235, 205) ,
'blue' : ( 0, 0, 255) ,
'blueviolet' : (138, 43, 226) ,
'brown' : (165, 42, 42) ,
'burlywood' : (222, 184, 135) ,
'cadetblue' : ( 95, 158, 160) ,
'chartreuse' : (127, 255, 0) ,
'chocolate' : (210, 105, 30) ,
'coral' : (255, 127, 80) ,
'cornflowerblue' : (100, 149, 237) ,
'cornsilk' : (255, 248, 220) ,
'crimson' : (220, 20, 60) ,
'cyan' : ( 0, 255, 255) ,
'darkblue' : ( 0, 0, 139) ,
'darkcyan' : ( 0, 139, 139) ,
'darkgoldenrod' : (184, 134, 11) ,
'darkgray' : (169, 169, 169) ,
'darkgreen' : ( 0, 100, 0) ,
'darkgrey' : (169, 169, 169) ,
'darkkhaki' : (189, 183, 107) ,
'darkmagenta' : (139, 0, 139) ,
'darkolivegreen' : ( 85, 107, 47) ,
'darkorange' : (255, 140, 0) ,
'darkorchid' : (153, 50, 204) ,
'darkred' : (139, 0, 0) ,
'darksalmon' : (233, 150, 122) ,
'darkseagreen' : (143, 188, 143) ,
'darkslateblue' : ( 72, 61, 139) ,
'darkslategray' : ( 47, 79, 79) ,
'darkslategrey' : ( 47, 79, 79) ,
'darkturquoise' : ( 0, 206, 209) ,
'darkviolet' : (148, 0, 211) ,
'deeppink' : (255, 20, 147) ,
'deepskyblue' : ( 0, 191, 255) ,
'dimgray' : (105, 105, 105) ,
'dimgrey' : (105, 105, 105) ,
'dodgerblue' : ( 30, 144, 255) ,
'firebrick' : (178, 34, 34) ,
'floralwhite' : (255, 250, 240) ,
'forestgreen' : ( 34, 139, 34) ,
'fuchsia' : (255, 0, 255) ,
'gainsboro' : (220, 220, 220) ,
'ghostwhite' : (248, 248, 255) ,
'gold' : (255, 215, 0) ,
'goldenrod' : (218, 165, 32) ,
'gray' : (128, 128, 128) ,
'grey' : (128, 128, 128) ,
'green' : ( 0, 128, 0) ,
'greenyellow' : (173, 255, 47) ,
'honeydew' : (240, 255, 240) ,
'hotpink' : (255, 105, 180) ,
'indianred' : (205, 92, 92) ,
'indigo' : ( 75, 0, 130) ,
'ivory' : (255, 255, 240) ,
'khaki' : (240, 230, 140) ,
'lavender' : (230, 230, 250) ,
'lavenderblush' : (255, 240, 245) ,
'lawngreen' : (124, 252, 0) ,
'lemonchiffon' : (255, 250, 205) ,
'lightblue' : (173, 216, 230) ,
'lightcoral' : (240, 128, 128) ,
'lightcyan' : (224, 255, 255) ,
'lightgoldenrodyellow' : (250, 250, 210) ,
'lightgray' : (211, 211, 211) ,
'lightgreen' : (144, 238, 144) ,
'lightgrey' : (211, 211, 211) ,
'lightpink' : (255, 182, 193) ,
'lightsalmon' : (255, 160, 122) ,
'lightseagreen' : ( 32, 178, 170) ,
'lightskyblue' : (135, 206, 250) ,
'lightslategray' : (119, 136, 153) ,
'lightslategrey' : (119, 136, 153) ,
'lightsteelblue' : (176, 196, 222) ,
'lightyellow' : (255, 255, 224) ,
'lime' : ( 0, 255, 0) ,
'limegreen' : ( 50, 205, 50) ,
'linen' : (250, 240, 230) ,
'magenta' : (255, 0, 255) ,
'maroon' : (128, 0, 0) ,
'mediumaquamarine' : (102, 205, 170) ,
'mediumblue' : ( 0, 0, 205) ,
'mediumorchid' : (186, 85, 211) ,
'mediumpurple' : (147, 112, 219) ,
'mediumseagreen' : ( 60, 179, 113) ,
'mediumslateblue' : (123, 104, 238) ,
'mediumspringgreen' : ( 0, 250, 154) ,
'mediumturquoise' : ( 72, 209, 204) ,
'mediumvioletred' : (199, 21, 133) ,
'midnightblue' : ( 25, 25, 112) ,
'mintcream' : (245, 255, 250) ,
'mistyrose' : (255, 228, 225) ,
'moccasin' : (255, 228, 181) ,
'navajowhite' : (255, 222, 173) ,
'navy' : ( 0, 0, 128) ,
'oldlace' : (253, 245, 230) ,
'olive' : (128, 128, 0) ,
'olivedrab' : (107, 142, 35) ,
'orange' : (255, 165, 0) ,
'orangered' : (255, 69, 0) ,
'orchid' : (218, 112, 214) ,
'palegoldenrod' : (238, 232, 170) ,
'palegreen' : (152, 251, 152) ,
'paleturquoise' : (175, 238, 238) ,
'palevioletred' : (219, 112, 147) ,
'papayawhip' : (255, 239, 213) ,
'peachpuff' : (255, 218, 185) ,
'peru' : (205, 133, 63) ,
'pink' : (255, 192, 203) ,
'plum' : (221, 160, 221) ,
'powderblue' : (176, 224, 230) ,
'purple' : (128, 0, 128) ,
'red' : (255, 0, 0) ,
'rosybrown' : (188, 143, 143) ,
'royalblue' : ( 65, 105, 225) ,
'saddlebrown' : (139, 69, 19) ,
'salmon' : (250, 128, 114) ,
'sandybrown' : (244, 164, 96) ,
'seagreen' : ( 46, 139, 87) ,
'seashell' : (255, 245, 238) ,
'sienna' : (160, 82, 45) ,
'silver' : (192, 192, 192) ,
'skyblue' : (135, 206, 235) ,
'slateblue' : (106, 90, 205) ,
'slategray' : (112, 128, 144) ,
'slategrey' : (112, 128, 144) ,
'snow' : (255, 250, 250) ,
'springgreen' : ( 0, 255, 127) ,
'steelblue' : ( 70, 130, 180) ,
'tan' : (210, 180, 140) ,
'teal' : ( 0, 128, 128) ,
'thistle' : (216, 191, 216) ,
'tomato' : (255, 99, 71) ,
'turquoise' : ( 64, 224, 208) ,
'violet' : (238, 130, 238) ,
'wheat' : (245, 222, 179) ,
'white' : (255, 255, 255) ,
'whitesmoke' : (245, 245, 245) ,
'yellow' : (255, 255, 0) ,
'yellowgreen' : (154, 205, 50) ,
}
def fillCSS2SystemColours():
#The system colours require a wxApp to be present to retrieve,
#so if you wnat support for them you'll need
#to call this function after your wxApp instance starts
systemColors = {
"ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER,
"ActiveCaption": wx.SYS_COLOUR_ACTIVECAPTION,
"AppWorkspace": wx.SYS_COLOUR_APPWORKSPACE,
"Background": wx.SYS_COLOUR_BACKGROUND,
"ButtonFace": wx.SYS_COLOUR_BTNFACE,
"ButtonHighlight": wx.SYS_COLOUR_BTNHIGHLIGHT,
"ButtonShadow": wx.SYS_COLOUR_BTNSHADOW,
"ButtonText": wx.SYS_COLOUR_BTNTEXT,
"CaptionText": wx.SYS_COLOUR_CAPTIONTEXT,
"GrayText": wx.SYS_COLOUR_GRAYTEXT,
"Highlight": wx.SYS_COLOUR_HIGHLIGHT,
"HighlightText": wx.SYS_COLOUR_HIGHLIGHTTEXT,
"InactiveBorder": wx.SYS_COLOUR_INACTIVEBORDER,
"InactiveCaption": wx.SYS_COLOUR_INACTIVECAPTION,
"InfoBackground": wx.SYS_COLOUR_INFOBK,
"InfoText": wx.SYS_COLOUR_INFOTEXT,
"Menu": wx.SYS_COLOUR_MENU,
"MenuText": wx.SYS_COLOUR_MENUTEXT,
"Scrollbar": wx.SYS_COLOUR_SCROLLBAR,
"ThreeDDarkShadow": wx.SYS_COLOUR_3DDKSHADOW,
"ThreeDFace": wx.SYS_COLOUR_3DFACE,
"ThreeDHighlight": wx.SYS_COLOUR_3DHIGHLIGHT,
"ThreeDLightShadow": wx.SYS_COLOUR_3DLIGHT,
"ThreeDShadow": wx.SYS_COLOUR_3DSHADOW,
"Window": wx.SYS_COLOUR_WINDOW,
"WindowFrame": wx.SYS_COLOUR_WINDOWFRAME,
"WindowText": wx.SYS_COLOUR_WINDOWTEXT
}
NamedColours.update(
#strip the alpha from the system colors. Is this really what we want to do?
(k.lower(), wx.SystemSettings.GetColour(v)[:3]) for (k,v) in systemColors.iteritems()
)
\ No newline at end of file
""" Parse CSS identifiers. More complicated than it sounds"""
from pyparsing import Word, Literal, Regex, Combine, Optional, White, oneOf, ZeroOrMore
import string
import re
class White(White):
""" Customize whitespace to match the CSS spec values"""
def __init__(self, ws=" \t\r\n\f", min=1, max=0, exact=0):
super(White, self).__init__(ws, min, max, exact)
escaped = (
Literal("\\").suppress() +
#chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode)
Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE)
)
def convertToUnicode(t):
return unichr(int(t[0], 16))
hex_unicode = (
Literal("\\").suppress() +
Regex("[0-9a-f]{1,6}", re.IGNORECASE) +
Optional(White(exact=1)).suppress()
).setParseAction(convertToUnicode)
escape = hex_unicode | escaped
#any unicode literal outside the 0-127 ascii range
nonascii = Regex(u"[^\u0000-\u007f]")
#single character for starting an identifier.
nmstart = Regex(u"[A-Z]", re.IGNORECASE) | nonascii | escape
nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape
identifier = Combine(nmstart + ZeroOrMore(nmchar))
\ No newline at end of file
""" Parser for inline CSS in style attributes """
def inlineStyle(styleString):
if not styleString:
return {}
styles = styleString.split(";")
rv = dict(style.split(":") for style in styles if len(style) != 0)
return rv
\ No newline at end of file
"""
Parsing for CSS and CSS-style values, such as transform and filter attributes.
"""
from pyparsing import (Literal, Word, CaselessLiteral,
Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, delimitedList)
#some shared definitions from pathdata
from ..pathdata import number, maybeComma
paren = Literal("(").suppress()
cparen = Literal(")").suppress()
def Parenthised(exp):
return Group(paren + exp + cparen)
skewY = Literal("skewY") + Parenthised(number)
skewX = Literal("skewX") + Parenthised(number)
rotate = Literal("rotate") + Parenthised(
number + Optional(maybeComma + number + maybeComma + number)
)
scale = Literal("scale") + Parenthised(
number + Optional(maybeComma + number)
)
translate = Literal("translate") + Parenthised(
number + Optional(maybeComma + number)
)
matrix = Literal("matrix") + Parenthised(
#there's got to be a better way to write this
number + maybeComma +
number + maybeComma +
number + maybeComma +
number + maybeComma +
number + maybeComma +
number
)
transform = (skewY | skewX | rotate | scale | translate | matrix)
transformList = delimitedList(Group(transform), delim=maybeComma)
if __name__ == '__main__':
from tests.test_css import *
unittest.main()
\ No newline at end of file
"""
Parser for various kinds of CSS values as per CSS2 spec section 4.3
"""
from pyparsing import Word, Combine, Optional, Literal, oneOf, CaselessLiteral, StringEnd
def asInt(s,l,t):
return int(t[0])
def asFloat(s,l,t):
return float(t[0])
def asFloatOrInt(s,l,t):
""" Return an int if possible, otherwise a float"""
v = t[0]
try:
return int(v)
except ValueError:
return float(v)
integer = Word("0123456789").setParseAction(asInt)
number = Combine(
Optional(Word("0123456789")) + Literal(".") + Word("01234567890")
| integer
)
number.setName('number')
sign = oneOf("+ -")
signedNumber = Combine(Optional(sign) + number).setParseAction(asFloat)
lengthValue = Combine(Optional(sign) + number).setParseAction(asFloatOrInt)
lengthValue.setName('lengthValue')
#TODO: The physical units like in, mm
lengthUnit = oneOf(['em', 'ex', 'px', 'pt', '%'], caseless=True)
#the spec says that the unit is only optional for a 0 length, but
#there are just too many places where a default is permitted.
#TODO: Maybe should use a ctor like optional to let clients declare it?
length = lengthValue + Optional(lengthUnit, default=None) + StringEnd()
length.leaveWhitespace()
#set the parse action aftward so it doesn't "infect" the parsers that build on it
number.setParseAction(asFloat)
\ No newline at end of file
This diff is collapsed.
"""
SVG path data parser
Usage:
steps = svg.parseString(pathdata)
for command, arguments in steps:
pass
"""
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore)
#ParserElement.enablePackrat()
def Command(char):
""" Case insensitive but case preserving"""
return CaselessPreservingLiteral(char)
def Arguments(token):
return Group(token)
class CaselessPreservingLiteral(CaselessLiteral):
""" Like CaselessLiteral, but returns the match as found
instead of as defined.
"""
def __init__( self, matchString ):
super(CaselessPreservingLiteral,self).__init__( matchString.upper() )
self.name = "'%s'" % matchString
self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg
def parseImpl( self, instring, loc, doActions=True ):
test = instring[ loc:loc+self.matchLen ]
if test.upper() == self.match:
return loc+self.matchLen, test
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
def Sequence(token):
""" A sequence of the token"""
return OneOrMore(token+maybeComma)
digit_sequence = Word(nums)
sign = oneOf("+ -")
def convertToFloat(s, loc, toks):
try:
return float(toks[0])
except:
raise ParseException(loc, "invalid float format %s"%toks[0])
exponent = CaselessLiteral("e")+Optional(sign)+Word(nums)
#note that almost all these fields are optional,
#and this can match almost anything. We rely on Pythons built-in
#float() function to clear out invalid values - loosely matching like this
#speeds up parsing quite a lot
floatingPointConstant = Combine(
Optional(sign) +
Optional(Word(nums)) +
Optional(Literal(".") + Optional(Word(nums)))+
Optional(exponent)
)
floatingPointConstant.setParseAction(convertToFloat)
number = floatingPointConstant
#same as FP constant but don't allow a - sign
nonnegativeNumber = Combine(
Optional(Word(nums)) +
Optional(Literal(".") + Optional(Word(nums)))+
Optional(exponent)
)
nonnegativeNumber.setParseAction(convertToFloat)
coordinate = number
#comma or whitespace can seperate values all over the place in SVG
maybeComma = Optional(Literal(',')).suppress()
coordinateSequence = Sequence(coordinate)
coordinatePair = (coordinate + maybeComma + coordinate).setParseAction(lambda t: tuple(t))
coordinatePairSequence = Sequence(coordinatePair)
coordinatePairPair = coordinatePair + maybeComma + coordinatePair
coordinatePairPairSequence = Sequence(Group(coordinatePairPair))
coordinatePairTriple = coordinatePair + maybeComma + coordinatePair + maybeComma + coordinatePair
coordinatePairTripleSequence = Sequence(Group(coordinatePairTriple))
#commands
lineTo = Group(Command("L") + Arguments(coordinatePairSequence))
moveTo = Group(Command("M") + Arguments(coordinatePairSequence))
closePath = Group(Command("Z")).setParseAction(lambda t: ('Z', (None,)))
flag = oneOf("1 0").setParseAction(lambda t: bool(int((t[0]))))
arcRadius = (
nonnegativeNumber + maybeComma + #rx
nonnegativeNumber #ry
).setParseAction(lambda t: tuple(t))
arcFlags = (flag + maybeComma + flag).setParseAction(lambda t: tuple(t))
ellipticalArcArgument = Group(
arcRadius + maybeComma + #rx, ry
number + maybeComma +#rotation
arcFlags + #large-arc-flag, sweep-flag
coordinatePair #(x,y)
)
ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument)))
smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence))
quadraticBezierCurveto = Group(Command("Q") + Arguments(coordinatePairPairSequence))
smoothCurve = Group(Command("S") + Arguments(coordinatePairPairSequence))
curve = Group(Command("C") + Arguments(coordinatePairTripleSequence))
horizontalLine = Group(Command("H") + Arguments(coordinateSequence))
verticalLine = Group(Command("V") + Arguments(coordinateSequence))
drawToCommand = (
lineTo | moveTo | closePath | ellipticalArc | smoothQuadraticBezierCurveto |
quadraticBezierCurveto | smoothCurve | curve | horizontalLine | verticalLine
)
#~ number.debug = True
moveToDrawToCommands = moveTo + ZeroOrMore(drawToCommand)
svg = ZeroOrMore(moveToDrawToCommands)
svg.keepTabs = True
def profile():
import cProfile
p = cProfile.Profile()
p.enable()
ptest()
ptest()
ptest()
p.disable()
p.print_stats()
bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35
81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58
80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58
C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58
210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83
145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83
105.83 375.83 105.83 C375.83 105.83 377.33 114.33 371.33 121.33 C370.3 122.53 367.83 134.33 361.83 140.83 C360.14 142.67
361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83
190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83
C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83
C336.33 266.83 333.46 262.38 332.83 263.83 C329.83 270.83 325.81 269.15 324.33 270.83 C320.83 274.83 317.33 274.83 315.83 276.33
C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83
C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33
C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83
C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33
C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83
65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83
58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33
C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33
39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83
202 145.83 C202 145.83 202.36 143.28 203 141.83 C203.64 140.39 204.56 140.02 204.33 139.83 z"""
def ptest():
svg.parseString(bpath)
if __name__ == '__main__':
#~ from tests.test_pathdata import *
#~ unittest.main()
profile()
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="23.838" height="23.838" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:slic3r="http://slic3r.org/namespaces/slic3r">
<!--
Generated using Slic3r 0.7.2b
http://slic3r.org/
-->
<g id="layer0" slic3r:z="0.03" >
<polygon slic3r:type="contour" points="11.919,23.457361 10.528202,23.373235 9.157683,23.122118 7.827451,22.707599 6.556855,22.135663 5.364459,21.414874 4.267648,20.555585 3.282414,19.570351 2.423125,18.47354 1.702336,17.281144 1.1304,16.010548 0.715881,14.680316 0.464764,13.309797 0.380639,11.919 0.464764,10.528202 0.715881,9.157683 1.1304,7.827451 1.702336,6.556855 2.423125,5.364459 3.282414,4.267648 4.267648,3.282414 5.364459,2.423125 6.556855,1.702336 7.827451,1.1304 9.157683,0.715881 10.528202,0.464764 11.919,0.380639 13.309797,0.464764 14.680316,0.715881 16.010548,1.1304 17.281144,1.702336 18.47354,2.423125 19.570351,3.282414 20.555585,4.267648 21.414874,5.364459 22.135663,6.556855 22.707599,7.827451 23.122118,9.157683 23.373235,10.528202 23.457361,11.919 23.373235,13.309797 23.122118,14.680316 22.707599,16.010548 22.135663,17.281144 21.414874,18.47354 20.555585,19.570351 19.570351,20.555585 18.47354,21.414874 17.281144,22.135663 16.010548,22.707599 14.680316,23.122118 13.309797,23.373235" style="fill: white" />
<polygon slic3r:type="hole" points="10.769,19.167808 10.769,16.269 13.069,16.269 13.069,19.167808 13.554669,19.085248 14.346729,18.85706 15.108288,18.541616 15.829724,18.14289 16.501994,17.665893 17.116627,17.116627 17.665893,16.501994 18.14289,15.829724 18.541616,15.108288 18.85706,14.346729 19.085248,13.554669 19.167808,13.069 16.269,13.069 16.269,10.769 19.167808,10.769 19.085248,10.283331 18.85706,9.491271 18.541616,8.729712 18.14289,8.008276 17.665893,7.336006 17.116627,6.721373 16.501994,6.172107 15.829724,5.69511 15.108288,5.296384 14.346729,4.98094 13.554669,4.752752 13.069,4.670192 13.069,7.569 10.769,7.569 10.769,4.670192 10.283331,4.752752 9.491271,4.98094 8.729712,5.296384 8.008276,5.69511 7.336006,6.172107 6.721373,6.721373 6.172107,7.336006 5.69511,8.008276 5.296384,8.729712 4.98094,9.491271 4.752752,10.283331 4.670192,10.769 7.569,10.769 7.569,13.069 4.670192,13.069 4.752752,13.554669 4.98094,14.346729 5.296384,15.108288 5.69511,15.829724 6.172107,16.501994 6.721373,17.116627 7.336006,17.665893 8.008276,18.14289 8.729712,18.541616 9.491271,18.85706 10.283331,19.085248" style="fill: black" />
</g>
<g id="layer1" slic3r:z="0.11">
<polygon slic3r:type="contour" points="11.919,23.377361 10.537846,23.293818 9.176828,23.04444 7.855816,22.632796 6.594036,22.06483 5.409906,21.349036 4.320698,20.495704 3.342295,19.517301 2.488963,18.428093 1.773169,17.243963 1.205203,15.982183 0.793559,14.661171 0.544181,13.300153 0.460639,11.919 0.544181,10.537846 0.793559,9.176828 1.205203,7.855816 1.773169,6.594036 2.488963,5.409906 3.342295,4.320698 4.320698,3.342295 5.409906,2.488963 6.594036,1.773169 7.855816,1.205203 9.176828,0.793559 10.537846,0.544181 11.919,0.460639 13.300153,0.544181 14.661171,0.793559 15.982183,1.205203 17.243963,1.773169 18.428093,2.488963 19.517301,3.342295 20.495704,4.320698 21.349036,5.409906 22.06483,6.594036 22.632796,7.855816 23.04444,9.176828 23.293818,10.537846 23.377361,11.919 23.293818,13.300153 23.04444,14.661171 22.632796,15.982183 22.06483,17.243963 21.349036,18.428093 20.495704,19.517301 19.517301,20.495704 18.428093,21.349036 17.243963,22.06483 15.982183,22.632796 14.661171,23.04444 13.300153,23.293818" style="fill: white" />
<polygon slic3r:type="hole" points="10.769,19.167808 10.769,16.269 13.069,16.269 13.069,19.167808 13.554669,19.085248 14.346729,18.85706 15.108288,18.541616 15.829724,18.14289 16.501994,17.665893 17.116627,17.116627 17.665893,16.501994 18.14289,15.829724 18.541616,15.108288 18.85706,14.346729 19.085248,13.554669 19.167808,13.069 16.269,13.069 16.269,10.769 19.167808,10.769 19.085248,10.283331 18.85706,9.491271 18.541616,8.729712 18.14289,8.008276 17.665893,7.336006 17.116627,6.721373 16.501994,6.172107 15.829724,5.69511 15.108288,5.296384 14.346729,4.98094 13.554669,4.752752 13.069,4.670192 13.069,7.569 10.769,7.569 10.769,4.670192 10.283331,4.752752 9.491271,4.98094 8.729712,5.296384 8.008276,5.69511 7.336006,6.172107 6.721373,6.721373 6.172107,7.336006 5.69511,8.008276 5.296384,8.729712 4.98094,9.491271 4.752752,10.283331 4.670192,10.769 7.569,10.769 7.569,13.069 4.670192,13.069 4.752752,13.554669 4.98094,14.346729 5.296384,15.108288 5.69511,15.829724 6.172107,16.501994 6.721373,17.116627 7.336006,17.665893 8.008276,18.14289 8.729712,18.541616 9.491271,18.85706 10.283331,19.085248" style="fill: black" />
</g>
<g id="layer2" slic3r:z="0.21">
<polygon slic3r:type="contour" points="11.919,23.277361 10.549901,23.194547 9.200759,22.947343 7.891273,22.539291 6.640509,21.976288 5.466718,21.266742 4.387008,20.42085 3.417149,19.450991 2.571257,18.371281 1.861711,17.19749 1.298708,15.946726 0.890656,14.63724 0.643452,13.288098 0.560639,11.919 0.643452,10.549901 0.890656,9.200759 1.298708,7.891273 1.861711,6.640509 2.571257,5.466718 3.417149,4.387008 4.387008,3.417149 5.466718,2.571257 6.640509,1.861711 7.891273,1.298708 9.200759,0.890656 10.549901,0.643452 11.919,0.560639 13.288098,0.643452 14.63724,0.890656 15.946726,1.298708 17.19749,1.861711 18.371281,2.571257 19.450991,3.417149 20.42085,4.387008 21.266742,5.466718 21.976288,6.640509 22.539291,7.891273 22.947343,9.200759 23.194547,10.549901 23.277361,11.919 23.194547,13.288098 22.947343,14.63724 22.539291,15.946726 21.976288,17.19749 21.266742,18.371281 20.42085,19.450991 19.450991,20.42085 18.371281,21.266742 17.19749,21.976288 15.946726,22.539291 14.63724,22.947343 13.288098,23.194547" style="fill: white" />
<polygon slic3r:type="hole" points="10.769,19.167808 10.769,16.269 13.069,16.269 13.069,19.167808 13.554669,19.085248 14.346729,18.85706 15.108288,18.541616 15.829724,18.14289 16.501994,17.665893 17.116627,17.116627 17.665893,16.501994 18.14289,15.829724 18.541616,15.108288 18.85706,14.346729 19.085248,13.554669 19.167808,13.069 16.269,13.069 16.269,10.769 19.167808,10.769 19.085248,10.283331 18.85706,9.491271 18.541616,8.729712 18.14289,8.008276 17.665893,7.336006 17.116627,6.721373 16.501994,6.172107 15.829724,5.69511 15.108288,5.296384 14.346729,4.98094 13.554669,4.752752 13.069,4.670192 13.069,7.569 10.769,7.569 10.769,4.670192 10.283331,4.752752 9.491271,4.98094 8.729712,5.296384 8.008276,5.69511 7.336006,6.172107 6.721373,6.721373 6.172107,7.336006 5.69511,8.008276 5.296384,8.729712 4.98094,9.491271 4.752752,10.283331 4.670192,10.769 7.569,10.769 7.569,13.069 4.670192,13.069 4.752752,13.554669 4.98094,14.346729 5.296384,15.108288 5.69511,15.829724 6.172107,16.501994 6.721373,17.116627 7.336006,17.665893 8.008276,18.14289 8.729712,18.541616 9.491271,18.85706 10.283331,19.085248" style="fill: black" />
</g>
</svg>
......@@ -47,7 +47,7 @@ class XYButtons(BufferedCanvas):
center = (124, 121)
spacer = 7
def __init__(self, parent, moveCallback=None, cornerCallback=None, ID=-1):
def __init__(self, parent, moveCallback=None, cornerCallback=None, spacebarCallback=None, bgcolor="#FFFFFF", 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
......@@ -56,7 +56,15 @@ class XYButtons(BufferedCanvas):
self.corner = None
self.moveCallback = moveCallback
self.cornerCallback = cornerCallback
self.spacebarCallback = spacebarCallback
self.enabled = False
# Remember the last clicked buttons, so we can repeat when spacebar pressed
self.lastMove = None
self.lastCorner = None
self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor)
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
BufferedCanvas.__init__(self, parent, ID)
self.SetSize(self.bg_bmp.GetSize())
......@@ -77,6 +85,16 @@ class XYButtons(BufferedCanvas):
self.enabled = True
self.update()
def repeatLast(self):
if self.lastMove:
self.moveCallback(*self.lastMove)
if self.lastCorner:
self.cornerCallback(self.lastCorner)
def clearRepeat(self):
self.lastMove = None
self.lastCorner = None
def distanceToLine(self, pos, x1, y1, x2, y2):
xlen = x2 - x1
ylen = y2 - y1
......@@ -206,6 +224,7 @@ class XYButtons(BufferedCanvas):
def draw(self, dc, w, h):
dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear()
gc = wx.GraphicsContext.Create(dc)
......@@ -240,8 +259,8 @@ class XYButtons(BufferedCanvas):
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.SetPen(wx.Pen(self.bgcolor, 0))
gc.SetBrush(wx.Brush(self.bgcolormask))
gc.DrawRectangle(0, 0, w, h)
......@@ -273,8 +292,6 @@ class XYButtons(BufferedCanvas):
self.quadrant = 2
elif evt.GetKeyCode() == wx.WXK_RIGHT:
self.quadrant = 0
elif evt.GetKeyCode() == wx.WXK_SPACE:
pass
else:
evt.Skip()
return
......@@ -283,6 +300,9 @@ class XYButtons(BufferedCanvas):
self.concentric = self.keypad_idx
x, y = self.getMovement()
self.moveCallback(x, y)
elif evt.GetKeyCode() == wx.WXK_SPACE:
self.spacebarCallback()
def OnMotion(self, event):
if not self.enabled:
......@@ -335,9 +355,13 @@ class XYButtons(BufferedCanvas):
if self.quadrant != None:
x, y = self.getMovement()
if self.moveCallback:
self.lastMove = (x, y)
self.lastCorner = None
self.moveCallback(x, y)
elif self.corner != None:
if self.cornerCallback:
self.lastCorner = self.corner
self.lastMove = None
self.cornerCallback(self.corner)
else:
if self.keypad_idx == idx:
......
......@@ -39,13 +39,19 @@ class ZButtons(BufferedCanvas):
3: None
}
def __init__(self, parent, moveCallback=None, ID=-1):
def __init__(self, parent, moveCallback=None, bgcolor="#FFFFFF", 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
# Remember the last clicked value, so we can repeat when spacebar pressed
self.lastValue = None
self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor)
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
BufferedCanvas.__init__(self, parent, ID)
......@@ -65,6 +71,13 @@ class ZButtons(BufferedCanvas):
self.enabled = True
self.update()
def repeatLast(self):
if self.lastValue:
self.moveCallback(self.lastValue)
def clearRepeat(self):
self.lastValue = None
def lookupRange(self, ydist):
idx = -1
for d in ZButtons.button_ydistances:
......@@ -93,6 +106,7 @@ class ZButtons(BufferedCanvas):
return (self.lookupRange(abs(ydelta)), sign(ydelta))
def draw(self, dc, w, h):
dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear()
gc = wx.GraphicsContext.Create(dc)
if self.bg_bmp:
......@@ -114,8 +128,8 @@ class ZButtons(BufferedCanvas):
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.SetPen(wx.Pen(self.bgcolor, 0))
gc.SetBrush(wx.Brush(self.bgcolormask))
gc.DrawRectangle(0, 0, w, h)
## ------ ##
......@@ -143,6 +157,7 @@ class ZButtons(BufferedCanvas):
if r >= 0:
value = math.pow(10, self.orderOfMagnitudeIdx) * math.pow(10, r - 1) * d
if self.moveCallback:
self.lastValue = value
self.moveCallback(value)
def OnLeaveWindow(self, evt):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment