37 """ |
37 """ |
38 Class that implements a custom tool tip |
38 Class that implements a custom tool tip |
39 """ |
39 """ |
40 |
40 |
41 class CustomToolTip(wx.PopupWindow): |
41 class CustomToolTip(wx.PopupWindow): |
42 |
42 |
43 def __init__(self, parent, tip, restricted=True): |
43 def __init__(self, parent, tip, restricted=True): |
44 """ |
44 """ |
45 Constructor |
45 Constructor |
46 @param parent: Parent window |
46 @param parent: Parent window |
47 @param tip: Tip text (may be multiline) |
47 @param tip: Tip text (may be multiline) |
48 @param restricted: Tool tip must follow size restriction in line and |
48 @param restricted: Tool tip must follow size restriction in line and |
49 characters number defined (default True) |
49 characters number defined (default True) |
50 """ |
50 """ |
51 wx.PopupWindow.__init__(self, parent) |
51 wx.PopupWindow.__init__(self, parent) |
52 |
52 |
53 self.Restricted = restricted |
53 self.Restricted = restricted |
54 |
54 |
55 self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) |
55 self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) |
56 self.SetTip(tip) |
56 self.SetTip(tip) |
57 |
57 |
58 # Initialize text font style |
58 # Initialize text font style |
59 self.Font = wx.Font( |
59 self.Font = wx.Font( |
60 faces["size"], |
60 faces["size"], |
61 wx.SWISS, |
61 wx.SWISS, |
62 wx.NORMAL, |
62 wx.NORMAL, |
63 wx.NORMAL, |
63 wx.NORMAL, |
64 faceName = faces["mono"]) |
64 faceName = faces["mono"]) |
65 |
65 |
66 self.Bind(wx.EVT_PAINT, self.OnPaint) |
66 self.Bind(wx.EVT_PAINT, self.OnPaint) |
67 |
67 |
68 def SetFont(self, font): |
68 def SetFont(self, font): |
69 """ |
69 """ |
70 Set tool tip text font style |
70 Set tool tip text font style |
71 @param font: wx.Font object containing font style |
71 @param font: wx.Font object containing font style |
72 """ |
72 """ |
73 self.Font = font |
73 self.Font = font |
74 self.RefreshTip() |
74 self.RefreshTip() |
75 |
75 |
76 def SetTip(self, tip): |
76 def SetTip(self, tip): |
77 """ |
77 """ |
78 Set tool tip text |
78 Set tool tip text |
79 @param tip: Tool tip text |
79 @param tip: Tool tip text |
80 """ |
80 """ |
95 self.Tip.append(new_line) |
95 self.Tip.append(new_line) |
96 new_line = word |
96 new_line = word |
97 self.Tip.append(new_line) |
97 self.Tip.append(new_line) |
98 else: |
98 else: |
99 self.Tip.append(line) |
99 self.Tip.append(line) |
100 |
100 |
101 # Restrict number of lines |
101 # Restrict number of lines |
102 if len(self.Tip) > TOOLTIP_MAX_LINE: |
102 if len(self.Tip) > TOOLTIP_MAX_LINE: |
103 self.Tip = self.Tip[:TOOLTIP_MAX_LINE] |
103 self.Tip = self.Tip[:TOOLTIP_MAX_LINE] |
104 |
104 |
105 # Add ... to the end of last line to indicate that tool tip |
105 # Add ... to the end of last line to indicate that tool tip |
106 # text is too long |
106 # text is too long |
107 if len(self.Tip[-1]) < TOOLTIP_MAX_CHARACTERS - 3: |
107 if len(self.Tip[-1]) < TOOLTIP_MAX_CHARACTERS - 3: |
108 self.Tip[-1] += "..." |
108 self.Tip[-1] += "..." |
109 else: |
109 else: |
110 self.Tip[-1] = self.Tip[-1]\ |
110 self.Tip[-1] = self.Tip[-1]\ |
111 [:TOOLTIP_MAX_CHARACTERS - 3] + "..." |
111 [:TOOLTIP_MAX_CHARACTERS - 3] + "..." |
112 else: |
112 else: |
113 self.Tip = tip.splitlines() |
113 self.Tip = tip.splitlines() |
114 |
114 |
115 # Prevent to call wx method in non-wx threads |
115 # Prevent to call wx method in non-wx threads |
116 wx.CallAfter(self.RefreshTip) |
116 wx.CallAfter(self.RefreshTip) |
117 |
117 |
118 def SetToolTipPosition(self, pos): |
118 def SetToolTipPosition(self, pos): |
119 """ |
119 """ |
120 Set tool tip position |
120 Set tool tip position |
121 @param pos: New tool tip position |
121 @param pos: New tool tip position |
122 """ |
122 """ |
123 # Get screen size to prevent tool tip to go out of the screen |
123 # Get screen size to prevent tool tip to go out of the screen |
124 screen_width, screen_height = wx.GetDisplaySize() |
124 screen_width, screen_height = wx.GetDisplaySize() |
125 |
125 |
126 # Calculate position of tool tip to stay in screen limits |
126 # Calculate position of tool tip to stay in screen limits |
127 tip_width, tip_height = self.GetToolTipSize() |
127 tip_width, tip_height = self.GetToolTipSize() |
128 self.SetPosition(wx.Point( |
128 self.SetPosition(wx.Point( |
129 max(0, min(pos.x, screen_width - tip_width)), |
129 max(0, min(pos.x, screen_width - tip_width)), |
130 max(0, min(pos.y, screen_height - tip_height)))) |
130 max(0, min(pos.y, screen_height - tip_height)))) |
131 |
131 |
132 def GetToolTipSize(self): |
132 def GetToolTipSize(self): |
133 """ |
133 """ |
134 Get tool tip size according to tip text and restriction |
134 Get tool tip size according to tip text and restriction |
135 @return: wx.Size(tool_tip_width, tool_tip_height) |
135 @return: wx.Size(tool_tip_width, tool_tip_height) |
136 """ |
136 """ |
137 max_width = max_height = 0 |
137 max_width = max_height = 0 |
138 |
138 |
139 # Create a memory DC for calculating text extent |
139 # Create a memory DC for calculating text extent |
140 dc = wx.MemoryDC() |
140 dc = wx.MemoryDC() |
141 dc.SetFont(self.Font) |
141 dc.SetFont(self.Font) |
142 |
142 |
143 # Compute max tip text size |
143 # Compute max tip text size |
144 for line in self.Tip: |
144 for line in self.Tip: |
145 w, h = dc.GetTextExtent(line) |
145 w, h = dc.GetTextExtent(line) |
146 max_width = max(max_width, w) |
146 max_width = max(max_width, w) |
147 max_height += h |
147 max_height += h |
148 |
148 |
149 return wx.Size(max_width + 4, max_height + 4) |
149 return wx.Size(max_width + 4, max_height + 4) |
150 |
150 |
151 def RefreshTip(self): |
151 def RefreshTip(self): |
152 """ |
152 """ |
153 Refresh tip on screen |
153 Refresh tip on screen |
154 """ |
154 """ |
155 # Prevent to call this function if tool tip destroyed |
155 # Prevent to call this function if tool tip destroyed |
156 if self: |
156 if self: |
157 # Refresh tool tip size and position |
157 # Refresh tool tip size and position |
158 self.SetClientSize(self.GetToolTipSize()) |
158 self.SetClientSize(self.GetToolTipSize()) |
159 |
159 |
160 # Redraw tool tip |
160 # Redraw tool tip |
161 self.Refresh() |
161 self.Refresh() |
162 |
162 |
163 def OnPaint(self, event): |
163 def OnPaint(self, event): |
164 """ |
164 """ |
165 Callback for Paint Event |
165 Callback for Paint Event |
166 @param event: Paint event |
166 @param event: Paint event |
167 """ |
167 """ |
168 # Get buffered paint DC for tool tip |
168 # Get buffered paint DC for tool tip |
169 dc = wx.AutoBufferedPaintDC(self) |
169 dc = wx.AutoBufferedPaintDC(self) |
170 dc.Clear() |
170 dc.Clear() |
171 |
171 |
172 # Set DC drawing style |
172 # Set DC drawing style |
173 dc.SetPen(wx.BLACK_PEN) |
173 dc.SetPen(wx.BLACK_PEN) |
174 dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170))) |
174 dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170))) |
175 dc.SetFont(self.Font) |
175 dc.SetFont(self.Font) |
176 |
176 |
177 # Draw Tool tip |
177 # Draw Tool tip |
178 dc.BeginDrawing() |
178 dc.BeginDrawing() |
179 tip_width, tip_height = self.GetToolTipSize() |
179 tip_width, tip_height = self.GetToolTipSize() |
180 |
180 |
181 # Draw background rectangle |
181 # Draw background rectangle |
182 dc.DrawRectangle(0, 0, tip_width, tip_height) |
182 dc.DrawRectangle(0, 0, tip_width, tip_height) |
183 |
183 |
184 # Draw tool tip text |
184 # Draw tool tip text |
185 line_offset = 0 |
185 line_offset = 0 |
186 for line in self.Tip: |
186 for line in self.Tip: |
187 dc.DrawText(line, 2, line_offset + 2) |
187 dc.DrawText(line, 2, line_offset + 2) |
188 line_width, line_height = dc.GetTextExtent(line) |
188 line_width, line_height = dc.GetTextExtent(line) |
189 line_offset += line_height |
189 line_offset += line_height |
190 |
190 |
191 dc.EndDrawing() |
191 dc.EndDrawing() |
192 |
192 |
193 event.Skip() |
193 event.Skip() |