Changeset 6137


Ignore:
Timestamp:
07/16/09 19:31:07 (3 years ago)
Author:
garu
Message:

committed GabrielVieira?'s refactoring/bugfixes for the Directory Browser

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/Padre-0.40/lib/Padre/Wx/Directory.pm

    r6132 r6137  
    1313our @ISA     = 'Wx::TreeCtrl'; 
    1414 
    15 my %CACHED; 
    16 my %SKIP = map { $_ => 1 } ( '.', '..', '.svn', 'CVS', '.git' ); 
    17  
    18 # TODO - This violates encapsulation. 
    19 #        Do not store application state in package variables. 
    20 my $current_dir; 
    21 my $current_item; 
    22  
    2315sub new { 
    2416    my $class = shift; 
     
    3325            | Wx::wxTR_FULL_ROW_HIGHLIGHT 
    3426    ); 
     27 
     28    $self->{SKIP}            = { map { $_ => 1 } ( '.', '..', '.svn', 'CVS', '.git' ) }; 
     29    $self->{CACHED}          = {}; 
     30    $self->{force_next}      = 0; 
     31    $self->{current_item}    = {}; 
     32    $self->{current_project} = ''; 
     33 
     34    $self->_setup_events; 
     35    $self->_add_root(); 
     36 
    3537    $self->SetIndent(10); 
    36     $self->{force_next} = 0; 
    37  
    38     Wx::Event::EVT_TREE_ITEM_ACTIVATED( 
    39         $self, $self, 
    40         sub { 
    41             $self->on_tree_item_activated( $_[1] ); 
    42         }, 
    43     ); 
    44  
    45     Wx::Event::EVT_SET_FOCUS( 
    46         $self, 
    47         \&_on_focus 
    48     ); 
    49  
    50     Wx::Event::EVT_TREE_ITEM_MENU( 
    51         $self, $self, 
    52         \&_on_tree_item_menu, 
    53     ); 
    54  
    55     Wx::Event::EVT_TREE_SEL_CHANGED( 
    56         $self, $self, 
    57         \&_on_tree_sel_changed, 
    58     ); 
    59  
    60     Wx::Event::EVT_TREE_ITEM_EXPANDING( 
    61         $self, $self, 
    62         \&_on_tree_item_expanding, 
    63     ); 
    64  
    65     Wx::Event::EVT_TREE_ITEM_COLLAPSING( 
    66         $self, $self, 
    67         \&_on_tree_item_collapsing, 
    68     ); 
    69  
    70     Wx::Event::EVT_TREE_BEGIN_LABEL_EDIT( 
    71         $self, $self, 
    72         \&_on_tree_begin_label_edit, 
    73     ); 
    74  
    75     Wx::Event::EVT_TREE_END_LABEL_EDIT( 
    76         $self, $self, 
    77         \&_on_tree_end_label_edit, 
    78     ); 
    79  
    80     my $root = $self->AddRoot( 
    81         Wx::gettext('Directory'), 
    82         -1, 
    83         -1, 
    84         Wx::TreeItemData->new('') 
    85     ); 
    86  
    87     $self->GetBestSize; 
    88     $self->Thaw; 
    89  
    90     $self->Hide; 
     38 
     39    #   Do they need to be used? 
     40    #   $self->GetBestSize; 
     41    #   $self->Thaw; 
     42    #   $self->Hide; 
    9143 
    9244    return $self; 
     
    11062 
    11163sub clear { 
    112     unless ( $_[0]->current->filename ) { 
    113         $_[0]->DeleteChildren( $_[0]->GetRootItem ); 
    114         $current_dir = ""; 
     64    my $self = shift; 
     65    unless ( $self->current->filename ) { 
     66        $self->DeleteChildren( $self->GetRootItem ); 
     67        $self->{current_project} = ''; 
    11568    } 
    11669    return; 
     
    12780} 
    12881 
     82sub _setup_events { 
     83    my $self = shift; 
     84    Wx::Event::EVT_TREE_ITEM_ACTIVATED( 
     85        $self, $self, 
     86        \&_on_tree_item_activated 
     87    ); 
     88 
     89    Wx::Event::EVT_SET_FOCUS( 
     90        $self, 
     91        \&_on_focus 
     92    ); 
     93 
     94    Wx::Event::EVT_TREE_ITEM_MENU( 
     95        $self, $self, 
     96        \&_on_tree_item_menu, 
     97    ); 
     98 
     99    Wx::Event::EVT_TREE_SEL_CHANGED( 
     100        $self, $self, 
     101        \&_on_tree_sel_changed, 
     102    ); 
     103 
     104    Wx::Event::EVT_TREE_ITEM_EXPANDING( 
     105        $self, $self, 
     106        \&_on_tree_item_expanding, 
     107    ); 
     108 
     109    Wx::Event::EVT_TREE_ITEM_COLLAPSING( 
     110        $self, $self, 
     111        \&_on_tree_item_collapsing, 
     112    ); 
     113 
     114    Wx::Event::EVT_TREE_BEGIN_LABEL_EDIT( 
     115        $self, $self, 
     116        \&_on_tree_begin_label_edit, 
     117    ); 
     118 
     119    Wx::Event::EVT_TREE_END_LABEL_EDIT( 
     120        $self, $self, 
     121        \&_on_tree_end_label_edit, 
     122    ); 
     123 
     124} 
     125 
     126sub _add_root { 
     127    my ( $self, $name, $data ) = @_; 
     128 
     129    $name |= Wx::gettext('Directory'); 
     130    $data |= {}; 
     131 
     132    $self->AddRoot( 
     133        $name, 
     134        -1, 
     135        -1, 
     136        Wx::TreeItemData->new($data) 
     137    ); 
     138} 
     139 
    129140##################################################################### 
    130141# Event Handlers 
    131142 
    132 sub on_tree_item_activated { 
    133     my ( $self, $event ) = @_; 
    134  
    135     my $itemObj = $event->GetItem; 
    136     my $item    = $self->GetPlData($itemObj); 
    137  
    138     return if not defined $item; 
    139  
    140     if ( $item->{type} eq "folder" ) { 
    141         $self->Toggle($itemObj); 
    142         return; 
    143     } 
    144  
    145     my $path = File::Spec->catfile( $item->{dir}, $item->{name} ); 
    146     return if not defined $path; 
    147     my $main = $self->main; 
    148     if ( my $id = $main->find_editor_of_file($path) ) { 
    149         my $page = $main->notebook->GetPage($id); 
    150         $page->SetFocus; 
    151     } else { 
    152         $main->setup_editors($path); 
    153     } 
    154     return; 
    155 } 
    156  
    157 sub list_dir { 
    158     my $dir = shift; 
    159     my @data; 
    160  
    161     if ( UpdatedDir($dir) ) { 
    162  
    163         $CACHED{$dir}->{Change} = ( stat $dir )[10]; 
     143sub _list_dir { 
     144    my ( $self, $dir ) = @_; 
     145 
     146    my $cached = $self->{CACHED}->{$dir}; 
     147 
     148    if ( $self->_updated_dir($dir) ) { 
     149 
     150        $cached->{Change} = ( stat $dir )[10]; 
    164151 
    165152        if ( opendir my $dh, $dir ) { 
    166153 
    167             my @items = sort { lc($a) cmp lc($b) } grep { not $SKIP{$_} } readdir $dh; 
    168             @items = grep { not /^\./ } @items unless $CACHED{$dir}->{ShowHidden}; 
    169  
     154            my @items = sort { lc($a) cmp lc($b) } grep { not $self->{SKIP}->{$_} } readdir $dh; 
     155 
     156 
     157            unless ( $cached->{ShowHidden} ) { 
     158 
     159##################################################################### 
     160# Show/Hide Windows hidden files and directories - NEED TO BE TESTED 
     161# 
     162#               if ( $^O !~ /^win32/i ) { 
     163#                   require Win32::File; 
     164#                   my $attribs; 
     165#                   @items = grep { Win32::File::GetAttributes( $_, $attribs ) and !( $attribs & HIDDEN ) } @items; 
     166#               } 
     167#               else { 
     168# 
     169                @items = grep { not /^\./ } @items; 
     170 
     171# 
     172#               } 
     173##################################################################### 
     174            } 
     175 
     176            my @data; 
    170177            foreach my $thing (@items) { 
    171178                my $path = File::Spec->catfile( $dir, $thing ); 
     
    178185            } 
    179186 
    180             @{ $CACHED{$dir}->{Data} } = sort { $b->{isDir} <=> $a->{isDir} } @data; 
     187            @{ $cached->{Data} } = sort { $b->{isDir} <=> $a->{isDir} } @data; 
    181188            closedir $dh; 
    182189        } 
    183190    } 
    184     return $CACHED{$dir}->{Data}; 
    185 } 
    186  
    187 sub UpdatedDir { 
    188     my $dir       = shift; 
    189     my $dirChange = ( stat $dir )[10]; 
    190     return (   !defined $CACHED{$dir} 
    191             || !$CACHED{$dir}->{Data} 
    192             || !$CACHED{$dir}->{Change} 
    193             || $dirChange != $CACHED{$dir}->{Change} ) ? 1 : 0; 
    194 } 
     191    return $cached->{Data}; 
     192} 
     193 
    195194 
    196195sub update_gui { 
     
    203202        || File::Basename::dirname($filename); 
    204203 
    205     my $updated = UpdatedDir($dir); 
    206     list_dir($dir); 
    207     return unless @{ $CACHED{$dir}->{Data} }; 
    208  
    209     my $directory = $self->main->directory; 
    210     my $root      = $directory->GetRootItem; 
    211  
    212     if ( ( defined($current_dir) and $current_dir ne $dir ) or $updated ) { 
    213         $directory->DeleteChildren($root); 
    214         _update_treectrl( $directory, $CACHED{$dir}->{Data}, $root ); 
    215     } 
    216  
    217     $current_dir = $dir; 
    218     _update_subdirs( $directory, $root ); 
     204    my $updated = $self->_updated_dir($dir); 
     205    my $data    = $self->_list_dir($dir); 
     206    return unless @{$data}; 
     207 
     208    my $root    = $self->GetRootItem; 
     209    my $project = $self->{current_project}; 
     210 
     211    if ( ( defined($project) and $project ne $dir ) or $updated ) { 
     212        $self->DeleteChildren($root); 
     213        _update_treectrl( $self, $data, $root ); 
     214    } 
     215 
     216    $project = $dir; 
     217    _update_subdirs( $self, $root ); 
     218} 
     219 
     220sub _updated_dir { 
     221    my $self   = shift; 
     222    my $dir    = shift; 
     223    my $cached = $self->{CACHED}->{$dir}; 
     224 
     225    if ( not defined($cached) or !$cached->{Data} or !$cached->{Change} or ( stat $dir )[10] != $cached->{Change} ) { 
     226        return 1; 
     227    } 
     228    return 0; 
    219229} 
    220230 
    221231sub _update_subdirs { 
    222232    my ( $self, $root ) = @_; 
     233    my $project = $self->{current_project}; 
    223234 
    224235    my $cookie; 
     
    232243        if (    defined $itemData->{type} 
    233244            and $itemData->{type} eq 'folder' 
    234             and defined $CACHED{$current_dir}->{Expanded}->{$path} ) 
     245            and defined $self->{CACHED}->{$project}->{Expanded}->{$path} ) 
    235246        { 
    236247 
    237248            $self->Expand($node); 
    238249 
    239             if ( UpdatedDir($path) ) { 
     250            if ( $self->_updated_dir($path) ) { 
    240251                $self->DeleteChildren($node); 
    241                 _update_treectrl( $self, list_dir($path), $node ); 
     252                _update_treectrl( $self, $self->_list_dir($path), $node ); 
    242253            } 
    243254            _update_subdirs( $self, $node ); 
    244255        } 
    245         if ( defined $current_item->{$current_dir} and $current_item->{$current_dir} eq $path ) { 
     256        if ( defined $self->{current_item}->{$project} and $self->{current_item}->{$project} eq $path ) { 
    246257            $self->SelectItem($node); 
    247258            $self->ScrollTo($node); 
     
    254265    my $main = $self->main; 
    255266 
    256     if ( $main->has_directory ) { 
    257         $main->directory->update_gui; 
    258     } 
     267    $self->update_gui if $main->has_directory; 
     268} 
     269 
     270sub _on_tree_item_activated { 
     271    my ( $self, $event ) = @_; 
     272 
     273    my $itemObj = $event->GetItem; 
     274    my $item    = $self->GetPlData($itemObj); 
     275 
     276    return if not defined $item; 
     277 
     278    if ( $item->{type} eq "folder" ) { 
     279        $self->Toggle($itemObj); 
     280        return; 
     281    } 
     282 
     283    my $path = File::Spec->catfile( $item->{dir}, $item->{name} ); 
     284    return if not defined $path; 
     285    my $main = $self->main; 
     286    if ( my $id = $main->find_editor_of_file($path) ) { 
     287        my $page = $main->notebook->GetPage($id); 
     288        $page->SetFocus; 
     289    } else { 
     290        $main->setup_editors($path); 
     291    } 
     292    return; 
    259293} 
    260294 
     
    277311    my $newFile = File::Spec->catfile( $itemData->{dir}, $newLabel ); 
    278312 
     313    if ( -e $newFile ){ 
     314        $event->Veto(); 
     315        return; 
     316    } 
     317 
    279318    if ( rename $oldFile, $newFile ) { 
    280319 
    281320        $itemData->{name} = $newLabel; 
    282         $current_item->{$current_dir} = $newFile; 
    283  
    284         if ( defined $CACHED{$current_dir}->{Expanded}->{$oldFile} ) { 
    285             $CACHED{$current_dir}->{Expanded}->{$newFile} = 1; 
    286             delete $CACHED{$current_dir}->{Expanded}->{$oldFile}; 
     321        my $project = $self->{current_project}; 
     322        $self->{current_item}->{$project} = $newFile; 
     323 
     324        my $cached = $self->{CACHED}; 
     325 
     326        if ( defined $cached->{$project}->{Expanded}->{$oldFile} ) { 
     327            $cached->{$project}->{Expanded}->{$newFile} = 1; 
     328            delete $cached->{$project}->{Expanded}->{$oldFile}; 
    287329        } 
    288330        map { 
    289             $CACHED{ $newFile . ( defined $1 ? $1 : '' ) } = $CACHED{$_}, delete $CACHED{$_} 
     331            $cached->{ $newFile . ( defined $1 ? $1 : '' ) } = $cached->{$_}, delete $cached->{$_} 
    290332                if $_ =~ m#^$oldFile(\/.+)?$# 
    291         } keys %CACHED; 
     333        } keys %$cached; 
    292334    } else { 
    293335        $event->Veto(); 
     
    300342    my $itemData = $self->GetPlData($itemObj); 
    301343    if ( ref $itemData eq 'HASH' ) { 
    302         $current_item->{$current_dir} = File::Spec->catfile( $itemData->{dir}, $itemData->{name} ); 
     344        $self->{current_item}->{ $self->{current_project} } = 
     345            File::Spec->catfile( $itemData->{dir}, $itemData->{name} ); 
    303346    } 
    304347} 
     
    313356 
    314357        my $path = File::Spec->catfile( $itemData->{dir}, $itemData->{name} ); 
    315         $CACHED{$current_dir}->{Expanded}->{$path} = 1; 
    316  
    317         if ( UpdatedDir($path) or !$self->GetChildrenCount($itemObj) ) { 
     358        $self->{CACHED}->{ $self->{current_project} }->{Expanded}->{$path} = 1; 
     359 
     360        if ( $self->_updated_dir($path) or !$self->GetChildrenCount($itemObj) ) { 
    318361            $self->DeleteChildren($itemObj); 
    319             _update_treectrl( $self, list_dir($path), $itemObj ); 
     362            _update_treectrl( $self, $self->_list_dir($path), $itemObj ); 
    320363        } 
    321364    } 
     
    329372    if ( defined( $itemData->{type} ) && $itemData->{type} eq 'folder' ) { 
    330373        my $path = File::Spec->catfile( $itemData->{dir}, $itemData->{name} ); 
    331         delete $CACHED{$current_dir}->{Expanded}->{$path}; 
     374        delete $self->{CACHED}->{ $self->{current_project} }->{Expanded}->{$path}; 
    332375    } 
    333376} 
    334377 
    335378sub _on_tree_item_menu { 
    336     my ( $dir, $event ) = @_; 
     379    my ( $self, $event ) = @_; 
    337380 
    338381    my $itemObj   = $event->GetItem; 
    339     my $itemData  = $dir->GetPlData($itemObj); 
    340     my $SelectDir = $itemData->{dir}; 
    341  
    342     if ( defined $itemData ) { 
    343  
    344         my $menu = Wx::Menu->new; 
    345  
    346         if ( defined( $itemData->{type} ) 
    347             && $itemData->{type} eq 'folder' ) 
     382    my $item_data = $self->GetPlData($itemObj); 
     383 
     384    if ( defined $item_data ) { 
     385 
     386        my $menu         = Wx::Menu->new; 
     387        my $selected_dir = $item_data->{dir}; 
     388 
     389        ################################################ 
     390        # Default action - same when the item is activated 
     391        # 
     392        if ( defined $item_data->{type}  
     393            and $item_data->{type} eq 'folder' ) 
    348394        { 
    349395            my $default = $menu->Append( -1, Wx::gettext("Expand / Collapse") ); 
    350396            Wx::Event::EVT_MENU( 
    351                 $dir, $default, 
    352                 sub { 
    353                     $dir->Toggle($itemObj); 
    354                 } 
     397                $self, $default, 
     398                sub { $self->Toggle($itemObj) }, 
    355399            ); 
    356400        } else { 
    357401            my $default = $menu->Append( -1, Wx::gettext("Open File") ); 
    358402            Wx::Event::EVT_MENU( 
    359                 $dir, $default, 
    360                 sub { 
    361                     $dir->on_tree_item_activated($event); 
    362                 }, 
     403                $self, $default, 
     404                sub { $self->on_tree_item_activated($event) }, 
    363405            ); 
    364406        } 
     
    366408        $menu->AppendSeparator(); 
    367409 
     410        ############################################# 
     411        # Rename and/or move the item 
    368412        my $rename = $menu->Append( -1, Wx::gettext("Rename") ); 
    369413        Wx::Event::EVT_MENU( 
    370             $dir, $rename, 
     414            $self, $rename, 
    371415            sub { 
    372                 $dir->EditLabel($itemObj); 
     416                $self->EditLabel($itemObj); 
    373417            }, 
    374418        ); 
    375419 
    376420 
    377         if ( defined( $itemData->{type} ) 
    378             && ( $itemData->{type} eq 'modules' || $itemData->{type} eq 'pragmata' ) ) 
     421        if ( defined $item_data->{type} 
     422            and ( $item_data->{type} eq 'modules' or $item_data->{type} eq 'pragmata' ) ) 
    379423        { 
    380424            my $pod = $menu->Append( -1, Wx::gettext("Open &Documentation") ); 
    381425            Wx::Event::EVT_MENU( 
    382                 $dir, $pod, 
     426                $self, $pod, 
    383427                sub { 
    384428 
     
    386430                    require Padre::Wx::DocBrowser; 
    387431                    my $help = Padre::Wx::DocBrowser->new; 
    388                     $help->help( $itemData->{name} ); 
     432                    $help->help( $item_data->{name} ); 
    389433                    $help->SetFocus; 
    390434                    $help->Show(1); 
     
    397441 
    398442        ##################################################################### 
    399         # Shows / Hides dot started files and folers 
     443        # Shows / Hides dot started files and folers (N/A on Windows) 
    400444        if ( $^O !~ /^win32/i ) { 
     445 
    401446            my $hiddenFiles = $menu->AppendCheckItem( -1, Wx::gettext("Show hidden files") ); 
    402  
    403             $SelectDir = File::Spec->catfile( $itemData->{dir}, $itemData->{name} ) if $itemData->{type} eq 'folder'; 
    404  
    405             my $show = $CACHED{$SelectDir}->{ShowHidden}; 
     447            if ( $item_data->{type} eq 'folder' ) { 
     448                $selected_dir = File::Spec->catfile( $item_data->{dir}, $item_data->{name} ); 
     449            } 
     450            my $cached = $self->{CACHED}->{$selected_dir}; 
     451            my $show   = $cached->{ShowHidden}; 
    406452            $hiddenFiles->Check($show); 
    407453 
    408454            Wx::Event::EVT_MENU( 
    409                 $dir, 
     455                $self, 
    410456                $hiddenFiles, 
    411457                sub { 
    412                     $CACHED{$SelectDir}->{ShowHidden} = !$show; 
    413                     delete $CACHED{$SelectDir}->{Data}; 
     458                    $cached->{ShowHidden} = !$show; 
     459                    delete $cached->{Data}; 
    414460                }, 
    415461            ); 
     
    417463        ##################################################################### 
    418464        # Updates the directory listing 
    419  
    420465        my $reload = $menu->Append( -1, Wx::gettext("Reload") ); 
    421466        Wx::Event::EVT_MENU( 
    422             $dir, $reload, 
     467            $self, $reload, 
    423468            sub { 
    424                 delete $CACHED{ $dir->GetPlData($itemObj)->{dir} }->{Change}; 
     469                delete $self->{CACHED}->{ $self->GetPlData($itemObj)->{dir} }->{Change}; 
    425470            } 
    426471        ); 
    427472 
     473        ##################################################################### 
     474        # Pops up the context menu 
    428475        my $x = $event->GetPoint->x; 
    429476        my $y = $event->GetPoint->y; 
    430         $dir->PopupMenu( $menu, $x, $y ); 
     477        $self->PopupMenu( $menu, $x, $y ); 
    431478    } 
    432479    return; 
Note: See TracChangeset for help on using the changeset viewer.