~ubuntu-branches/ubuntu/saucy/padre/saucy-proposed

« back to all changes in this revision

Viewing changes to lib/Padre/Wx/Diff.pm

  • Committer: Package Import Robot
  • Author(s): Dominique Dumont, gregor herrmann, Dominique Dumont
  • Date: 2012-01-04 12:04:20 UTC
  • mfrom: (1.3.3)
  • Revision ID: package-import@ubuntu.com-20120104120420-i5oybqwf91m1d3il
Tags: 0.92.ds1-1
[ gregor herrmann ]
* Remove debian/source/local-options; abort-on-upstream-changes
  and unapply-patches are default in dpkg-source since 1.16.1.
* Swap order of alternative (build) dependencies after the perl
  5.14 transition.

[ Dominique Dumont ]
* Imported Upstream version 0.92.ds1
* removed fix-spelling patch (applied upstream)
* lintian-override: use wildcard to avoid listing a gazillion files
* updated size of some 'not-real-man-page' entries
* rules: remove dekstop cruft (replaced by a file provided in debian
  directory)
* control: removed Breaks statement. Add /me to uploaders. Updated
  dependencies
* rules: make sure that non-DFSG file (i.e. the cute butterfly, sigh)
  is not distributed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package Padre::Wx::Diff;
 
2
 
 
3
use 5.008;
 
4
use strict;
 
5
use warnings;
 
6
use Scalar::Util            ();
 
7
use Params::Util            ();
 
8
use Padre::Constant         ();
 
9
use Padre::Role::Task       ();
 
10
use Padre::Wx               ();
 
11
use Padre::Util             ();
 
12
use Padre::Wx::Dialog::Diff ();
 
13
use Padre::Logger;
 
14
 
 
15
our $VERSION = '0.92';
 
16
our @ISA     = qw{
 
17
        Padre::Role::Task
 
18
};
 
19
 
 
20
 
 
21
 
 
22
 
 
23
 
 
24
######################################################################
 
25
# Constructor and Accessors
 
26
 
 
27
sub new {
 
28
        my $class = shift;
 
29
        my $main  = shift;
 
30
 
 
31
        my $self = bless {@_}, $class;
 
32
        $self->{main} = $main;
 
33
 
 
34
        $self->{diffs} = {};
 
35
 
 
36
        return $self;
 
37
}
 
38
 
 
39
 
 
40
 
 
41
 
 
42
 
 
43
######################################################################
 
44
# Padre::Role::Task Methods
 
45
 
 
46
sub task_finish {
 
47
        TRACE( $_[1] ) if DEBUG;
 
48
        my $self   = shift;
 
49
        my $task   = shift;
 
50
        my $chunks = Params::Util::_ARRAY0( $task->{data} ) or return;
 
51
        my $main   = $self->{main};
 
52
        my $editor = $main->current->editor or return;
 
53
        my $lock   = $editor->lock_update;
 
54
 
 
55
        # Clear any old content
 
56
        $self->clear;
 
57
 
 
58
        my $delta = 0;
 
59
        $self->{diffs} = {};
 
60
        for my $chunk ( @$chunks ) {
 
61
                my $marker_line   = undef;
 
62
                my $lines_deleted = 0;
 
63
                my $lines_added   = 0;
 
64
                for my $diff ( @$chunk ) {
 
65
                        my ( $type, $line, $text ) = @$diff;
 
66
                        TRACE("$type, $line, $text") if DEBUG;
 
67
 
 
68
                        unless ($marker_line) {
 
69
                                $marker_line = $line + $delta;
 
70
 
 
71
                                $self->{diffs}->{$marker_line} = {
 
72
                                        message  => undef,
 
73
                                        type     => undef,
 
74
                                        old_text => undef,
 
75
                                        new_text => undef,
 
76
                                };
 
77
                        }
 
78
 
 
79
                        my $diff = $self->{diffs}->{$marker_line};
 
80
 
 
81
                        if ( $type eq '-' ) {
 
82
                                $lines_deleted++;
 
83
                                $diff->{old_text} .= $text;
 
84
                        } else {
 
85
                                $lines_added++;
 
86
                                $diff->{new_text} .= $text;
 
87
                        }
 
88
                }
 
89
 
 
90
                my $description;
 
91
                my $diff = $self->{diffs}->{$marker_line};
 
92
                my $type;
 
93
                if ( $lines_deleted > 0 and $lines_added > 0 ) {
 
94
 
 
95
                        # Line(s) changed
 
96
                        $description =
 
97
                                $lines_deleted > 1
 
98
                                ? sprintf( Wx::gettext('%d lines changed'), $lines_deleted )
 
99
                                : sprintf( Wx::gettext('%d line changed'),  $lines_deleted );
 
100
                        $editor->MarkerDelete( $marker_line, $_ ) for ( Padre::Constant::MARKER_ADDED, Padre::Constant::MARKER_DELETED );
 
101
                        $editor->MarkerAdd( $marker_line, Padre::Constant::MARKER_CHANGED );
 
102
                        $type = 'C';
 
103
 
 
104
                } elsif ( $lines_added > 0 ) {
 
105
 
 
106
                        # Line(s) added
 
107
                        $description =
 
108
                                $lines_added > 1
 
109
                                ? sprintf( Wx::gettext('%d lines added'), $lines_added )
 
110
                                : sprintf( Wx::gettext('%d line added'),  $lines_added );
 
111
                        $editor->MarkerDelete( $marker_line, $_ ) for ( Padre::Constant::MARKER_CHANGED, Padre::Constant::MARKER_DELETED );
 
112
                        $editor->MarkerAdd( $marker_line, Padre::Constant::MARKER_ADDED );
 
113
                        $type = 'A';
 
114
                } elsif ( $lines_deleted > 0 ) {
 
115
 
 
116
                        # Line(s) deleted
 
117
                        $description =
 
118
                                $lines_deleted > 1
 
119
                                ? sprintf( Wx::gettext('%d lines deleted'), $lines_deleted )
 
120
                                : sprintf( Wx::gettext('%d line deleted'),  $lines_deleted );
 
121
                        $editor->MarkerDelete( $marker_line, $_ ) for ( Padre::Constant::MARKER_ADDED, Padre::Constant::MARKER_CHANGED );
 
122
                        $editor->MarkerAdd( $marker_line, Padre::Constant::MARKER_DELETED );
 
123
                        $type = 'D';
 
124
 
 
125
                } else {
 
126
 
 
127
                        # TODO No change... what to do there... ignore? :)
 
128
                        $description = 'no change!';
 
129
                        $type        = 'N';
 
130
                }
 
131
 
 
132
                # Record lines added/deleted
 
133
                $diff->{lines_added}   = $lines_added;
 
134
                $diff->{lines_deleted} = $lines_deleted;
 
135
                $diff->{type}          = $type;
 
136
                $diff->{message}       = $description;
 
137
 
 
138
                # Update the offset
 
139
                $delta = $delta + $lines_added - $lines_deleted;
 
140
 
 
141
                TRACE("$description at line #$marker_line") if DEBUG;
 
142
        }
 
143
 
 
144
        $editor->SetMarginSensitive( 1, 1 );
 
145
        my $myself = $self;
 
146
        Wx::Event::EVT_STC_MARGINCLICK(
 
147
                $editor, $editor,
 
148
                sub {
 
149
                        my $self  = shift;
 
150
                        my $event = shift;
 
151
 
 
152
                        if ( $event->GetMargin == 1 ) {
 
153
                                $myself->show_diff_box( $editor->LineFromPosition( $event->GetPosition ), $editor );
 
154
                        }
 
155
 
 
156
                        # Keep processing
 
157
                        $event->Skip(1);
 
158
                }
 
159
        );
 
160
 
 
161
        return 1;
 
162
}
 
163
 
 
164
 
 
165
 
 
166
 
 
167
 
 
168
######################################################################
 
169
# General Methods
 
170
 
 
171
sub clear {
 
172
        my $self    = shift;
 
173
        my $current = $self->{main}->current or return;
 
174
        my $editor  = $current->editor       or return;
 
175
        my $lock    = $editor->lock_update;
 
176
 
 
177
        $editor->MarkerDeleteAll(Padre::Constant::MARKER_ADDED);
 
178
        $editor->MarkerDeleteAll(Padre::Constant::MARKER_CHANGED);
 
179
        $editor->MarkerDeleteAll(Padre::Constant::MARKER_DELETED);
 
180
 
 
181
        $self->{dialog}->Hide if $self->{dialog};
 
182
}
 
183
 
 
184
sub refresh {
 
185
        TRACE( $_[0] ) if DEBUG;
 
186
        my $self     = shift;
 
187
        my $current  = shift or return;
 
188
        my $document = $current->document;
 
189
 
 
190
        # Cancel any existing diff task
 
191
        $self->task_reset;
 
192
 
 
193
        # Hide the widgets when no files are open
 
194
        unless ($document) {
 
195
                $self->clear;
 
196
                return;
 
197
        }
 
198
 
 
199
        # Shortcut if there is nothing to search for
 
200
        if ( $document->is_unused ) {
 
201
                return;
 
202
        }
 
203
 
 
204
        # Trigger the task to fetch the refresh data
 
205
        $self->task_request(
 
206
                task     => 'Padre::Task::Diff',
 
207
                document => $document,
 
208
        );
 
209
}
 
210
 
 
211
# Generic method to select next or previous difference
 
212
sub _select_next_prev_difference {
 
213
        my $self             = shift;
 
214
        my $select_next_diff = shift;
 
215
        my $current          = $self->{main}->current or return;
 
216
        my $editor           = $current->editor or return;
 
217
 
 
218
        # Sort lines in ascending order
 
219
        my @lines = sort { $a <=> $b } keys %{ $self->{diffs} };
 
220
 
 
221
        # Lines in descending order if select previous diff is enabled
 
222
        @lines = reverse @lines unless $select_next_diff;
 
223
 
 
224
        my $current_line   = $editor->LineFromPosition( $editor->GetCurrentPos );
 
225
        my $line_to_select = undef;
 
226
        for my $line (@lines) {
 
227
                unless ( defined $line_to_select ) {
 
228
                        $line_to_select = $line;
 
229
                }
 
230
                if ($select_next_diff) {
 
231
 
 
232
                        # Next difference
 
233
                        if ( $line > $current_line ) {
 
234
                                $line_to_select = $line;
 
235
                                last;
 
236
                        }
 
237
                } else {
 
238
 
 
239
                        # Previous difference
 
240
                        if ( $line < $current_line ) {
 
241
                                $line_to_select = $line;
 
242
                                last;
 
243
                        }
 
244
                }
 
245
        }
 
246
        if ( defined $line_to_select ) {
 
247
 
 
248
                # Select the line in the editor and show the diff box
 
249
                Padre::Util::select_line_in_editor( $line_to_select, $editor );
 
250
                $self->show_diff_box( $line_to_select, $editor );
 
251
        } else {
 
252
                $self->{main}->error( Wx::gettext('No changes found') );
 
253
        }
 
254
}
 
255
 
 
256
# Selects the next difference in the editor
 
257
sub select_next_difference {
 
258
        $_[0]->_select_next_prev_difference(1);
 
259
}
 
260
 
 
261
# Selects the previous difference in the editor
 
262
sub select_previous_difference {
 
263
        $_[0]->_select_next_prev_difference(0);
 
264
}
 
265
 
 
266
# Shows the difference dialog box for the provided line in the editor provided
 
267
sub show_diff_box {
 
268
        my $self   = shift;
 
269
        my $line   = shift;
 
270
        my $editor = shift;
 
271
        my $diff   = $self->{diffs}->{$line} or return;
 
272
 
 
273
        unless ( defined $self->{dialog} ) {
 
274
                $self->{dialog} = Padre::Wx::Dialog::Diff->new( $self->{main} );
 
275
        }
 
276
        $self->{dialog}->show(
 
277
                $editor, $line, $diff,
 
278
                $editor->PointFromPosition( $editor->PositionFromLine( $line + 1 ) )
 
279
        );
 
280
}
 
281
 
 
282
1;
 
283
 
 
284
# Copyright 2008-2011 The Padre development team as listed in Padre.pm.
 
285
# LICENSE
 
286
# This program is free software; you can redistribute it and/or
 
287
# modify it under the same terms as Perl 5 itself.