controls/CustomToolTip.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1847 6198190bc121
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    24 
    24 
    25 import wx
    25 import wx
    26 
    26 
    27 from controls.CustomStyledTextCtrl import faces
    27 from controls.CustomStyledTextCtrl import faces
    28 
    28 
    29 TOOLTIP_MAX_CHARACTERS = 30 # Maximum number of characters by line in ToolTip
    29 TOOLTIP_MAX_CHARACTERS = 30  # Maximum number of characters by line in ToolTip
    30 TOOLTIP_MAX_LINE = 5        # Maximum number of line in ToolTip
    30 TOOLTIP_MAX_LINE = 5         # Maximum number of line in ToolTip
    31 TOOLTIP_WAIT_PERIOD = 0.5   # Wait period before displaying tooltip in second
    31 TOOLTIP_WAIT_PERIOD = 0.5    # Wait period before displaying tooltip in second
    32 
    32 
    33 #-------------------------------------------------------------------------------
    33 # -------------------------------------------------------------------------------
    34 #                               Custom ToolTip
    34 #                               Custom ToolTip
    35 #-------------------------------------------------------------------------------
    35 # -------------------------------------------------------------------------------
    36 
    36 
    37 """
       
    38 Class that implements a custom tool tip
       
    39 """
       
    40 
    37 
    41 class CustomToolTip(wx.PopupWindow):
    38 class CustomToolTip(wx.PopupWindow):
    42     
    39     """
       
    40     Class that implements a custom tool tip
       
    41     """
       
    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         """
    85                 if line != "":
    85                 if line != "":
    86                     words = line.split()
    86                     words = line.split()
    87                     new_line = words[0]
    87                     new_line = words[0]
    88                     for word in words[1:]:
    88                     for word in words[1:]:
    89                         # Add word to line
    89                         # Add word to line
    90                         if len(new_line + " " + word) <= \
    90                         if len(new_line + " " + word) <= TOOLTIP_MAX_CHARACTERS:
    91                             TOOLTIP_MAX_CHARACTERS:
       
    92                             new_line += " " + word
    91                             new_line += " " + word
    93                         # Create new line
    92                         # Create new line
    94                         else:
    93                         else:
    95                             self.Tip.append(new_line)
    94                             self.Tip.append(new_line)
    96                             new_line = word
    95                             new_line = word
    97                     self.Tip.append(new_line)
    96                     self.Tip.append(new_line)
    98                 else:
    97                 else:
    99                     self.Tip.append(line)
    98                     self.Tip.append(line)
   100             
    99 
   101             # Restrict number of lines
   100             # Restrict number of lines
   102             if len(self.Tip) > TOOLTIP_MAX_LINE:
   101             if len(self.Tip) > TOOLTIP_MAX_LINE:
   103                 self.Tip = self.Tip[:TOOLTIP_MAX_LINE]
   102                 self.Tip = self.Tip[:TOOLTIP_MAX_LINE]
   104                 
   103 
   105                 # Add ... to the end of last line to indicate that tool tip
   104                 # Add ... to the end of last line to indicate that tool tip
   106                 # text is too long
   105                 # text is too long
   107                 if len(self.Tip[-1]) < TOOLTIP_MAX_CHARACTERS - 3:
   106                 if len(self.Tip[-1]) < TOOLTIP_MAX_CHARACTERS - 3:
   108                     self.Tip[-1] += "..."
   107                     self.Tip[-1] += "..."
   109                 else:
   108                 else:
   110                     self.Tip[-1] = self.Tip[-1]\
   109                     self.Tip[-1] = self.Tip[-1][:TOOLTIP_MAX_CHARACTERS - 3] + \
   111                         [:TOOLTIP_MAX_CHARACTERS - 3] + "..."
   110                                    "..."
   112         else:
   111         else:
   113             self.Tip = tip.splitlines()
   112             self.Tip = tip.splitlines()
   114         
   113 
   115         # Prevent to call wx method in non-wx threads
   114         # Prevent to call wx method in non-wx threads
   116         wx.CallAfter(self.RefreshTip)
   115         wx.CallAfter(self.RefreshTip)
   117     
   116 
   118     def SetToolTipPosition(self, pos):
   117     def SetToolTipPosition(self, pos):
   119         """
   118         """
   120         Set tool tip position
   119         Set tool tip position
   121         @param pos: New tool tip position
   120         @param pos: New tool tip position
   122         """
   121         """
   123         # Get screen size to prevent tool tip to go out of the screen
   122         # Get screen size to prevent tool tip to go out of the screen
   124         screen_width, screen_height = wx.GetDisplaySize()
   123         screen_width, screen_height = wx.GetDisplaySize()
   125         
   124 
   126         # Calculate position of tool tip to stay in screen limits
   125         # Calculate position of tool tip to stay in screen limits
   127         tip_width, tip_height = self.GetToolTipSize()
   126         tip_width, tip_height = self.GetToolTipSize()
   128         self.SetPosition(wx.Point(
   127         self.SetPosition(wx.Point(
   129             max(0, min(pos.x, screen_width - tip_width)),
   128             max(0, min(pos.x, screen_width - tip_width)),
   130             max(0, min(pos.y, screen_height - tip_height))))
   129             max(0, min(pos.y, screen_height - tip_height))))
   131     
   130 
   132     def GetToolTipSize(self):
   131     def GetToolTipSize(self):
   133         """
   132         """
   134         Get tool tip size according to tip text and restriction
   133         Get tool tip size according to tip text and restriction
   135         @return: wx.Size(tool_tip_width, tool_tip_height)
   134         @return: wx.Size(tool_tip_width, tool_tip_height)
   136         """
   135         """
   137         max_width = max_height = 0
   136         max_width = max_height = 0
   138         
   137 
   139         # Create a memory DC for calculating text extent
   138         # Create a memory DC for calculating text extent
   140         dc = wx.MemoryDC()
   139         dc = wx.MemoryDC()
   141         dc.SetFont(self.Font)
   140         dc.SetFont(self.Font)
   142         
   141 
   143         # Compute max tip text size
   142         # Compute max tip text size
   144         for line in self.Tip:
   143         for line in self.Tip:
   145             w, h = dc.GetTextExtent(line)
   144             w, h = dc.GetTextExtent(line)
   146             max_width = max(max_width, w)
   145             max_width = max(max_width, w)
   147             max_height += h
   146             max_height += h
   148         
   147 
   149         return wx.Size(max_width + 4, max_height + 4)
   148         return wx.Size(max_width + 4, max_height + 4)
   150     
   149 
   151     def RefreshTip(self):
   150     def RefreshTip(self):
   152         """
   151         """
   153         Refresh tip on screen
   152         Refresh tip on screen
   154         """
   153         """
   155         # Prevent to call this function if tool tip destroyed
   154         # Prevent to call this function if tool tip destroyed
   156         if self:
   155         if self:
   157             # Refresh tool tip size and position
   156             # Refresh tool tip size and position
   158             self.SetClientSize(self.GetToolTipSize())
   157             self.SetClientSize(self.GetToolTipSize())
   159             
   158 
   160             # Redraw tool tip
   159             # Redraw tool tip
   161             self.Refresh()
   160             self.Refresh()
   162     
   161 
   163     def OnPaint(self, event):
   162     def OnPaint(self, event):
   164         """
   163         """
   165         Callback for Paint Event
   164         Callback for Paint Event
   166         @param event: Paint event
   165         @param event: Paint event
   167         """
   166         """
   168         # Get buffered paint DC for tool tip
   167         # Get buffered paint DC for tool tip
   169         dc = wx.AutoBufferedPaintDC(self)
   168         dc = wx.AutoBufferedPaintDC(self)
   170         dc.Clear()
   169         dc.Clear()
   171         
   170 
   172         # Set DC drawing style
   171         # Set DC drawing style
   173         dc.SetPen(wx.BLACK_PEN)
   172         dc.SetPen(wx.BLACK_PEN)
   174         dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170)))
   173         dc.SetBrush(wx.Brush(wx.Colour(255, 238, 170)))
   175         dc.SetFont(self.Font)
   174         dc.SetFont(self.Font)
   176         
   175 
   177         # Draw Tool tip
   176         # Draw Tool tip
   178         dc.BeginDrawing()
   177         dc.BeginDrawing()
   179         tip_width, tip_height = self.GetToolTipSize()
   178         tip_width, tip_height = self.GetToolTipSize()
   180         
   179 
   181         # Draw background rectangle
   180         # Draw background rectangle
   182         dc.DrawRectangle(0, 0, tip_width, tip_height)
   181         dc.DrawRectangle(0, 0, tip_width, tip_height)
   183         
   182 
   184         # Draw tool tip text
   183         # Draw tool tip text
   185         line_offset = 0
   184         line_offset = 0
   186         for line in self.Tip:
   185         for line in self.Tip:
   187             dc.DrawText(line, 2, line_offset + 2)
   186             dc.DrawText(line, 2, line_offset + 2)
   188             line_width, line_height = dc.GetTextExtent(line)
   187             line_width, line_height = dc.GetTextExtent(line)
   189             line_offset += line_height
   188             line_offset += line_height
   190         
   189 
   191         dc.EndDrawing()
   190         dc.EndDrawing()
   192         
   191 
   193         event.Skip()
   192         event.Skip()