202 self.main_sizer.Add(self.desc, flag=wx.GROW) |
203 self.main_sizer.Add(self.desc, flag=wx.GROW) |
203 self.main_sizer.Add(self.edit_sizer, flag=wx.GROW) |
204 self.main_sizer.Add(self.edit_sizer, flag=wx.GROW) |
204 self.SetSizer(self.main_sizer) |
205 self.SetSizer(self.main_sizer) |
205 self.main_sizer.Fit(self) |
206 self.main_sizer.Fit(self) |
206 |
207 |
|
208 def GetValue(self): |
|
209 return self.edit.GetValue() |
|
210 |
207 def setValidity(self, validity): |
211 def setValidity(self, validity): |
208 if validity is not None: |
212 if validity is not None: |
209 bmp = self.valid_bmp if validity else self.invalid_bmp |
213 bmp = self.valid_bmp if validity else self.invalid_bmp |
210 self.validity_sbmp.SetBitmap(bmp) |
214 self.validity_sbmp.SetBitmap(bmp) |
211 self.validity_sbmp.Show(True) |
215 self.validity_sbmp.Show(True) |
236 map(lambda typename: |
240 map(lambda typename: |
237 models[typename].match(txt) is not None, |
241 models[typename].match(txt) is not None, |
238 accepts), |
242 accepts), |
239 False) |
243 False) |
240 if accepts and txt else None) |
244 if accepts and txt else None) |
|
245 self.ParentObj.RegenSVGLater() |
241 event.Skip() |
246 event.Skip() |
242 |
247 |
243 class PathEditor(ParamEditor): |
248 class PathEditor(ParamEditor): |
244 def __init__(self, parent, pathdesc): |
249 def __init__(self, parent, pathdesc): |
245 ParamEditor.__init__(self, parent, pathdesc) |
250 ParamEditor.__init__(self, parent, pathdesc) |
259 |
264 |
260 def OnPathChanged(self, event): |
265 def OnPathChanged(self, event): |
261 # TODO : find corresponding hmitre node and type to update validity |
266 # TODO : find corresponding hmitre node and type to update validity |
262 # Lazy way : hide validity |
267 # Lazy way : hide validity |
263 self.setValidity(None) |
268 self.setValidity(None) |
|
269 self.ParentObj.RegenSVGLater() |
264 event.Skip() |
270 event.Skip() |
265 |
271 |
266 def KeepDoubleNewLines(txt): |
272 def KeepDoubleNewLines(txt): |
267 return "\n\n".join(map( |
273 return "\n\n".join(map( |
268 lambda s:re.sub(r'\s+',' ',s), |
274 lambda s:re.sub(r'\s+',' ',s), |
345 self.picker_desc_splitter.SplitHorizontally(self.picker_panel, self.desc, 400) |
351 self.picker_desc_splitter.SplitHorizontally(self.picker_panel, self.desc, 400) |
346 self.SplitVertically(self.main_panel, self.picker_desc_splitter, 300) |
352 self.SplitVertically(self.main_panel, self.picker_desc_splitter, 300) |
347 |
353 |
348 self.tempf = None |
354 self.tempf = None |
349 |
355 |
|
356 self.RegenSVGThread = None |
|
357 self.RegenSVGLock = Lock() |
|
358 self.RegenSVGTimer = wx.Timer(self, -1) |
|
359 self.RegenSVGParams = None |
|
360 self.Bind(wx.EVT_TIMER, |
|
361 self.RegenSVG, |
|
362 self.RegenSVGTimer) |
|
363 |
350 self.args_editors = [] |
364 self.args_editors = [] |
351 self.paths_editors = [] |
365 self.paths_editors = [] |
352 |
366 |
353 def ResetSignature(self): |
367 def ResetSignature(self): |
354 self.args_sizer.Clear() |
368 self.args_sizer.Clear() |
479 |
495 |
480 self.selected_SVG = svgpath if have_thumb else None |
496 self.selected_SVG = svgpath if have_thumb else None |
481 |
497 |
482 self.AnalyseWidgetAndUpdateUI(fname) |
498 self.AnalyseWidgetAndUpdateUI(fname) |
483 |
499 |
484 if self.msg: |
500 self.staticmsg.SetLabel(self.msg) |
485 self.staticmsg.Show() |
|
486 self.staticmsg.SetLabel(self.msg) |
|
487 else: |
|
488 self.staticmsg.Hide() |
|
489 |
|
490 |
501 |
491 except IOError: |
502 except IOError: |
492 self.msg = _("Widget library must be writable") |
503 self.msg = _("Widget library must be writable") |
493 |
504 |
494 self.Refresh() |
505 self.Refresh() |
495 event.Skip() |
506 event.Skip() |
496 |
507 |
497 def OnHMITreeNodeSelection(self, hmitree_nodes): |
508 def OnHMITreeNodeSelection(self, hmitree_nodes): |
498 self.hmitree_nodes = hmitree_nodes |
509 self.hmitree_nodes = hmitree_nodes |
499 # [0] if len(hmitree_nodes) else None |
|
500 # self.ValidateWidget() |
|
501 # self.Refresh() |
|
502 |
510 |
503 def OnLeftDown(self, evt): |
511 def OnLeftDown(self, evt): |
504 if self.tempf is not None: |
512 if self.tempf is not None: |
505 filename = self.tempf.name |
513 filename = self.tempf.name |
506 data = wx.FileDataObject() |
514 data = wx.FileDataObject() |
507 data.AddFile(filename) |
515 data.AddFile(filename) |
508 dropSource = wx.DropSource(self) |
516 dropSource = wx.DropSource(self) |
509 dropSource.SetData(data) |
517 dropSource.SetData(data) |
510 dropSource.DoDragDrop(wx.Drag_AllowMove) |
518 dropSource.DoDragDrop(wx.Drag_AllowMove) |
511 |
519 |
512 def GiveDetails(self, _context, msgs): |
520 def RegenSVGLater(self, when=1): |
513 for msg in msgs: |
521 self.RegenSVGTimer.Start(milliseconds=when*1000, oneShot=True) |
514 self.msg += msg.text + "\n" |
522 |
|
523 def RegenSVGNow(self): |
|
524 self.RegenSVGLater(when=0) |
|
525 |
|
526 def RegenSVG(self, event): |
|
527 args = [arged.GetValue() for arged in self.args_editors] |
|
528 paths = [pathed.GetValue() for pathed in self.paths_editors] |
|
529 if self.RegenSVGLock.acquire(True): |
|
530 self.RegenSVGParams = (args, paths) |
|
531 if self.RegenSVGThread is None: |
|
532 self.RegenSVGThread = \ |
|
533 Thread(target=self.RegenSVGProc, |
|
534 name="RegenSVGThread").start() |
|
535 self.RegenSVGLock.release() |
|
536 event.Skip() |
|
537 |
|
538 def RegenSVGProc(self): |
|
539 self.RegenSVGLock.acquire(True) |
|
540 |
|
541 newparams = self.RegenSVGParams |
|
542 self.RegenSVGParams = None |
|
543 |
|
544 while newparams is not None: |
|
545 self.RegenSVGLock.release() |
|
546 |
|
547 res = self.GenDnDSVG(newparams) |
|
548 |
|
549 self.RegenSVGLock.acquire(True) |
|
550 |
|
551 newparams = self.RegenSVGParams |
|
552 self.RegenSVGParams = None |
|
553 |
|
554 self.RegenSVGThread = None |
|
555 |
|
556 self.RegenSVGLock.release() |
|
557 |
|
558 wx.CallAfter(self.DoneRegenSVG) |
515 |
559 |
516 def PassMessage(self, _context, msgs): |
560 def DoneRegenSVG(self): |
517 for msg in msgs: |
561 self.staticmsg.SetLabel(self.msg) |
518 self.msg += msg.text + "\n" |
562 |
519 |
|
520 def GetSubHMITree(self, _context): |
|
521 return [self.hmitree_node.etree()] |
|
522 |
|
523 def AnalyseWidgetAndUpdateUI(self, fname): |
563 def AnalyseWidgetAndUpdateUI(self, fname): |
524 self.msg = "" |
564 self.msg = "" |
525 self.ResetSignature() |
565 self.ResetSignature() |
526 |
566 |
527 try: |
567 try: |
592 print(path, path_value, path_accepts) |
632 print(path, path_value, path_accepts) |
593 |
633 |
594 self.main_panel.SetupScrolling(scroll_x=False) |
634 self.main_panel.SetupScrolling(scroll_x=False) |
595 |
635 |
596 |
636 |
597 |
637 def PassMessage(self, _context, msgs): |
598 def ValidateWidget(self): |
638 for msg in msgs: |
|
639 self.msg += msg.text + "\n" |
|
640 |
|
641 def GetWidgetParams(self, _context): |
|
642 args,paths = self.GenDnDSVGParams |
|
643 root = etree.Element("params") |
|
644 for arg in args: |
|
645 etree.SubElement(root, "arg", value=arg) |
|
646 for path in paths: |
|
647 etree.SubElement(root, "path", value=path) |
|
648 return root |
|
649 |
|
650 |
|
651 def GenDnDSVG(self, newparams): |
599 self.msg = "" |
652 self.msg = "" |
|
653 |
|
654 self.GenDnDSVGParams = newparams |
600 |
655 |
601 if self.tempf is not None: |
656 if self.tempf is not None: |
602 os.unlink(self.tempf.name) |
657 os.unlink(self.tempf.name) |
603 self.tempf = None |
658 self.tempf = None |
604 |
659 |
605 try: |
660 try: |
606 if self.selected_SVG is None: |
661 if self.selected_SVG is None: |
607 raise Exception(_("No widget selected")) |
662 raise Exception(_("No widget selected")) |
608 if self.hmitree_node is None: |
|
609 raise Exception(_("No HMI tree node selected")) |
|
610 |
663 |
611 transform = XSLTransform( |
664 transform = XSLTransform( |
612 os.path.join(ScriptDirectory, "gen_dnd_widget_svg.xslt"), |
665 os.path.join(ScriptDirectory, "gen_dnd_widget_svg.xslt"), |
613 [("GetSubHMITree", self.GetSubHMITree), |
666 [("GetWidgetParams", self.GetWidgetParams), |
614 ("PassMessage", self.GiveDetails)]) |
667 ("PassMessage", self.PassMessage)]) |
615 |
668 |
616 svgdom = etree.parse(self.selected_SVG) |
669 svgdom = etree.parse(self.selected_SVG) |
617 |
670 |
618 result = transform.transform( |
671 result = transform.transform(svgdom) |
619 svgdom, hmi_path = self.hmitree_node.hmi_path()) |
|
620 |
672 |
621 for entry in transform.get_error_log(): |
673 for entry in transform.get_error_log(): |
622 self.msg += "XSLT: " + entry.message + "\n" |
674 self.msg += "XSLT: " + entry.message + "\n" |
623 |
675 |
624 self.tempf = NamedTemporaryFile(suffix='.svg', delete=False) |
676 self.tempf = NamedTemporaryFile(suffix='.svg', delete=False) |