The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Padre::Wx::Dialog::Diff;

use 5.008;
use strict;
use warnings;
use Padre::Constant ();
use Padre::Wx       ();

our $VERSION = '0.96';
our @ISA     = (
	'Padre::Wx::Role::Main',
	'Wx::PopupWindow',
);

sub new {
	my $class = shift;
	my $self  = $class->SUPER::new(@_);

	my $panel = Wx::Panel->new($self);

	$self->{prev_diff_button} = Wx::BitmapButton->new(
		$panel,
		-1,
		Padre::Wx::Icon::find("actions/go-up"),
	);
	$self->{prev_diff_button}->SetToolTip( Wx::gettext('Previous difference') );
	$self->{next_diff_button} = Wx::BitmapButton->new(
		$panel,
		-1,
		Padre::Wx::Icon::find("actions/go-down"),
	);
	$self->{next_diff_button}->SetToolTip( Wx::gettext('Next difference') );

	$self->{revert_button} = Wx::BitmapButton->new(
		$panel,
		-1,
		Padre::Wx::Icon::find("actions/edit-undo"),
	);
	$self->{revert_button}->SetToolTip( Wx::gettext('Revert this change') );

	$self->{close_button} = Wx::BitmapButton->new(
		$panel,
		-1,
		Padre::Wx::Icon::find("actions/window-close"),
	);
	$self->{close_button}->SetToolTip( Wx::gettext('Close this window') );

	$self->{status_label} = Wx::TextCtrl->new(
		$panel,
		-1,
		'',
		Wx::DefaultPosition,
		[ 130, -1 ],
		Wx::TE_READONLY,
	);

	$self->{text_ctrl} = Wx::TextCtrl->new(
		$panel,
		-1,
		'',
		Wx::DefaultPosition,

		# (pbp line = 78 chrs) *2/3=52
		# (9/16) 52 chrs plus a half; (52*9)+4 = 472
		# 4 lines plus a half: (4*16)+8= 72
		[ 472, 72 ],
		Wx::TE_READONLY | Wx::TE_MULTILINE | Wx::TE_DONTWRAP,
	);

	my $button_sizer = Wx::BoxSizer->new(Wx::HORIZONTAL);
	$button_sizer->Add( $self->{prev_diff_button}, 0, 0, 0 );
	$button_sizer->Add( $self->{next_diff_button}, 0, 0, 0 );
	$button_sizer->Add( $self->{revert_button},    0, 0, 0 );
	$button_sizer->AddSpacer(10);
	$button_sizer->Add( $self->{status_label}, 0, Wx::ALL, 0 );
	$button_sizer->AddStretchSpacer;
	$button_sizer->Add( $self->{close_button}, 0, 0, 0 );

	my $vsizer = Wx::BoxSizer->new(Wx::VERTICAL);
	$vsizer->AddSpacer(1);
	$vsizer->Add( $button_sizer,      0, Wx::ALL | Wx::EXPAND, 1 );
	$vsizer->Add( $self->{text_ctrl}, 0, Wx::ALL | Wx::EXPAND, 1 );

	# Previous difference button
	Wx::Event::EVT_BUTTON(
		$self,
		$self->{prev_diff_button},
		\&on_prev_diff_button,
	);

	# Next difference button
	Wx::Event::EVT_BUTTON(
		$self,
		$self->{next_diff_button},
		\&on_next_diff_button,
	);


	# Revert button
	Wx::Event::EVT_BUTTON(
		$self,
		$self->{revert_button},
		\&on_revert_button,
	);

	# Close button
	Wx::Event::EVT_BUTTON(
		$self,
		$self->{close_button},
		sub {
			$_[0]->Hide;
		}
	);

	$panel->SetSizer($vsizer);
	$panel->Fit;
	$self->Fit;

	return $self;
}

sub on_prev_diff_button {
	$_[0]->main->diff->select_previous_difference;
}

sub on_next_diff_button {
	$_[0]->main->diff->select_next_difference;
}

sub on_revert_button {
	my $self = shift;

	my $editor   = $self->{editor};
	my $line     = $self->{line};
	my $diff     = $self->{diff};
	my $old_text = $diff->{old_text};
	my $new_text = $diff->{new_text};

	my $start = $editor->PositionFromLine($line);
	my $end   = $editor->GetLineEndPosition( $line + $diff->{lines_added} ) + 1;
	$editor->SetTargetStart($start);
	$editor->SetTargetEnd( $start + length($new_text) );
	$editor->ReplaceTarget( $old_text ? $old_text : '' );

	$self->Hide;
}

sub show {

	my $self   = shift;
	my $editor = shift;
	my $line   = shift;
	my $diff   = shift;
	my $pt     = shift;

	my $type = $diff->{type} or return;

	# Store editor reference so we can access it in revert
	$self->{editor} = $editor;
	$self->{line}   = $line;
	$self->{diff}   = $diff;

	# Inherit font from current editor
	my $font = $editor->GetFont;
	$self->{status_label}->SetFont($font);
	$self->{text_ctrl}->SetFont($font);

	# Hack to workaround Wx::PopupWindow relative positioning bug
	if (Padre::Constant::WIN32) {
		$self->Move( $self->main->ScreenToClient( $editor->ClientToScreen($pt) ) );
	} else {
		$self->Move( $editor->ClientToScreen($pt) );
	}

	my $color;
	if ( $type eq 'A' ) {
		$color = Padre::Wx::Editor::DARK_GREEN();
	} elsif ( $type eq 'D' ) {
		$color = Padre::Wx::Editor::LIGHT_RED();
	} elsif ( $type eq 'C' ) {
		$color = Padre::Wx::Editor::LIGHT_BLUE();
	} else {
		$color = Wx::Colour->new("black");
	}
	$self->{text_ctrl}->SetBackgroundColour($color);

	$self->{status_label}->SetValue( $diff->{message} );
	if ( $diff->{old_text} ) {
		$self->{text_ctrl}->SetValue( $diff->{old_text} );
		$self->{text_ctrl}->Show(1);
	} else {
		$self->{text_ctrl}->Show(0);
	}


	# Hide when the editor loses focus
	my $popup = $self;
	Wx::Event::EVT_KILL_FOCUS(
		$editor,
		sub {
			$popup->Hide;
		}
	);

	Wx::Event::EVT_KEY_UP(
		$editor,
		sub {
			my ( $self, $event ) = @_;
			if ( $event->GetKeyCode == Wx::WXK_ESCAPE ) {

				# Escape hides the diff box
				$popup->Hide;
			}
			$event->Skip;
		}
	);

	my $panel = $self->{text_ctrl}->GetParent;
	$panel->Layout;
	$panel->Fit;
	$self->Fit;

	$self->Show(1);
}

1;

# Copyright 2008-2012 The Padre development team as listed in Padre.pm.
# LICENSE
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl 5 itself.