00001 import wx
00002
00003
00004 class InputOutputShape:
00005 def __init__(self, parent, type='input', pos=(100, 100)):
00006 self.parentparent = parent
00007 self.typetype = type
00008 self.pospos = pos
00009 self.shownshown = True
00010 self.fullscreenfullscreen = False
00011
00012 self.namename = type
00013 self.bmpbmp = wx.Bitmap('bitmaps/%s.png' % self.typetype[:-3])
00014 self.namebmpnamebmp = self.GetNameBitmapGetNameBitmap()
00015
00016
00017 self.connectedToconnectedTo = None
00018
00019 def Draw(self, dc, op = wx.COPY):
00020 if self.bmpbmp.Ok() and self.namebmpnamebmp.Ok():
00021 memDC = wx.MemoryDC()
00022
00023
00024 memDC.SelectObject(self.namebmpnamebmp)
00025 if self.typetype == 'input':
00026 dc.Blit(self.pospos[0] + self.bmpbmp.GetWidth()/2 - self.namebmpnamebmp.GetWidth()/2 - 10,
00027 self.pospos[1] - self.namebmpnamebmp.GetHeight(),
00028 self.namebmpnamebmp.GetWidth(), self.namebmpnamebmp.GetHeight(),
00029 memDC, 0, 0, op, True)
00030 else:
00031 dc.Blit(self.pospos[0] + self.bmpbmp.GetWidth()/2 - self.namebmpnamebmp.GetWidth()/2 + 10,
00032 self.pospos[1] - self.namebmpnamebmp.GetHeight(),
00033 self.namebmpnamebmp.GetWidth(), self.namebmpnamebmp.GetHeight(),
00034 memDC, 0, 0, op, True)
00035
00036
00037 memDC.SelectObject(self.bmpbmp)
00038 dc.Blit(self.pospos[0], self.pospos[1],
00039 self.bmpbmp.GetWidth(), self.bmpbmp.GetHeight(),
00040 memDC, 0, 0, op, True)
00041
00042 def GetNameBitmap(self):
00043 font = wx.Font(11, wx.MODERN, wx.NORMAL, wx.NORMAL)
00044 textExtent = self.parentparent.GetFullTextExtent(self.namename, font)
00045 txtbmp = wx.EmptyBitmap(textExtent[0], textExtent[1])
00046
00047 memDC = wx.MemoryDC()
00048 memDC.SelectObject(txtbmp)
00049 memDC.SetBackground(wx.Brush(wx.WHITE, wx.SOLID))
00050 memDC.Clear()
00051 memDC.SetTextForeground(wx.BLACK)
00052 memDC.SetFont(font)
00053 memDC.DrawText(self.namename, 0, 0)
00054
00055 mask = wx.Mask(txtbmp, wx.WHITE)
00056 txtbmp.SetMask(mask)
00057 return txtbmp
00058
00059 def Rename(self, name):
00060 self.namename = name
00061 self.namebmpnamebmp = self.GetNameBitmapGetNameBitmap()
00062
00063 def HitTestBody(self, pt):
00064 rect = self.GetRectGetRect()
00065 if self.typetype == 'input':
00066 rect.width = rect.width - 20
00067 else:
00068 rect.x = rect.x + 20
00069 rect.width = rect.width - 20
00070
00071 return rect.InsideXY(pt.x, pt.y)
00072
00073 def HitTestArrow(self, pt):
00074
00075 rect = self.GetRectGetRect()
00076 return rect.InsideXY(pt.x, pt.y) and not self.HitTestBodyHitTestBody(pt)
00077
00078 def GetRect(self):
00079 return wx.Rect(self.pospos[0], self.pospos[1],
00080 self.bmpbmp.GetWidth(), self.bmpbmp.GetHeight())
00081
00082
00083 class DragShape:
00084 def __init__(self, parent, operation, name, pos=(100, 100)):
00085
00086 self.parentparent = parent
00087 self.operationoperation = operation
00088
00089
00090 self.namename = name
00091 self.bmpbmp = self.GetBitmapGetBitmap()
00092 self.namebmpnamebmp = self.GetNameBitmapGetNameBitmap()
00093 self.pospos = pos
00094 self.shownshown = True
00095 self.fullscreenfullscreen = False
00096
00097 def Rename(self, name):
00098 self.namename = name
00099 self.namebmpnamebmp = self.GetNameBitmapGetNameBitmap()
00100
00101 def GetBitmap(self):
00102 self.num_innum_in = len(self.operationoperation.input.parts)
00103 self.num_outnum_out = len(self.operationoperation.output.parts)
00104 return wx.Bitmap('bitmaps/%dto%d.png' % (self.num_innum_in, self.num_outnum_out))
00105
00106 def GetNameBitmap(self):
00107 font = wx.Font(11, wx.MODERN, wx.NORMAL, wx.NORMAL)
00108 textExtent = self.parentparent.GetFullTextExtent(self.namename, font)
00109 txtbmp = wx.EmptyBitmap(textExtent[0], textExtent[1])
00110
00111 memDC = wx.MemoryDC()
00112 memDC.SelectObject(txtbmp)
00113 memDC.SetBackground(wx.Brush(wx.WHITE, wx.SOLID))
00114 memDC.Clear()
00115 memDC.SetTextForeground(wx.BLACK)
00116 memDC.SetFont(font)
00117 memDC.DrawText(self.namename, 0, 0)
00118
00119 mask = wx.Mask(txtbmp, wx.WHITE)
00120 txtbmp.SetMask(mask)
00121 return txtbmp
00122
00123 def HitTestBody(self, pt):
00124 rect = self.GetRectGetRect()
00125 if self.num_innum_in > 0:
00126 rect.x = rect.x + 27
00127 rect.width = rect.width - 27
00128 if self.num_outnum_out > 0:
00129 rect.width = rect.width - 27
00130
00131 return rect.InsideXY(pt.x, pt.y)
00132
00133 def HitTestArrow(self, pt):
00134
00135 rect = self.GetRectGetRect()
00136 return rect.InsideXY(pt.x, pt.y) and not self.HitTestBodyHitTestBody(pt)
00137
00138 def GetRect(self):
00139 return wx.Rect(self.pospos[0], self.pospos[1],
00140 self.bmpbmp.GetWidth(), self.bmpbmp.GetHeight())
00141
00142 def Draw(self, dc, op = wx.COPY):
00143 if self.bmpbmp.Ok() and self.namebmpnamebmp.Ok():
00144 memDC = wx.MemoryDC()
00145
00146
00147 memDC.SelectObject(self.namebmpnamebmp)
00148 dc.Blit(self.pospos[0] + self.bmpbmp.GetWidth()/2 - self.namebmpnamebmp.GetWidth()/2,
00149 self.pospos[1] - self.namebmpnamebmp.GetHeight(),
00150 self.namebmpnamebmp.GetWidth(), self.namebmpnamebmp.GetHeight(),
00151 memDC, 0, 0, op, True)
00152
00153
00154 memDC.SelectObject(self.bmpbmp)
00155 dc.Blit(self.pospos[0], self.pospos[1],
00156 self.bmpbmp.GetWidth(), self.bmpbmp.GetHeight(),
00157 memDC, 0, 0, op, True)
00158
00159
00160 class Connection:
00161 def __init__(self, parent, input, output):
00162
00163 self.coordictcoordict = {'in.png': ([], [20]),
00164 'out.png': ([20], []),
00165 '0to1.png': ([], [31]),
00166 '0to2.png': ([], [18, 43]),
00167 '0to3.png': ([], [18, 43, 67]),
00168 '0to4.png': ([], [18, 43, 67, 93]),
00169 '0to5.png': ([], [18, 43, 67, 93, 118]),
00170 '1to0.png': ([31], []),
00171 '1to1.png': ([31], [31]),
00172 '1to2.png': ([31], [18, 43]),
00173 '1to3.png': ([43], [18, 43, 67]),
00174 '1to4.png': ([56], [18, 43, 67, 93]),
00175 '1to5.png': ([68], [18, 43, 67, 93, 118]),
00176 '2to0.png': ([18, 43], []),
00177 '2to1.png': ([18, 43], [31]),
00178 '2to2.png': ([18, 43], [18, 43]),
00179 '2to3.png': ([30, 56], [18, 43, 67]),
00180 '2to4.png': ([43, 67], [18, 43, 67, 93]),
00181 '2to5.png': ([43, 93], [18, 43, 67, 93, 118]),
00182 '3to0.png': ([18, 43, 67], []),
00183 '3to1.png': ([18, 43, 67], [43]),
00184 '3to2.png': ([18, 43, 67], [30, 56]),
00185 '3to3.png': ([18, 43, 67], [18, 43, 67]),
00186 '3to4.png': ([30, 55, 80], [18, 43, 67, 93]),
00187 '3to5.png': ([43, 67, 93], [18, 43, 67, 93, 118]),
00188 '4to0.png': ([18, 43, 67, 93], []),
00189 '4to1.png': ([18, 43, 67, 93], [55]),
00190 '4to2.png': ([18, 43, 67, 93], [43, 67]),
00191 '4to3.png': ([18, 43, 67, 93], [30, 55, 80]),
00192 '4to4.png': ([18, 43, 67, 93], [18, 43, 67, 93]),
00193 '4to5.png': ([31, 56, 81, 106], [18, 43, 67, 93, 118]),
00194 '5to0.png': ([18, 43, 67, 93, 118], []),
00195 '5to1.png': ([18, 43, 67, 93, 118], [67]),
00196 '5to2.png': ([18, 43, 67, 93, 118], [43, 93]),
00197 '5to3.png': ([18, 43, 67, 93, 118], [43, 67, 93]),
00198 '5to4.png': ([18, 43, 67, 93, 118], [31, 56, 81, 106]),
00199 '5to5.png': ([18, 43, 67, 93, 118], [18, 43, 67, 93, 118])
00200 }
00201
00202 self.parentparent = parent
00203 self.outputoutput = output
00204 self.inputinput = input
00205 self.iposipos = None
00206 self.oposopos = None
00207 self.shownshown = True
00208
00209 self.ibmpnameibmpname = '%dto%d.png' % (len(self.inputinput[0].operation.input.parts),
00210 len(self.inputinput[0].operation.output.parts))
00211 self.obmpnameobmpname = '%dto%d.png' % (len(self.outputoutput[0].operation.input.parts),
00212 len(self.outputoutput[0].operation.output.parts))
00213
00214 self.CalculateCoordsCalculateCoords()
00215
00216 def CalculateCoords(self):
00217 self.iposipos = self.GetCoordsForShapeGetCoordsForShape(self.inputinput[0], self.inputinput[1])
00218 self.oposopos = self.GetCoordsForShapeGetCoordsForShape(self.outputoutput[0],
00219 self.outputoutput[1], False)
00220
00221 def GetCoordsForShape(self, shape, partno, input=True):
00222 if input:
00223 bmfname = self.ibmpnameibmpname
00224 if bmfname not in self.coordictcoordict:
00225 return None
00226 else:
00227 return (shape.pos[0] + 2,
00228 shape.pos[1] + self.coordictcoordict[bmfname][0][partno])
00229 else:
00230 bmfname = self.obmpnameobmpname
00231 if bmfname not in self.coordictcoordict:
00232 return None
00233 else:
00234 return (shape.pos[0] - 2 + shape.bmp.GetWidth(),
00235 shape.pos[1] + self.coordictcoordict[bmfname][1][partno])
00236
00237 def Draw(self, dc):
00238 if self.iposipos and self.oposopos:
00239 dc.SetPen(wx.Pen('black', 2))
00240 dc.DrawLine(self.iposipos[0], self.iposipos[1],
00241 self.oposopos[0], self.oposopos[1])
00242
00243 def HitTest(self, pt):
00244 if not self.shownshown or not self.iposipos or not self.oposopos:
00245 return False
00246
00247
00248 d = 8
00249 if pt.x < ipos[0]-d and pt.x < opos[0]-d or pt.x > ipos[0]+d and pt.x > opos[0]+d:
00250 return False
00251 if pt.x < ipos[1]-d and pt.x < opos[1]-d or pt.x > ipos[1]+d and pt.x > opos[1]+d:
00252 return False
00253
00254
00255 rc = float((d - b) / (c - a))
00256 if rc > 1.0 or rc < -1.0:
00257
00258 pass
00259 else:
00260
00261 pass
00262
00263 class DragCanvas(wx.Panel):
00264 def __init__(self, parent, ID, definition = None):
00265 wx.Panel.__init__(self, parent, ID)
00266 self.defsdefs = definition
00267
00268
00269 self.shapesshapes = []
00270 self.dragImagedragImage = None
00271 self.dragShapedragShape = None
00272
00273
00274 self.dragArrowdragArrow = None
00275 self.dragFirstdragFirst = None
00276 self.connectionsconnections = []
00277 self.selectedShapeselectedShape = None
00278
00279 self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
00280 self.bg_bmpbg_bmp = wx.Bitmap('bitmaps/background.bmp')
00281 self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
00282 self.SetBackgroundColour(wx.WHITE)
00283
00284 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackgroundOnEraseBackground)
00285 self.Bind(wx.EVT_PAINT, self.OnPaintOnPaint)
00286 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDownOnLeftDown)
00287 self.Bind(wx.EVT_LEFT_UP, self.OnLeftUpOnLeftUp)
00288 self.Bind(wx.EVT_MOTION, self.OnMotionOnMotion)
00289 self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightMouseDownOnRightMouseDown)
00290
00291 def AddOperation(self, operation):
00292 shape_count = 1
00293 for s in self.shapesshapes:
00294 if s.operation.name == operation.name:
00295 shape_count += 1
00296 if shape_count == 1:
00297 shape = DragShape(self, operation, operation.name)
00298 else:
00299 shape = DragShape(self, operation,
00300 '%s<%d>' % (operation.name, shape_count))
00301 self.shapesshapes.append(shape)
00302 self.Refresh()
00303
00304 def AddInput(self):
00305 s = InputOutputShape(self)
00306 self.shapesshapes.append(s)
00307 self.Refresh()
00308
00309 def AddOutput(self):
00310 s = InputOutputShape(self, type="output")
00311 self.shapesshapes.append(s)
00312 self.Refresh()
00313
00314 def SetDefs(self, definition):
00315
00316 self.defsdefs = definition
00317 self.ClearAllClearAll()
00318
00319 def ClearAll(self):
00320 self.dragImagedragImage = None
00321 self.dragShapedragShape = None
00322 dc = wx.ClientDC(self)
00323
00324 self.shapesshapes = []
00325 self.connectionsconnections = []
00326 self.TileBackgroundTileBackground(dc)
00327
00328
00329 def TileBackground(self, dc):
00330 sz = self.GetClientSize()
00331 w = self.bg_bmpbg_bmp.GetWidth()
00332 h = self.bg_bmpbg_bmp.GetHeight()
00333
00334 x = 0
00335 while x < sz.width:
00336 y = 0
00337 while y < sz.height:
00338 dc.DrawBitmap(self.bg_bmpbg_bmp, x, y)
00339 y += h
00340 x += w
00341
00342 def DrawShapes(self, dc):
00343 for shape in self.shapesshapes:
00344 if shape.shown:
00345 shape.Draw(dc)
00346 for connection in self.connectionsconnections:
00347 if connection.shown:
00348 connection.Draw(dc)
00349
00350
00351
00352 def FindShapeBody(self, pt):
00353 for s in reversed(self.shapesshapes):
00354 if s.HitTestBody(pt):
00355 return s
00356 return None
00357
00358 def FindShapeArrow(self, pt):
00359
00360 for s in reversed(self.shapesshapes):
00361 if s.HitTestArrow(pt):
00362 return s
00363 return None
00364
00365 def EraseShape(self, shape, dc):
00366
00367 r = shape.GetRect()
00368 dc.SetClippingRect(r)
00369 self.TileBackgroundTileBackground(dc)
00370 self.DrawShapesDrawShapes(dc)
00371 dc.DestroyClippingRegion()
00372
00373
00374
00375 def OnEraseBackground(self, evt):
00376 dc = evt.GetDC()
00377
00378 if not dc:
00379 dc = wx.ClientDC(self)
00380 rect = self.GetUpdateRegion().GetBox()
00381 dc.SetClippingRect(rect)
00382 self.TileBackgroundTileBackground(dc)
00383
00384
00385 def OnPaint(self, evt):
00386 dc = wx.PaintDC(self)
00387 self.PrepareDC(dc)
00388 self.DrawShapesDrawShapes(dc)
00389
00390 def OnRightMouseDown(self, event):
00391 shape = self.FindShapeBodyFindShapeBody(event.GetPosition())
00392 if shape:
00393 self.ClearArrowDraggingClearArrowDragging()
00394 self.ClearShapeDraggingClearShapeDragging()
00395 self.selectedShapeselectedShape = shape
00396
00397 menu = self.MakeArrowMenuMakeArrowMenu(shape)
00398 self.PopupMenu(menu)
00399 menu.Destroy()
00400
00401 self.selectedShapeselectedShape = None
00402 else:
00403 self.ClearArrowDraggingClearArrowDragging()
00404 self.ClearShapeDraggingClearShapeDragging()
00405
00406 def ClearArrowDragging(self):
00407 self.dragArrowdragArrow = None
00408 self.dragFirstdragFirst = None
00409 self.selectedShapeselectedShape = None
00410
00411 def ClearShapeDragging(self):
00412 self.dragShapedragShape = None
00413 self.dragImagedragImage = None
00414 self.selectedShapeselectedShape = None
00415
00416 def HandleArrow(self, arrow):
00417
00418 if not self.dragArrowdragArrow:
00419
00420 self.ClearArrowDraggingClearArrowDragging()
00421 self.ClearShapeDraggingClearShapeDragging()
00422 self.dragArrowdragArrow = arrow
00423 self.selectedShapeselectedShape = arrow
00424
00425 menu = self.MakeArrowMenuMakeArrowMenu(arrow)
00426 self.PopupMenu(menu)
00427 menu.Destroy()
00428
00429 if self.dragFirstdragFirst:
00430 self.dragArrowdragArrow = arrow
00431 else:
00432 self.dragArrowdragArrow = None
00433 self.selectedShapeselectedShape = None
00434 else:
00435 if arrow and arrow != self.dragArrowdragArrow:
00436
00437 self.dragArrowdragArrow = arrow
00438 self.dragImagedragImage = None
00439 self.dragShapedragShape = None
00440 self.selectedShapeselectedShape = arrow
00441
00442 menu = self.MakeArrowMenuMakeArrowMenu(arrow)
00443 self.PopupMenu(menu)
00444 menu.Destroy()
00445
00446 self.selectedShapeselectedShape = None
00447
00448
00449 def OnLeftDown(self, evt):
00450
00451 shape = self.FindShapeBodyFindShapeBody(evt.GetPosition())
00452
00453 if shape and not self.dragArrowdragArrow:
00454
00455 self.ClearArrowDraggingClearArrowDragging()
00456 self.ClearShapeDraggingClearShapeDragging()
00457
00458 self.dragShapedragShape = shape
00459 self.dragStartPos = evt.GetPosition()
00460 else:
00461
00462 if shape:
00463
00464 self.HandleArrowHandleArrow(shape)
00465 return
00466
00467
00468 arrow = self.FindShapeArrowFindShapeArrow(evt.GetPosition())
00469 if arrow:
00470 self.HandleArrowHandleArrow(arrow)
00471 else:
00472
00473 self.ClearArrowDraggingClearArrowDragging()
00474 self.ClearShapeDraggingClearShapeDragging()
00475
00476 def MakeArrowMenu(self, arrow):
00477 """Create the menu which is displayed when the user clicks
00478 on an in- or output arrow.
00479 """
00480 input_ids = 3000
00481 output_ids = 4000
00482
00483 menu = wx.Menu()
00484 m = menu.Append(-1, 'Connect %s' % arrow.name)
00485 m.Enable(False)
00486 menu.AppendSeparator()
00487
00488 if isinstance(arrow, DragShape):
00489 m = menu.Append(-1, 'Input:')
00490 m.Enable(False)
00491 for part in arrow.operation.input.parts:
00492 m = menu.Append(input_ids,
00493 '%s (%s)' % (part.name, part.type.name))
00494 self.Bind(wx.EVT_MENU, self.OnArrowMenuOnArrowMenu, m)
00495 input_ids += 1
00496
00497 menu.AppendSeparator()
00498 m = menu.Append(-1, 'Output:')
00499 m.Enable(False)
00500 for part in arrow.operation.output.parts:
00501 m = menu.Append(output_ids,
00502 '%s (%s)' % (part.name, part.type.name))
00503 self.Bind(wx.EVT_MENU, self.OnArrowMenuOnArrowMenu, m)
00504 output_ids += 1
00505 else:
00506 if arrow.type == 'input':
00507 if arrow.connectedTo:
00508 m = menu.Append(input_ids, 'Input (%s)' % arrow.connectedTo)
00509 self.Bind(wx.EVT_MENU, self.OnArrowMenuOnArrowMenu, m)
00510 else:
00511 m = menu.Append(input_ids, 'Input')
00512 self.Bind(wx.EVT_MENU, self.OnArrowMenuOnArrowMenu, m)
00513 m = menu.Append(-1, 'Provide input')
00514 self.Bind(wx.EVT_MENU, self.OnProvideInputOnProvideInput, m)
00515 else:
00516 if arrow.connectedTo:
00517 m = menu.Append(output_ids, 'Input (%s)' % arrow.connectedTo)
00518 self.Bind(wx.EVT_MENU, self.OnArrowMenuOnArrowMenu, m)
00519 else:
00520 m = menu.Append(output_ids, 'Output')
00521 self.Bind(wx.EVT_MENU, self.OnArrowMenuOnArrowMenu, m)
00522
00523 menu.AppendSeparator()
00524 m = menu.Append(-1, 'Clear %s' % arrow.name)
00525 self.Bind(wx.EVT_MENU, self.OnClearShapeOnClearShape, m)
00526 m = menu.Append(-1, 'Rename %s' % arrow.name)
00527 self.Bind(wx.EVT_MENU, self.OnRenameShapeOnRenameShape, m)
00528
00529 return menu
00530
00531 def OnClearShape(self, event):
00532 if self.selectedShapeselectedShape:
00533 to_remove = []
00534 for c in self.connectionsconnections:
00535 if c.input[0] == self.selectedShapeselectedShape or c.output[0] == self.selectedShapeselectedShape:
00536 to_remove.append(c)
00537 for c in to_remove:
00538 self.connectionsconnections.remove(c)
00539
00540 self.shapesshapes.remove(self.selectedShapeselectedShape)
00541 self.selectedShapeselectedShape = None
00542 self.Refresh()
00543
00544 def OnRenameShape(self, event):
00545 if self.selectedShapeselectedShape:
00546 dlg = wx.TextEntryDialog(self, 'Please enter a new name.',
00547 'Rename', 'Python')
00548 dlg.SetValue(self.selectedShapeselectedShape.name)
00549 if dlg.ShowModal() == wx.ID_OK:
00550 self.selectedShapeselectedShape.Rename(dlg.GetValue())
00551 dlg.Destroy()
00552 self.Refresh()
00553
00554 def OnProvideInput(self, event):
00555 pass
00556
00557 def OnArrowMenu(self, event):
00558 menu_id = event.GetId()
00559 if self.dragFirst == None:
00560 if menu_id >= 3000 and menu_id < 4000:
00561
00562 self.dragFirst = (self.dragArrow,
00563 True, menu_id - 3000)
00564 else:
00565
00566 self.dragFirst = (self.dragArrow,
00567 False, menu_id - 4000)
00568 else:
00569
00570 if menu_id >= 3000 and menu_id < 4000:
00571
00572 second = (self.dragArrow, True, menu_id - 3000)
00573 else:
00574
00575 second = (self.dragArrow, False, menu_id - 4000)
00576 self.MakeConnection(self.dragFirst, second)
00577 self.ClearArrowDragging()
00578
00579 def MakeConnection(self, first, second):
00580
00581 if first[1] == second[1]:
00582 self.PrintErrorAndStopConnectingPrintErrorAndStopConnecting('Must connect input to output or vice versa')
00583 elif isinstance(first[0], InputOutputShape) and isinstance(second[0], InputOutputShape):
00584 self.PrintErrorAndStopConnectingPrintErrorAndStopConnecting('Cannot connect input directly to output')
00585 elif first[1] and isinstance(first[0], InputOutputShape):
00586 self.MakeInputConnectionMakeInputConnection(first, second)
00587 elif second[1] and isinstance(second[0], InputOutputShape):
00588 self.MakeInputConnectionMakeInputConnection(second, first)
00589 elif not first[1] and isinstance(first[0], InputOutputShape):
00590 self.MakeOutputConnectionMakeOutputConnection(first, second)
00591 elif not second[1] and isinstance(second[0], InputOutputShape):
00592 self.MakeOutputConnectionMakeOutputConnection(second, first)
00593
00594 else:
00595
00596 part1 = first[0].operation
00597 part2 = second[0].operation
00598 if first[1]:
00599 if part1.input.parts[first[2]].type.name != part2.output.parts[second[2]].type.name:
00600 self.PrintErrorAndStopConnectingPrintErrorAndStopConnecting('Types don\'t match.')
00601 else:
00602 self.connectionsconnections.append(Connection(self,
00603 (first[0], first[2]),
00604 (second[0], second[2])))
00605 else:
00606 if part1.output.parts[first[2]].type.name != part2.input.parts[second[2]].type.name:
00607 self.PrintErrorAndStopConnectingPrintErrorAndStopConnecting('Types don\'t match.')
00608 else:
00609 self.connectionsconnections.append(Connection(self,
00610 (second[0], second[2]),
00611 (first[0], first[2])))
00612 self.Refresh()
00613
00614 def MakeInputConnection(self, input, other):
00615 pass
00616
00617 def MakeOutputConnection(self, output, other):
00618 pass
00619
00620 def PrintErrorAndStopConnecting(self, msg):
00621 dlg = wx.MessageDialog(self, msg, 'Connection Error', wx.OK|wx.ICON_ERROR)
00622 dlg.ShowModal()
00623 dlg.Destroy()
00624 self.ClearArrowDragging()
00625
00626 def round(self, n, m):
00627 x = n / m
00628 if n <= x * n + m / 2:
00629 return x * m
00630 else:
00631 return (x + 1) * m
00632
00633
00634 def OnLeftUp(self, evt):
00635 if not self.dragImagedragImage or not self.dragShapedragShape:
00636 self.dragImagedragImage = None
00637 self.dragShapedragShape = None
00638 evt.Skip()
00639 return
00640
00641
00642 self.dragImagedragImage.Hide()
00643 self.dragImagedragImage.EndDrag()
00644 self.dragImagedragImage = None
00645
00646
00647 self.dragShapedragShape.pos = (
00648 self.roundround(self.dragShapedragShape.pos[0] + evt.GetPosition()[0] - self.dragStartPos[0], 10),
00649 self.roundround(self.dragShapedragShape.pos[1] + evt.GetPosition()[1] - self.dragStartPos[1], 10)
00650 )
00651
00652
00653 for s in self.shapesshapes:
00654 if s == self.dragShapedragShape:
00655 self.shapesshapes.remove(s)
00656 self.shapesshapes.append(self.dragShapedragShape)
00657
00658
00659 for c in self.connectionsconnections:
00660 if c.input[0] == self.dragShapedragShape or c.output[0] == self.dragShapedragShape:
00661 c.CalculateCoords()
00662 c.shown = True
00663
00664 self.dragShapedragShape.shown = True
00665 self.RefreshRect(self.dragShapedragShape.GetRect())
00666 self.dragShapedragShape = None
00667
00668 self.Refresh()
00669
00670
00671
00672 def OnMotion(self, evt):
00673
00674 if not self.dragShapedragShape or not evt.Dragging() or not evt.LeftIsDown():
00675 evt.Skip()
00676
00677
00678 if self.dragShapedragShape and not self.dragImagedragImage:
00679
00680
00681 tolerance = 2
00682 pt = evt.GetPosition()
00683 dx = abs(pt.x - self.dragStartPos.x)
00684 dy = abs(pt.y - self.dragStartPos.y)
00685 if dx <= tolerance and dy <= tolerance:
00686 return
00687
00688
00689 dc = wx.ClientDC(self)
00690 self.dragShapedragShape.shown = False
00691 self.EraseShapeEraseShape(self.dragShapedragShape, dc)
00692
00693
00694 for c in self.connectionsconnections:
00695 if c.input[0] == self.dragShapedragShape or c.output[0] == self.dragShapedragShape:
00696 c.shown = False
00697
00698 self.Refresh()
00699
00700 self.dragImagedragImage = wx.DragImage(self.dragShapedragShape.bmp,
00701 wx.StockCursor(wx.CURSOR_HAND))
00702
00703 hotspot = self.dragStartPos - self.dragShapedragShape.pos
00704 self.dragImagedragImage.BeginDrag(hotspot, self, self.dragShapedragShape.fullscreen)
00705
00706 self.dragImagedragImage.Move(pt)
00707 self.dragImagedragImage.Show()
00708
00709
00710 elif self.dragShapedragShape and self.dragImagedragImage:
00711
00712 self.dragImagedragImage.Move(evt.GetPosition())
00713 self.dragImagedragImage.Show()
00714
00715
00716 class ComplexRequestPanel(wx.Panel):
00717 def __init__(self, parent, connector):
00718 wx.Panel.__init__(self, parent, -1)
00719
00720 self.defsdefs = None
00721 self.selected_serviceselected_service = None
00722 self.selected_portselected_port = None
00723 self.selected_operationselected_operation = None
00724
00725 self.connconn = connector
00726 self.InitLayoutInitLayout()
00727
00728 def InitLayout(self):
00729 mainbox = wx.BoxSizer(wx.VERTICAL)
00730 canvasbox = wx.StaticBox(self, -1, 'Constructor Window')
00731 cbs = wx.StaticBoxSizer(canvasbox, wx.HORIZONTAL)
00732 self.canvascanvas = DragCanvas(self, -1, self.defsdefs)
00733
00734 mainbox.Add(self.InitHeadlineRowInitHeadlineRow(), 0, wx.EXPAND|wx.ALIGN_TOP|wx.ALL, 5)
00735 cbs.Add(self.canvascanvas, 1, wx.EXPAND)
00736 mainbox.Add(cbs, 1, wx.EXPAND|wx.ALL, 5)
00737 self.SetSizer(mainbox)
00738
00739 def InitHeadlineRow(self):
00740 headlinerow = wx.BoxSizer(wx.HORIZONTAL)
00741
00742 headlinerow.Add(wx.StaticText(self, -1, 'Select:'), 0,
00743 wx.RIGHT, 5)
00744
00745 self.servicesservices = wx.Choice(self, -1, choices=[])
00746 headlinerow.Add(self.servicesservices, 1)
00747 self.Bind(wx.EVT_CHOICE, self.OnServiceSelectedOnServiceSelected, self.servicesservices)
00748
00749 headlinerow.Add(wx.StaticText(self, -1, '>'), 0, wx.LEFT|wx.RIGHT, 5)
00750
00751 self.portsports = wx.Choice(self, -1, choices=[])
00752 self.Bind(wx.EVT_CHOICE, self.OnPortSelectedOnPortSelected, self.portsports)
00753 headlinerow.Add(self.portsports, 1)
00754
00755 headlinerow.Add(wx.StaticText(self, -1, '>'), 0, wx.LEFT|wx.RIGHT, 5)
00756
00757 self.operationsoperations = wx.Choice(self, -1, choices=[])
00758 self.Bind(wx.EVT_CHOICE, self.OnOperationSelectedOnOperationSelected, self.operationsoperations)
00759 headlinerow.Add(self.operationsoperations, 1)
00760
00761 headlinerow.Add(wx.StaticText(self, -1, 'or'), 0, wx.LEFT, 5)
00762
00763 btn = wx.Button(self, -1, 'Add Input')
00764 self.Bind(wx.EVT_BUTTON, self.OnInputAddOnInputAdd, btn)
00765 headlinerow.Add(btn, 0, wx.LEFT, 5)
00766
00767 btn = wx.Button(self, -1, 'Add Output')
00768 self.Bind(wx.EVT_BUTTON, self.OnOutputAddOnOutputAdd, btn)
00769 headlinerow.Add(btn, 0, wx.LEFT, 5)
00770
00771 headlinerow.Add((5, -1), 1)
00772
00773 btn = wx.Button(self, -1, 'Clear')
00774 self.Bind(wx.EVT_BUTTON, self.OnClearStructureOnClearStructure, btn)
00775 headlinerow.Add(btn, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5)
00776
00777 btn = wx.Button(self, -1, 'Execute')
00778 self.Bind(wx.EVT_BUTTON, self.OnExecuteOnExecute, btn)
00779 headlinerow.Add(btn, 0, wx.ALIGN_RIGHT)
00780
00781 return headlinerow
00782
00783 def OnInputAdd(self, event):
00784 self.canvascanvas.AddInput()
00785
00786 def OnOutputAdd(self, event):
00787 self.canvascanvas.AddOutput()
00788
00789 def OnServiceSelected(self, event):
00790
00791 self.portsports.Clear()
00792 self.operationsoperations.Clear()
00793 self.selected_serviceselected_service = None
00794 self.selected_portselected_port = None
00795 self.selected_operationselected_operation = None
00796
00797 if self.defsdefs:
00798 sel = event.GetString()
00799 for s in self.defsdefs.services:
00800 if s.name == sel:
00801 self.selected_serviceselected_service = s
00802 self.portsports.AppendItems([pt.name for pt in s.ports])
00803 break
00804
00805 def OnPortSelected(self, event):
00806 self.operationsoperations.Clear()
00807 self.selected_portselected_port = None
00808 self.selected_operationselected_operation = None
00809
00810 if self.selected_serviceselected_service:
00811 sel = event.GetString()
00812 for p in self.selected_serviceselected_service.ports:
00813 if p.name == sel:
00814 self.selected_portselected_port = p
00815 self.operationsoperations.AppendItems([op.name for op in p.type.operations])
00816 break
00817
00818 def OnOperationSelected(self, event):
00819 self.selected_operationselected_operation = None
00820 if self.selected_portselected_port:
00821 sel = event.GetString()
00822 for op in self.selected_portselected_port.type.operations:
00823 if op.name == sel:
00824 self.selected_operationselected_operation = op
00825 self.canvascanvas.AddOperation(self.selected_operationselected_operation)
00826
00827 def SetDefs(self, defs):
00828 self.ClearDefinitionsClearDefinitions()
00829 self.defsdefs = defs
00830 self.canvascanvas.SetDefs(defs)
00831 if self.defsdefs:
00832 for svc in self.defsdefs.services:
00833 self.servicesservices.Append(svc.name)
00834
00835 def OnExecute(self, event):
00836 pass
00837
00838 def OnClearStructure(self, event):
00839 self.canvas.ClearAll()
00840
00841 def ClearDefinitions(self):
00842 self.defsdefs = None
00843 self.selected_serviceselected_service = None
00844 self.selected_portselected_port = None
00845 self.selected_operationselected_operation = None
00846 self.ClearServiceListsClearServiceLists()
00847
00848 def ClearServiceLists(self):
00849 self.servicesservices.Clear()
00850 self.operationsoperations.Clear()
00851 self.portsports.Clear()
00852