controls/CustomToolTip.py
changeset 1730 64d8f52bc8c8
parent 1571 486f94a8032c
child 1736 7e61baa047f0
equal deleted inserted replaced
1726:d51af006fa6b 1730:64d8f52bc8c8
    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()