def OnFirstLayout(self, sender, e): p = self.popup if p.IsOpen: child = p.Child rv = wpf.get_root_visual() pos, end, line = utils.get_current_line(self.tbx) offset = wpf.get_position(self.tbx) sz = wpf.measure_string(self._prefix, self.tbx.FontFamily, self.tbx.FontSize) desired_sz = wpf.measure(child) p.VerticalOffset = offset.Y + (self.tbx.Text[:pos].count('\n')+1) * sz.Height if p.VerticalOffset > rv.ActualHeight/2: # Display above the line p.VerticalOffset -= desired_sz.Height + sz.Height if p.VerticalOffset < 10: child.MaxHeight = desired_sz.Height - (10 - p.VerticalOffset) p.VerticalOffset = 10 elif p.VerticalOffset + desired_sz.Height + 10 > rv.ActualHeight: child.MaxHeight = rv.ActualHeight - p.VerticalOffset - 10 p.HorizontalOffset = offset.X + sz.Width if p.HorizontalOffset + desired_sz.Width > rv.ActualWidth-10: # Display further left p.HorizontalOffset = rv.ActualWidth - 10 - desired_sz.Width if p.Child is self.member_lbx: start = end - len(line) self.update_member_list(line[:pos-start])
def OnUpdateCursor(self, *ignore): if self._can_update: p = self.popup offset = wpf.get_position(self.tbx) pos, end, line = utils.get_current_line(self.tbx) sz = wpf.measure_string(self.tbx.Text[end-len(line):pos], self.tbx.FontFamily, self.tbx.FontSize) x = offset.X + sz.Width y = offset.Y + self.tbx.Text[:pos].count('\n') * sz.Height if x != p.HorizontalOffset: p.HorizontalOffset = x if y != p.VerticalOffset: p.VerticalOffset = y # Check if the cursor is out of bounds or if the textbox is hidden cursor_pos = wpf.Point(x, y) bounds = wpf.Rect(wpf.get_position(self.bounding_sv), wpf.Size(self.bounding_sv.ViewportWidth, self.bounding_sv.ViewportHeight)) if bounds.Contains(wpf.Point(cursor_pos.X, cursor_pos.Y + self.cursor.ActualHeight/2)) and bounds.Contains(offset): if not p.IsOpen: self.show() else: if p.IsOpen: self.hide()
def complete(self): pos, end, line = utils.get_current_line(self.tbx) completion = self.find_completion(line[:pos]) if completion is not None: self.tbx.Text = self.tbx.Text[:pos] + completion + self.tbx.Text[pos:] self.tbx.SelectionStart = pos + len(completion) return True return False
def show(self, child): p = self.popup p.Child = child child.MaxHeight = Double.PositiveInfinity pos, end, line = utils.get_current_line(self.tbx) self._prefix = self.tbx.Text[end-len(line):pos] wpf.on_first_layout(child, self.OnFirstLayout) p.IsOpen = True
def complete_from_member_list(self): if self.member_lbx.SelectedItem: pos, end, line = utils.get_current_line(self.tbx) start = end-len(line) s = ''.join(self._prefix.rpartition('.')[:2]) + self.member_lbx.SelectedItem self.tbx.Text = self.tbx.Text[:start] + s + self.tbx.Text[pos:] self.tbx.SelectionStart = start + len(s) self.hide() return True else: self.hide() return False
def OnTextChanged(self, sender, e): completions = self.filterCompletions self.filterCompletions = False pos, end, line = utils.get_current_line(self.tbx) if self.popup.IsOpen and self._prefix not in line: self.hide() if pos > 0: start = end - len(line) if self.tbx.Text[pos-1] == '.' and pos > 1: if self.tbx.Text[pos-2].isalnum() or self.tbx.Text[pos-2] == '_': self.show_member_list(line[:pos-start]) elif self.tbx.Text[pos-1] == '(': self.hide() self.show_calltip(line[:pos-start-1]) elif self.tbx.Text[pos-1] == ')': self._show_calltip = None self.hide() elif '.' in line: if completions: self.show_member_list(line[:pos-start], completions) elif self.popup.IsOpen and self.popup.Child is self.member_list: self.update_member_list(line[:pos-start])
def get_current_line(self): return utils.get_current_line(self.prompt)