<s> '''<STR_LIT>''' <EOL> __docformat__ = '<STR_LIT>' <EOL> __version__ = '<STR_LIT>' <EOL> import re <EOL> import time <EOL> from pyglet import clock <EOL> from pyglet import event <EOL> from pyglet . window import key <EOL> class Caret ( object ) : <EOL> '''<STR_LIT>''' <EOL> _next_word_re = re . compile ( r'<STR_LIT>' ) <EOL> _previous_word_re = re . compile ( r'<STR_LIT>' ) <EOL> _next_para_re = re . compile ( r'<STR_LIT:\n>' , flags = re . DOTALL ) <EOL> _previous_para_re = re . compile ( r'<STR_LIT:\n>' , flags = re . DOTALL ) <EOL> _position = <NUM_LIT:0> <EOL> _active = True <EOL> _visible = True <EOL> _blink_visible = True <EOL> _click_count = <NUM_LIT:0> <EOL> _click_time = <NUM_LIT:0> <EOL> PERIOD = <NUM_LIT:0.5> <EOL> SCROLL_INCREMENT = <NUM_LIT:12> * <NUM_LIT> // <NUM_LIT> <EOL> def __init__ ( self , layout , batch = None , color = ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ) : <EOL> '''<STR_LIT>''' <EOL> from pyglet import gl <EOL> self . _layout = layout <EOL> if batch is None : <EOL> batch = layout . batch <EOL> r , g , b = color <EOL> colors = ( r , g , b , <NUM_LIT:255> , r , g , b , <NUM_LIT:255> ) <EOL> self . _list = batch . add ( <NUM_LIT:2> , gl . GL_LINES , layout . background_group , <EOL> '<STR_LIT>' , ( '<STR_LIT>' , colors ) ) <EOL> self . _ideal_x = None <EOL> self . _ideal_line = None <EOL> self . _next_attributes = { } <EOL> self . visible = True <EOL> layout . push_handlers ( self ) <EOL> def delete ( self ) : <EOL> '''<STR_LIT>''' <EOL> self . _list . delete ( ) <EOL> self . _layout . remove_handlers ( self ) <EOL> def _blink ( self , dt ) : <EOL> if self . PERIOD : <EOL> self . _blink_visible = not self . _blink_visible <EOL> if self . _visible and self . _active and self . _blink_visible : <EOL> alpha = <NUM_LIT:255> <EOL> else : <EOL> alpha = <NUM_LIT:0> <EOL> self . _list . colors [ <NUM_LIT:3> ] = alpha <EOL> self . _list . colors [ <NUM_LIT:7> ] = alpha <EOL> def _nudge ( self ) : <EOL> self . visible = True <EOL> def _set_visible ( self , visible ) : <EOL> self . _visible = visible <EOL> clock . unschedule ( self . _blink ) <EOL> if visible and self . _active and self . PERIOD : <EOL> clock . schedule_interval ( self . _blink , self . PERIOD ) <EOL> self . _blink_visible = False <EOL> self . _blink ( <NUM_LIT:0> ) <EOL> def _get_visible ( self ) : <EOL> return self . _visible <EOL> visible = property ( _get_visible , _set_visible , <EOL> doc = '''<STR_LIT>''' ) <EOL> def _set_color ( self , color ) : <EOL> self . _list . colors [ : <NUM_LIT:3> ] = color <EOL> self . _list . colors [ <NUM_LIT:4> : <NUM_LIT:7> ] = color <EOL> def _get_color ( self ) : <EOL> return self . _list . colors [ : <NUM_LIT:3> ] <EOL> color = property ( _get_color , _set_color , <EOL> doc = '''<STR_LIT>''' ) <EOL> def _set_position ( self , index ) : <EOL> self . _position = index <EOL> self . _next_attributes . clear ( ) <EOL> self . _update ( ) <EOL> def _get_position ( self ) : <EOL> return self . _position <EOL> position = property ( _get_position , _set_position , <EOL> doc = '''<STR_LIT>''' ) <EOL> _mark = None <EOL> def _set_mark ( self , mark ) : <EOL> self . _mark = mark <EOL> self . _update ( line = self . _ideal_line ) <EOL> if mark is None : <EOL> self . _layout . set_selection ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> def _get_mark ( self ) : <EOL> return self . _mark <EOL> mark = property ( _get_mark , _set_mark , <EOL> doc = '''<STR_LIT>''' ) <EOL> def _set_line ( self , line ) : <EOL> if self . _ideal_x is None : <EOL> self . _ideal_x , _ = self . _layout . get_point_from_position ( self . _position ) <EOL> self . _position = self . _layout . get_position_on_line ( line , self . _ideal_x ) <EOL> self . _update ( line = line , update_ideal_x = False ) <EOL> def _get_line ( self ) : <EOL> if self . _ideal_line is not None : <EOL> return self . _ideal_line <EOL> else : <EOL> return self . _layout . get_line_from_position ( self . _position ) <EOL> line = property ( _get_line , _set_line , <EOL> doc = '''<STR_LIT>''' ) <EOL> def get_style ( self , attribute ) : <EOL> '''<STR_LIT>''' <EOL> if self . _mark is None or self . _mark == self . _position : <EOL> try : <EOL> return self . _next_attributes [ attribute ] <EOL> except KeyError : <EOL> return self . _layout . document . get_style ( attribute , <EOL> self . _position ) <EOL> start = min ( self . _position , self . _mark ) <EOL> end = max ( self . _position , self . _mark ) <EOL> return self . _layout . document . get_style_range ( attribute , start , end ) <EOL> def set_style ( self , attributes ) : <EOL> '''<STR_LIT>''' <EOL> if self . _mark is None or self . _mark == self . _position : <EOL> self . _next_attributes . update ( attributes ) <EOL> return <EOL> start = min ( self . _position , self . _mark ) <EOL> end = max ( self . _position , self . _mark ) <EOL> self . _layout . document . set_style ( start , end , attributes ) <EOL> def _delete_selection ( self ) : <EOL> start = min ( self . _mark , self . _position ) <EOL> end = max ( self . _mark , self . _position ) <EOL> self . _position = start <EOL> self . _mark = None <EOL> self . _layout . document . delete_text ( start , end ) <EOL> self . _layout . set_selection ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> def move_to_point ( self , x , y ) : <EOL> '''<STR_LIT>''' <EOL> line = self . _layout . get_line_from_point ( x , y ) <EOL> self . _mark = None <EOL> self . _layout . set_selection ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> self . _position = self . _layout . get_position_on_line ( line , x ) <EOL> self . _update ( line = line ) <EOL> self . _next_attributes . clear ( ) <EOL> def select_to_point ( self , x , y ) : <EOL> '''<STR_LIT>''' <EOL> line = self . _layout . get_line_from_point ( x , y ) <EOL> self . _position = self . _layout . get_position_on_line ( line , x ) <EOL> self . _update ( line = line ) <EOL> self . _next_attributes . clear ( ) <EOL> def select_word ( self , x , y ) : <EOL> '''<STR_LIT>''' <EOL> line = self . _layout . get_line_from_point ( x , y ) <EOL> p = self . _layout . get_position_on_line ( line , x ) <EOL> m1 = self . _previous_word_re . search ( self . _layout . document . text , <EOL> <NUM_LIT:0> , p + <NUM_LIT:1> ) <EOL> if not m1 : <EOL> m1 = <NUM_LIT:0> <EOL> else : <EOL> m1 = m1 . start ( ) <EOL> self . mark = m1 <EOL> m2 = self . _next_word_re . search ( self . _layout . document . text , p ) <EOL> if not m2 : <EOL> m2 = len ( self . _layout . document . text ) <EOL> else : <EOL> m2 = m2 . start ( ) <EOL> self . _position = m2 <EOL> self . _update ( line = line ) <EOL> self . _next_attributes . clear ( ) <EOL> def select_paragraph ( self , x , y ) : <EOL> '''<STR_LIT>''' <EOL> line = self . _layout . get_line_from_point ( x , y ) <EOL> p = self . _layout . get_position_on_line ( line , x ) <EOL> self . mark = self . _layout . document . get_paragraph_start ( p ) <EOL> self . _position = self . _layout . document . get_paragraph_end ( p ) <EOL> self . _update ( line = line ) <EOL> self . _next_attributes . clear ( ) <EOL> def _update ( self , line = None , update_ideal_x = True ) : <EOL> if line is None : <EOL> line = self . _layout . get_line_from_position ( self . _position ) <EOL> self . _ideal_line = None <EOL> else : <EOL> self . _ideal_line = line <EOL> x , y = self . _layout . get_point_from_position ( self . _position , line ) <EOL> if update_ideal_x : <EOL> self . _ideal_x = x <EOL> x -= self . _layout . top_group . translate_x <EOL> y -= self . _layout . top_group . translate_y <EOL> font = self . _layout . document . get_font ( max ( <NUM_LIT:0> , self . _position - <NUM_LIT:1> ) ) <EOL> self . _list . vertices [ : ] = [ x , y + font . descent , x , y + font . ascent ] <EOL> if self . _mark is not None : <EOL> self . _layout . set_selection ( min ( self . _position , self . _mark ) , <EOL> max ( self . _position , self . _mark ) ) <EOL> self . _layout . ensure_line_visible ( line ) <EOL> self . _layout . ensure_x_visible ( x ) <EOL> def on_layout_update ( self ) : <EOL> if self . position > len ( self . _layout . document . text ) : <EOL> self . position = len ( self . _layout . document . text ) <EOL> self . _update ( ) <EOL> def on_text ( self , text ) : <EOL> '''<STR_LIT>''' <EOL> if self . _mark is not None : <EOL> self . _delete_selection ( ) <EOL> text = text . replace ( '<STR_LIT:\r>' , '<STR_LIT:\n>' ) <EOL> pos = self . _position <EOL> self . _position += len ( text ) <EOL> self . _layout . document . insert_text ( pos , text , self . _next_attributes ) <EOL> self . _nudge ( ) <EOL> return event . EVENT_HANDLED <EOL> def on_text_motion ( self , motion , select = False ) : <EOL> '''<STR_LIT>''' <EOL> if motion == key . MOTION_BACKSPACE : <EOL> if self . mark is not None : <EOL> self . _delete_selection ( ) <EOL> elif self . _position > <NUM_LIT:0> : <EOL> self . _position -= <NUM_LIT:1> <EOL> self . _layout . document . delete_text ( <EOL> self . _position , self . _position + <NUM_LIT:1> ) <EOL> elif motion == key . MOTION_DELETE : <EOL> if self . mark is not None : <EOL> self . _delete_selection ( ) <EOL> elif self . _position < len ( self . _layout . document . text ) : <EOL> self . _layout . document . delete_text ( <EOL> self . _position , self . _position + <NUM_LIT:1> ) <EOL> elif self . _mark is not None and not select : <EOL> self . _mark = None <EOL> self . _layout . set_selection ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> if motion == key . MOTION_LEFT : <EOL> self . position = max ( <NUM_LIT:0> , self . position - <NUM_LIT:1> ) <EOL> elif motion == key . MOTION_RIGHT : <EOL> self . position = min ( len ( self . _layout . document . text ) , <EOL> self . position + <NUM_LIT:1> ) <EOL> elif motion == key . MOTION_UP : <EOL> self . line = max ( <NUM_LIT:0> , self . line - <NUM_LIT:1> ) <EOL> elif motion == key . MOTION_DOWN : <EOL> line = self . line <EOL> if line < self . _layout . get_line_count ( ) - <NUM_LIT:1> : <EOL> self . line = line + <NUM_LIT:1> <EOL> elif motion == key . MOTION_BEGINNING_OF_LINE : <EOL> self . position = self . _layout . get_position_from_line ( self . line ) <EOL> elif motion == key . MOTION_END_OF_LINE : <EOL> line = self . line <EOL> if line < self . _layout . get_line_count ( ) - <NUM_LIT:1> : <EOL> self . _position = self . _layout . get_position_from_line ( line + <NUM_LIT:1> ) - <NUM_LIT:1> <EOL> self . _update ( line ) <EOL> else : <EOL> self . position = len ( self . _layout . document . text ) <EOL> elif motion == key . MOTION_BEGINNING_OF_FILE : <EOL> self . position = <NUM_LIT:0> <EOL> elif motion == key . MOTION_END_OF_FILE : <EOL> self . position = len ( self . _layout . document . text ) <EOL> elif motion == key . MOTION_NEXT_WORD : <EOL> pos = self . _position + <NUM_LIT:1> <EOL> m = self . _next_word_re . search ( self . _layout . document . text , pos ) <EOL> if not m : <EOL> self . position = len ( self . _layout . document . text ) <EOL> else : <EOL> self . position = m . start ( ) <EOL> elif motion == key . MOTION_PREVIOUS_WORD : <EOL> pos = self . _position <EOL> m = self . _previous_word_re . search ( self . _layout . document . text , <EOL> <NUM_LIT:0> , pos ) <EOL> if not m : <EOL> self . position = <NUM_LIT:0> <EOL> else : <EOL> self . position = m . start ( ) <EOL> self . _next_attributes . clear ( ) <EOL> self . _nudge ( ) <EOL> return event . EVENT_HANDLED <EOL> def on_text_motion_select ( self , motion ) : <EOL> '''<STR_LIT>''' <EOL> if self . mark is None : <EOL> self . mark = self . position <EOL> self . on_text_motion ( motion , True ) <EOL> return event . EVENT_HANDLED <EOL> def on_mouse_scroll ( self , x , y , scroll_x , scroll_y ) : <EOL> '''<STR_LIT>''' <EOL> self . _layout . view_x -= scroll_x * self . SCROLL_INCREMENT <EOL> self . _layout . view_y += scroll_y * self . SCROLL_INCREMENT <EOL> return event . EVENT_HANDLED <EOL> def on_mouse_press ( self , x , y , button , modifiers ) : <EOL> '''<STR_LIT>''' <EOL> t = time . time ( ) <EOL> if t - self . _click_time < <NUM_LIT> : <EOL> self . _click_count += <NUM_LIT:1> <EOL> else : <EOL> self . _click_count = <NUM_LIT:1> <EOL> self . _click_time = time . time ( ) <EOL> if self . _click_count == <NUM_LIT:1> : <EOL> self . move_to_point ( x , y ) <EOL> elif self . _click_count == <NUM_LIT:2> : <EOL> self . select_word ( x , y ) <EOL> elif self . _click_count == <NUM_LIT:3> : <EOL> self . select_paragraph ( x , y ) <EOL> self . _click_count = <NUM_LIT:0> <EOL> self . _nudge ( ) <EOL> return event . EVENT_HANDLED <EOL> def on_mouse_drag ( self , x , y , dx , dy , buttons , modifiers ) : <EOL> '''<STR_LIT>''' <EOL> if self . mark is None : <EOL> self . mark = self . position <EOL> self . select_to_point ( x , y ) <EOL> self . _nudge ( ) <EOL> return event . EVENT_HANDLED <EOL> def on_activate ( self ) : <EOL> '''<STR_LIT>''' <EOL> self . _active = True <EOL> self . visible = self . _active <EOL> return event . EVENT_HANDLED <EOL> def on_deactivate ( self ) : <EOL> '''<STR_LIT>''' <EOL> self . _active = False <EOL> self . visible = self . _active <EOL> return event . EVENT_HANDLED </s>
