<s> from atom . api import Atom , Int , Typed , List , atomref <EOL> from enaml . layout . dock_layout import DockLayout <EOL> from enaml . qt . QtCore import Qt , QPoint , QRect , QObject <EOL> from enaml . qt . QtGui import QApplication <EOL> from . dock_overlay import DockOverlay <EOL> from . layout_handling import layout_hit_test , plug_frame , iter_containers <EOL> from . layout_builder import LayoutBuilder <EOL> from . layout_saver import LayoutSaver <EOL> from . proximity_handler import ProximityHandler <EOL> from . q_dock_area import QDockArea <EOL> from . q_dock_container import QDockContainer <EOL> from . q_dock_window import QDockWindow <EOL> from . q_guide_rose import QGuideRose <EOL> class DockContainerMonitor ( QObject ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , manager ) : <EOL> """<STR_LIT>""" <EOL> super ( DockContainerMonitor , self ) . __init__ ( ) <EOL> self . _manager = atomref ( manager ) <EOL> def onTopLevelChanged ( self , toplevel ) : <EOL> """<STR_LIT>""" <EOL> if self . _manager : <EOL> handler = self . _manager ( ) . _proximity_handler <EOL> container = self . sender ( ) <EOL> if toplevel : <EOL> handler . addFrame ( container ) <EOL> else : <EOL> handler . removeFrame ( container ) <EOL> class DockManager ( Atom ) : <EOL> """<STR_LIT>""" <EOL> _dock_area = Typed ( QDockArea ) <EOL> _overlay = Typed ( DockOverlay , ( ) ) <EOL> _dock_frames = List ( ) <EOL> _dock_items = Typed ( set , ( ) ) <EOL> _snap_dist = Int ( factory = lambda : QApplication . startDragDistance ( ) * <NUM_LIT:2> ) <EOL> _proximity_handler = Typed ( ProximityHandler , ( ) ) <EOL> _container_monitor = Typed ( DockContainerMonitor ) <EOL> def _default__container_monitor ( self ) : <EOL> return DockContainerMonitor ( self ) <EOL> def __init__ ( self , dock_area ) : <EOL> """<STR_LIT>""" <EOL> assert dock_area is not None <EOL> self . _dock_area = dock_area <EOL> self . _overlay = DockOverlay ( dock_area ) <EOL> def dock_area ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _dock_area <EOL> def add_item ( self , item ) : <EOL> """<STR_LIT>""" <EOL> if item in self . _dock_items : <EOL> return <EOL> self . _dock_items . add ( item ) <EOL> item . _manager = self <EOL> container = QDockContainer ( self , self . _dock_area ) <EOL> container . setDockItem ( item ) <EOL> container . setObjectName ( item . objectName ( ) ) <EOL> monitor = self . _container_monitor <EOL> container . topLevelChanged . connect ( monitor . onTopLevelChanged ) <EOL> self . _dock_frames . append ( container ) <EOL> def remove_item ( self , item ) : <EOL> """<STR_LIT>""" <EOL> if item not in self . _dock_items : <EOL> return <EOL> item . _manager = None <EOL> for container in self . dock_containers ( ) : <EOL> if container . dockItem ( ) is item : <EOL> if not container . isWindow ( ) : <EOL> container . unplug ( ) <EOL> container . hide ( ) <EOL> self . _free_container ( container ) <EOL> break <EOL> def save_layout ( self ) : <EOL> """<STR_LIT>""" <EOL> items = [ self . _dock_area ] + self . floating_frames ( ) <EOL> return DockLayout ( * map ( LayoutSaver ( ) , items ) ) <EOL> def apply_layout ( self , layout ) : <EOL> """<STR_LIT>""" <EOL> LayoutBuilder ( self ) ( layout ) <EOL> def update_layout ( self , ops ) : <EOL> """<STR_LIT>""" <EOL> builder = LayoutBuilder ( self ) <EOL> for op in ops : <EOL> builder ( op ) <EOL> def destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> for frame in self . _dock_frames : <EOL> if isinstance ( frame , QDockContainer ) : <EOL> frame . setDockItem ( None ) <EOL> frame . setParent ( None , Qt . Widget ) <EOL> frame . hide ( ) <EOL> for frame in self . _dock_frames : <EOL> if isinstance ( frame , QDockWindow ) : <EOL> frame . setParent ( None , Qt . Widget ) <EOL> frame . hide ( ) <EOL> for item in self . _dock_items : <EOL> item . _manager = None <EOL> self . _dock_area . setCentralWidget ( None ) <EOL> self . _dock_area . setMaximizedWidget ( None ) <EOL> del self . _dock_area <EOL> del self . _dock_frames <EOL> del self . _dock_items <EOL> del self . _proximity_handler <EOL> del self . _container_monitor <EOL> del self . _overlay <EOL> def dock_containers ( self ) : <EOL> """<STR_LIT>""" <EOL> f = lambda w : isinstance ( w , QDockContainer ) <EOL> return filter ( f , self . _dock_frames ) <EOL> def dock_windows ( self ) : <EOL> """<STR_LIT>""" <EOL> f = lambda w : isinstance ( w , QDockWindow ) <EOL> return filter ( f , self . _dock_frames ) <EOL> def floating_frames ( self ) : <EOL> """<STR_LIT>""" <EOL> f = lambda w : w . isWindow ( ) <EOL> return filter ( f , self . _dock_frames ) <EOL> def add_window ( self , window ) : <EOL> """<STR_LIT>""" <EOL> self . _dock_frames . append ( window ) <EOL> self . _proximity_handler . addFrame ( window ) <EOL> def close_container ( self , container , event ) : <EOL> """<STR_LIT>""" <EOL> item = container . dockItem ( ) <EOL> if item is None or item . close ( ) : <EOL> if not container . isWindow ( ) : <EOL> container . unplug ( ) <EOL> self . _free_container ( container ) <EOL> else : <EOL> event . ignore ( ) <EOL> def close_window ( self , window , event ) : <EOL> """<STR_LIT>""" <EOL> area = window . dockArea ( ) <EOL> if area is not None : <EOL> containers = list ( iter_containers ( area ) ) <EOL> geometries = { } <EOL> for container in containers : <EOL> pos = container . mapToGlobal ( QPoint ( <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> size = container . size ( ) <EOL> geometries [ container ] = QRect ( pos , size ) <EOL> for container , ignored in area . dockBarContainers ( ) : <EOL> containers . append ( container ) <EOL> size = container . sizeHint ( ) <EOL> geometries [ container ] = QRect ( window . pos ( ) , size ) <EOL> for container in containers : <EOL> if not container . close ( ) : <EOL> container . unplug ( ) <EOL> container . float ( ) <EOL> container . setGeometry ( geometries [ container ] ) <EOL> container . show ( ) <EOL> self . _free_window ( window ) <EOL> def raise_frame ( self , frame ) : <EOL> """<STR_LIT>""" <EOL> frames = self . _dock_frames <EOL> handler = self . _proximity_handler <EOL> if handler . hasLinkedFrames ( frame ) : <EOL> linked = set ( handler . linkedFrames ( frame ) ) <EOL> ordered = [ f for f in frames if f in linked ] <EOL> for other in ordered : <EOL> frames . remove ( other ) <EOL> frames . append ( other ) <EOL> other . raise_ ( ) <EOL> frame . raise_ ( ) <EOL> frames . remove ( frame ) <EOL> frames . append ( frame ) <EOL> def frame_resized ( self , frame ) : <EOL> """<STR_LIT>""" <EOL> if frame . isLinked ( ) : <EOL> handler = self . _proximity_handler <EOL> handler . updateLinks ( frame ) <EOL> if not handler . hasLinkedFrames ( frame ) : <EOL> frame . setLinked ( False ) <EOL> def drag_move_frame ( self , frame , target_pos , mouse_pos ) : <EOL> """<STR_LIT>""" <EOL> show_drag_overlay = True <EOL> handler = self . _proximity_handler <EOL> if frame . isLinked ( ) : <EOL> delta = target_pos - frame . pos ( ) <EOL> frame . move ( target_pos ) <EOL> if handler . hasLinkedFrames ( frame ) : <EOL> show_drag_overlay = False <EOL> for other in handler . linkedFrames ( frame ) : <EOL> other . move ( other . pos ( ) + delta ) <EOL> else : <EOL> f_size = frame . frameGeometry ( ) . size ( ) <EOL> f_rect = QRect ( target_pos , f_size ) <EOL> f_x = target_pos . x ( ) <EOL> f_y = target_pos . y ( ) <EOL> f_w = f_size . width ( ) <EOL> f_h = f_size . height ( ) <EOL> dist = self . _snap_dist <EOL> filt = lambda n : - dist < n < dist <EOL> for other in handler . proximalFrames ( f_rect , dist ) : <EOL> if other is not frame : <EOL> o_geo = other . frameGeometry ( ) <EOL> o_x = o_geo . left ( ) <EOL> o_y = o_geo . top ( ) <EOL> o_right = o_x + o_geo . width ( ) <EOL> o_bottom = o_y + o_geo . height ( ) <EOL> dx = filter ( filt , ( <EOL> o_x - f_x , <EOL> o_x - ( f_x + f_w ) , <EOL> o_right - f_x , <EOL> o_right - ( f_x + f_w ) , <EOL> ) ) <EOL> if dx : <EOL> f_x += min ( dx ) <EOL> dy = filter ( filt , ( <EOL> o_y - f_y , <EOL> o_y - ( f_y + f_h ) , <EOL> o_bottom - f_y , <EOL> o_bottom - ( f_y + f_h ) , <EOL> ) ) <EOL> if dy : <EOL> f_y += min ( dy ) <EOL> frame . move ( f_x , f_y ) <EOL> if show_drag_overlay : <EOL> self . _update_drag_overlay ( frame , mouse_pos ) <EOL> else : <EOL> self . _overlay . hide ( ) <EOL> def drag_release_frame ( self , frame , pos ) : <EOL> """<STR_LIT>""" <EOL> overlay = self . _overlay <EOL> overlay . hide ( ) <EOL> guide = overlay . guide_at ( pos ) <EOL> if guide == QGuideRose . Guide . NoGuide : <EOL> return <EOL> if self . _proximity_handler . hasLinkedFrames ( frame ) : <EOL> return <EOL> builder = LayoutBuilder ( self ) <EOL> target = self . _dock_target ( frame , pos ) <EOL> if isinstance ( target , QDockArea ) : <EOL> if target . maximizedWidget ( ) is not None : <EOL> return <EOL> with builder . drop_frame ( frame ) : <EOL> local = target . mapFromGlobal ( pos ) <EOL> widget = layout_hit_test ( target , local ) <EOL> plug_frame ( target , widget , frame , guide ) <EOL> elif isinstance ( target , QDockContainer ) : <EOL> with builder . dock_context ( target ) : <EOL> with builder . drop_frame ( frame ) : <EOL> area = target . parentDockArea ( ) <EOL> if area is not None : <EOL> plug_frame ( area , target , frame , guide ) <EOL> def _free_container ( self , container ) : <EOL> """<STR_LIT>""" <EOL> item = container . dockItem ( ) <EOL> container . setParent ( None ) <EOL> container . setDockItem ( None ) <EOL> container . _manager = None <EOL> self . _dock_items . discard ( item ) <EOL> self . _dock_frames . remove ( container ) <EOL> self . _proximity_handler . removeFrame ( container ) <EOL> def _free_window ( self , window ) : <EOL> """<STR_LIT>""" <EOL> window . setParent ( None ) <EOL> window . setDockArea ( None ) <EOL> window . _manager = None <EOL> self . _dock_frames . remove ( window ) <EOL> self . _proximity_handler . removeFrame ( window ) <EOL> def _iter_dock_targets ( self , frame ) : <EOL> """<STR_LIT>""" <EOL> for target in reversed ( self . _dock_frames ) : <EOL> if target is not frame and target . isWindow ( ) : <EOL> if isinstance ( target , QDockContainer ) : <EOL> yield target <EOL> elif isinstance ( target , QDockWindow ) : <EOL> yield target . dockArea ( ) <EOL> yield self . _dock_area <EOL> def _dock_target ( self , frame , pos ) : <EOL> """<STR_LIT>""" <EOL> for target in self . _iter_dock_targets ( frame ) : <EOL> if isinstance ( target , QDockArea ) : <EOL> pane = target . centralPane ( ) <EOL> local = pane . mapFromGlobal ( pos ) <EOL> if pane . rect ( ) . contains ( local ) : <EOL> return target <EOL> else : <EOL> local = target . mapFromGlobal ( pos ) <EOL> if target . rect ( ) . contains ( local ) : <EOL> return target <EOL> def _update_drag_overlay ( self , frame , pos ) : <EOL> """<STR_LIT>""" <EOL> overlay = self . _overlay <EOL> target = self . _dock_target ( frame , pos ) <EOL> if isinstance ( target , QDockContainer ) : <EOL> local = target . mapFromGlobal ( pos ) <EOL> overlay . mouse_over_widget ( target , local ) <EOL> elif isinstance ( target , QDockArea ) : <EOL> if target . maximizedWidget ( ) is not None : <EOL> overlay . hide ( ) <EOL> return <EOL> local = target . mapFromGlobal ( pos ) <EOL> widget = layout_hit_test ( target , local ) <EOL> overlay . mouse_over_area ( target , widget , local ) <EOL> else : <EOL> overlay . hide ( ) </s>
