181 """ |
181 """ |
182 Function that calculates the nearest point of the grid defined by scaling for the given point |
182 Function that calculates the nearest point of the grid defined by scaling for the given point |
183 """ |
183 """ |
184 pos = event.GetLogicalPosition(dc) |
184 pos = event.GetLogicalPosition(dc) |
185 if scaling: |
185 if scaling: |
186 pos.x = round(pos.x / scaling[0]) * scaling[0] |
186 sx,sy=tuple(map(round,scaling)) |
187 pos.y = round(pos.y / scaling[1]) * scaling[1] |
187 pos.x = round(pos.x / sx) * sx |
|
188 pos.y = round(pos.y / sy) * sy |
188 return pos |
189 return pos |
189 |
190 |
190 |
191 |
191 def DirectionChoice(v_base, v_target, dir_target): |
192 def DirectionChoice(v_base, v_target, dir_target): |
192 """ |
193 """ |
199 return dir_target |
200 return dir_target |
200 return v_base |
201 return v_base |
201 |
202 |
202 |
203 |
203 def MiterPen(colour, width=1, style=wx.SOLID): |
204 def MiterPen(colour, width=1, style=wx.SOLID): |
204 pen = wx.Pen(colour, width, style) |
205 pen = wx.Pen(colour, round(width), style) |
205 pen.SetJoin(wx.JOIN_MITER) |
206 pen.SetJoin(wx.JOIN_MITER) |
206 pen.SetCap(wx.CAP_PROJECTING) |
207 pen.SetCap(wx.CAP_PROJECTING) |
207 return pen |
208 return pen |
208 |
209 |
209 |
210 |
312 def Clone(self, parent): |
313 def Clone(self, parent): |
313 return Graphic_Element(parent, self.Id) |
314 return Graphic_Element(parent, self.Id) |
314 |
315 |
315 # Changes the block position |
316 # Changes the block position |
316 def SetPosition(self, x, y): |
317 def SetPosition(self, x, y): |
317 self.Pos.x = x |
318 self.Pos.x = int(x) |
318 self.Pos.y = y |
319 self.Pos.y = int(y) |
319 self.RefreshConnected() |
320 self.RefreshConnected() |
320 self.RefreshBoundingBox() |
321 self.RefreshBoundingBox() |
321 |
322 |
322 # Returns the block position |
323 # Returns the block position |
323 def GetPosition(self): |
324 def GetPosition(self): |
324 return self.Pos.x, self.Pos.y |
325 return self.Pos.x, self.Pos.y |
325 |
326 |
326 # Changes the element size |
327 # Changes the element size |
327 def SetSize(self, width, height): |
328 def SetSize(self, width, height): |
328 self.Size.SetWidth(width) |
329 self.Size.SetWidth(int(width)) |
329 self.Size.SetHeight(height) |
330 self.Size.SetHeight(int(height)) |
330 self.RefreshConnectors() |
331 self.RefreshConnectors() |
331 self.RefreshBoundingBox() |
332 self.RefreshBoundingBox() |
332 |
333 |
333 # Returns the element size |
334 # Returns the element size |
334 def GetSize(self): |
335 def GetSize(self): |
429 dc = self.Parent.GetLogicalDC() |
430 dc = self.Parent.GetLogicalDC() |
430 scalex, scaley = dc.GetUserScale() |
431 scalex, scaley = dc.GetUserScale() |
431 pos = event.GetPosition() |
432 pos = event.GetPosition() |
432 pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y)) |
433 pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y)) |
433 |
434 |
434 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE |
435 left = round((self.BoundingBox.x - 2) * scalex - HANDLE_SIZE) |
435 center = (self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2 |
436 center = round((self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2) |
436 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex |
437 right = round((self.BoundingBox.x + self.BoundingBox.width + 2) * scalex) |
437 |
438 |
438 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE |
439 top = round((self.BoundingBox.y - 2) * scaley - HANDLE_SIZE) |
439 middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE // 2 |
440 middle = round((self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE // 2) |
440 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley |
441 bottom = round((self.BoundingBox.y + self.BoundingBox.height + 2) * scaley) |
441 |
442 |
442 extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top) |
443 extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top) |
443 intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE) |
444 intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE) |
444 |
445 |
445 # Verify that this element is selected |
446 # Verify that this element is selected |
677 scalex, scaley = dc.GetUserScale() |
678 scalex, scaley = dc.GetUserScale() |
678 dc.SetUserScale(1, 1) |
679 dc.SetUserScale(1, 1) |
679 dc.SetPen(MiterPen(wx.BLACK)) |
680 dc.SetPen(MiterPen(wx.BLACK)) |
680 dc.SetBrush(wx.BLACK_BRUSH) |
681 dc.SetBrush(wx.BLACK_BRUSH) |
681 |
682 |
682 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE |
683 left = round((self.BoundingBox.x - 2) * scalex - HANDLE_SIZE) |
683 center = (self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2 |
684 center = round((self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2) |
684 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex |
685 right = round((self.BoundingBox.x + self.BoundingBox.width + 2) * scalex) |
685 |
686 |
686 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE |
687 top = round((self.BoundingBox.y - 2) * scaley - HANDLE_SIZE) |
687 middle = (self.BoundingBox.y + self.BoundingBox.height // 2) * scaley - HANDLE_SIZE // 2 |
688 middle = round((self.BoundingBox.y + self.BoundingBox.height // 2) * scaley - HANDLE_SIZE // 2) |
688 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley |
689 bottom = round((self.BoundingBox.y + self.BoundingBox.height + 2) * scaley) |
689 |
690 |
690 for x, y in [(left, top), (center, top), (right, top), |
691 for x, y in [(left, top), (center, top), (right, top), |
691 (left, middle), (right, middle), |
692 (left, middle), (right, middle), |
692 (left, bottom), (center, bottom), (right, bottom)]: |
693 (left, bottom), (center, bottom), (right, bottom)]: |
693 dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE) |
694 dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE) |
1976 |
1977 |
1977 # Calculate the start and end directions |
1978 # Calculate the start and end directions |
1978 self.StartPoint = [None, vector(self.Points[0], self.Points[1])] |
1979 self.StartPoint = [None, vector(self.Points[0], self.Points[1])] |
1979 self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])] |
1980 self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])] |
1980 # Calculate the start and end points |
1981 # Calculate the start and end points |
1981 self.StartPoint[0] = wx.Point(self.Points[0].x + CONNECTOR_SIZE * self.StartPoint[1][0], |
1982 self.StartPoint[0] = wx.Point(self.Points[0].x + round(CONNECTOR_SIZE * self.StartPoint[1][0]), |
1982 self.Points[0].y + CONNECTOR_SIZE * self.StartPoint[1][1]) |
1983 self.Points[0].y + round(CONNECTOR_SIZE * self.StartPoint[1][1])) |
1983 self.EndPoint[0] = wx.Point(self.Points[-1].x + CONNECTOR_SIZE * self.EndPoint[1][0], |
1984 self.EndPoint[0] = wx.Point(self.Points[-1].x + round(CONNECTOR_SIZE * self.EndPoint[1][0]), |
1984 self.Points[-1].y + CONNECTOR_SIZE * self.EndPoint[1][1]) |
1985 self.Points[-1].y + round(CONNECTOR_SIZE * self.EndPoint[1][1])) |
1985 self.Points[0] = self.StartPoint[0] |
1986 self.Points[0] = self.StartPoint[0] |
1986 self.Points[-1] = self.EndPoint[0] |
1987 self.Points[-1] = self.EndPoint[0] |
1987 # Calculate the segments directions |
1988 # Calculate the segments directions |
1988 self.Segments = [] |
1989 self.Segments = [] |
1989 i = 0 |
1990 i = 0 |
1990 while True: |
1991 while True: |
1991 lp = len(self.Points) |
1992 lp = len(self.Points) |
1992 if i > lp - 2: |
1993 if i > lp - 2: |
1993 break |
1994 break |
1994 |
1995 |
1995 segment = vector(self.Points[i], self.Points[i + 1]) |
1996 segment = tuple(map(round,vector(self.Points[i], self.Points[i + 1]))) |
1996 |
1997 |
1997 # merge segment if requested |
1998 # merge segment if requested |
1998 if merge_segments and 0 < i and \ |
1999 if merge_segments and 0 < i and \ |
1999 self.Segments[-1] == segment: |
2000 self.Segments[-1] == segment: |
2000 self.Points.pop(i) |
2001 self.Points.pop(i) |
2024 return None |
2025 return None |
2025 |
2026 |
2026 # Returns a list of the position of all wire points |
2027 # Returns a list of the position of all wire points |
2027 def GetPoints(self, invert=False): |
2028 def GetPoints(self, invert=False): |
2028 points = self.VerifyPoints() |
2029 points = self.VerifyPoints() |
2029 points[0] = wx.Point(points[0].x - CONNECTOR_SIZE * self.StartPoint[1][0], |
2030 points[0] = wx.Point(points[0].x - round(CONNECTOR_SIZE * self.StartPoint[1][0]), |
2030 points[0].y - CONNECTOR_SIZE * self.StartPoint[1][1]) |
2031 points[0].y - round(CONNECTOR_SIZE * self.StartPoint[1][1])) |
2031 points[-1] = wx.Point(points[-1].x - CONNECTOR_SIZE * self.EndPoint[1][0], |
2032 points[-1] = wx.Point(points[-1].x - round(CONNECTOR_SIZE * self.EndPoint[1][0]), |
2032 points[-1].y - CONNECTOR_SIZE * self.EndPoint[1][1]) |
2033 points[-1].y - round(CONNECTOR_SIZE * self.EndPoint[1][1])) |
2033 # An inversion of the list is asked |
2034 # An inversion of the list is asked |
2034 if invert: |
2035 if invert: |
2035 points.reverse() |
2036 points.reverse() |
2036 return points |
2037 return points |
2037 |
2038 |
2066 |
2067 |
2067 # Update the wire points position by keeping at most possible the current positions |
2068 # Update the wire points position by keeping at most possible the current positions |
2068 def GeneratePoints(self, realpoints=True): |
2069 def GeneratePoints(self, realpoints=True): |
2069 i = 0 |
2070 i = 0 |
2070 # Calculate the start enad end points with the minimum segment size in the right direction |
2071 # Calculate the start enad end points with the minimum segment size in the right direction |
2071 end = wx.Point(self.EndPoint[0].x + self.EndPoint[1][0] * MIN_SEGMENT_SIZE, |
2072 end = wx.Point(self.EndPoint[0].x + round(self.EndPoint[1][0] * MIN_SEGMENT_SIZE), |
2072 self.EndPoint[0].y + self.EndPoint[1][1] * MIN_SEGMENT_SIZE) |
2073 self.EndPoint[0].y + round(self.EndPoint[1][1] * MIN_SEGMENT_SIZE)) |
2073 start = wx.Point(self.StartPoint[0].x + self.StartPoint[1][0] * MIN_SEGMENT_SIZE, |
2074 start = wx.Point(self.StartPoint[0].x + round(self.StartPoint[1][0] * MIN_SEGMENT_SIZE), |
2074 self.StartPoint[0].y + self.StartPoint[1][1] * MIN_SEGMENT_SIZE) |
2075 self.StartPoint[0].y + round(self.StartPoint[1][1] * MIN_SEGMENT_SIZE)) |
2075 # Evaluate the point till it's the last |
2076 # Evaluate the point till it's the last |
2076 while i < len(self.Points) - 1: |
2077 while i < len(self.Points) - 1: |
2077 # The next point is the last |
2078 # The next point is the last |
2078 if i + 1 == len(self.Points) - 1: |
2079 if i + 1 == len(self.Points) - 1: |
2079 # Calculate the direction from current point to end point |
2080 # Calculate the direction from current point to end point |
2080 v_end = vector(self.Points[i], end) |
2081 v_end = tuple(map(round,vector(self.Points[i], end))) |
2081 # The current point is the first |
2082 # The current point is the first |
2082 if i == 0: |
2083 if i == 0: |
2083 # If the end point is not in the start direction, a point is added |
2084 # If the end point is not in the start direction, a point is added |
2084 if v_end != self.Segments[0] or v_end == self.EndPoint[1]: |
2085 if v_end != self.Segments[0] or v_end == self.EndPoint[1]: |
2085 self.Points.insert(1, wx.Point(start.x, start.y)) |
2086 self.Points.insert(1, wx.Point(start.x, start.y)) |
2197 self.Points.insert(1, wx.Point(start.x, start.y)) |
2198 self.Points.insert(1, wx.Point(start.x, start.y)) |
2198 self.Segments.insert( |
2199 self.Segments.insert( |
2199 1, |
2200 1, |
2200 DirectionChoice((self.Segments[0][1], |
2201 DirectionChoice((self.Segments[0][1], |
2201 self.Segments[0][0]), |
2202 self.Segments[0][0]), |
2202 vector(start, self.Points[1]), |
2203 tuple(map(round,vector(start, self.Points[1]))), |
2203 self.Segments[1])) |
2204 self.Segments[1])) |
2204 else: |
2205 else: |
2205 self.Points[1].x, self.Points[1].y = start.x, start.y |
2206 self.Points[1].x, self.Points[1].y = start.x, start.y |
2206 else: |
2207 else: |
2207 # Next point is aligned with current point |
2208 # Next point is aligned with current point |
2284 # Calculate the real points from the new size, it's important for |
2285 # Calculate the real points from the new size, it's important for |
2285 # keeping a proportionality in the points position with the size |
2286 # keeping a proportionality in the points position with the size |
2286 # during a resize dragging |
2287 # during a resize dragging |
2287 for i, point in enumerate(self.RealPoints): |
2288 for i, point in enumerate(self.RealPoints): |
2288 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected): |
2289 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected): |
2289 point[0] = point[0] * width / max(lastwidth, 1) |
2290 point[0] = int(point[0] * width / max(lastwidth, 1)) |
2290 point[1] = point[1] * height / max(lastheight, 1) |
2291 point[1] = int(point[1] * height / max(lastheight, 1)) |
2291 # Calculate the correct position of the points from real points |
2292 # Calculate the correct position of the points from real points |
2292 for i, point in enumerate(self.RealPoints): |
2293 for i, point in enumerate(self.RealPoints): |
2293 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected): |
2294 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected): |
2294 if i == 0: |
2295 if i == 0: |
2295 dir = self.StartPoint[1] |
2296 dir = self.StartPoint[1] |
2669 dc.SetLogicalFunction(wx.AND) |
2670 dc.SetLogicalFunction(wx.AND) |
2670 # Draw the start and end points if they are not connected or the mouse is over them |
2671 # Draw the start and end points if they are not connected or the mouse is over them |
2671 if len(self.Points) > 0 and (not self.StartConnected or self.OverStart): |
2672 if len(self.Points) > 0 and (not self.StartConnected or self.OverStart): |
2672 dc.DrawCircle(round(self.Points[0].x * scalex), |
2673 dc.DrawCircle(round(self.Points[0].x * scalex), |
2673 round(self.Points[0].y * scaley), |
2674 round(self.Points[0].y * scaley), |
2674 (POINT_RADIUS + 1) * scalex + 2) |
2675 round((POINT_RADIUS + 1) * scalex + 2)) |
2675 if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd): |
2676 if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd): |
2676 dc.DrawCircle(self.Points[-1].x * scalex, self.Points[-1].y * scaley, (POINT_RADIUS + 1) * scalex + 2) |
2677 dc.DrawCircle(round(self.Points[-1].x * scalex), round(self.Points[-1].y * scaley), round((POINT_RADIUS + 1) * scalex + 2)) |
2677 # Draw the wire lines and the last point (it seems that DrawLines stop before the last point) |
2678 # Draw the wire lines and the last point (it seems that DrawLines stop before the last point) |
2678 if len(self.Points) > 1: |
2679 if len(self.Points) > 1: |
2679 points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex), |
2680 points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex), |
2680 round((self.Points[0].y - self.Segments[0][1]) * scaley))] |
2681 round((self.Points[0].y - self.Segments[0][1]) * scaley))] |
2681 points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]]) |
2682 points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]]) |
2920 dc.SetUserScale(1, 1) |
2921 dc.SetUserScale(1, 1) |
2921 dc.SetPen(MiterPen(HIGHLIGHTCOLOR)) |
2922 dc.SetPen(MiterPen(HIGHLIGHTCOLOR)) |
2922 dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR)) |
2923 dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR)) |
2923 dc.SetLogicalFunction(wx.AND) |
2924 dc.SetLogicalFunction(wx.AND) |
2924 |
2925 |
2925 left = (self.Pos.x - 1) * scalex - 2 |
2926 left = round((self.Pos.x - 1) * scalex - 2) |
2926 right = (self.Pos.x + self.Size[0] + 1) * scalex + 2 |
2927 right = round((self.Pos.x + self.Size[0] + 1) * scalex + 2) |
2927 top = (self.Pos.y - 1) * scaley - 2 |
2928 top = round((self.Pos.y - 1) * scaley - 2) |
2928 bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2 |
2929 bottom = round((self.Pos.y + self.Size[1] + 1) * scaley + 2) |
2929 angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2 |
2930 angle_top = round((self.Pos.x + self.Size[0] - 9) * scalex + 2) |
2930 angle_right = (self.Pos.y + 9) * scaley - 2 |
2931 angle_right = round((self.Pos.y + 9) * scaley - 2) |
2931 |
2932 |
2932 polygon = [wx.Point(left, top), wx.Point(angle_top, top), |
2933 polygon = [wx.Point(left, top), wx.Point(angle_top, top), |
2933 wx.Point(right, angle_right), wx.Point(right, bottom), |
2934 wx.Point(right, angle_right), wx.Point(right, bottom), |
2934 wx.Point(left, bottom)] |
2935 wx.Point(left, bottom)] |
2935 dc.DrawPolygon(polygon) |
2936 dc.DrawPolygon(polygon) |