# --*-Perl-*--
# $Id: SearchDialog.pm 11 2004-11-22 23:56:20Z tandler $
#
package PBibTk::SearchDialog;
use strict;
use Tk;
use Tk::LabFrame;
use Tk::LabEntry;
use Data::Dumper;
use PBibTk::Main;
# use LitRefs;
use PBibTk::RefDialog;
#use LitUI::SearchDialog;
BEGIN {
use vars qw($Revision $VERSION);
my $major = 1; q$Revision: 11 $ =~ /: (\d+)/; my ($minor) = ($1); $VERSION = "$major." . ($minor<10 ? '0' : '') . $minor;
}
#
# constants
#
our $defwidth_list = 96;
our $defheight_list = 16;
our $maxheight_list = 20;
our $maxlength_title = 40;
our $maxlength_author = 32;
#
#
#
sub new {
my $class = shift;
my ($ui, $title, $pattern, $queryFields, $resultFields) = @_;
my $dialog = {
'pBibTkUI' => $ui,
'title' => $title,
'queryFields' => $queryFields,
'resultFields' => $resultFields,
'pattern' => $pattern,
};
return bless $dialog, $class;
}
sub show {
my $self = shift;
$self->window()->focus();
}
#
# access methods
#
sub window {
my $self = shift;
my $win = $self->{'window'};
return $win if defined($win);
my $ui = $self->pBibTkUI();
my $title = $self->{'title'};
$win = $ui->rootWindow()->Toplevel();
$win->configure(
-title => $self->title(),
-width => 700,
-height => 600,
);
$self->{'window'} = $win;
$self->initWidgets($win);
$self->updateResults();
return $win;
}
# sub litRefs { my $self = shift; return $self->litUI()->litRefs(); }
sub biblio { my $self = shift; return $self->pBibTkUI()->biblio(); }
sub pBibTkUI { my $self = shift; return $self->{'pBibTkUI'}; }
sub title { my $self = shift; my $title = $self->{'title'};
return defined($title) ? $title : "Search Results"; }
sub pattern { my $self = shift; return $self->{'pattern'}; }
sub queryFields { my $self = shift; return $self->{'queryFields'}; }
sub resultFields { my $self = shift; return $self->{'resultFields'}; }
sub results { my $self = shift; return $self->{'results'}; }
sub conv { my $self = shift; return $self->pBibTkUI()->conv(@_); }
#
# widgets
#
sub initWidgets {
my ($self, $win) = @_;
my $cmd;
# menu inside a menu frame
# my $mf = $win->Frame()->grid(-sticky => 'ew');
# $mf->gridColumnconfigure(1, -weight => 1);
## my $mf = $win->Frame()->pack(qw/-fill x -side top/);
## $mf->gridColumnconfigure(1, -weight => 1);
my $mf = $win->Menu(-type => 'menubar');
$win->configure(-menu => $mf);
$self->initMenu($mf, $win);
# result list
my $list = $win->Scrolled('Listbox',
-scrollbars => 'se',
-width => $defwidth_list,
-height => $defheight_list,
)->form(
-t => ['%0', 0],
-l => ['%0', 0],
-r => ['%100', 0],
#-b => [$do, 0],
);
$self->{'resultList'} = $list;
$cmd = [$self, 'showSelectedBiblioReference'];
$list->bind('<Double-Button-1>' => $cmd);
$list->bind('<Return>' => $cmd);
$list->bind('<Button-1>' => [$self, 'updateExpandedSelectedReference']); #myline
# $win->bind('<Return>' => $cmd); ## don't open two windows ...
$list->bind('<Up>' => [$self, 'selectionMove', $list, -1]);
$list->bind('<Down>' => [$self, 'selectionMove', $list, 1]);
$list->bind('<Control-Home>' => [$self, 'selectionMove', $list, 0]);
$list->bind('<Control-End>' => [$self, 'selectionMove', $list, 'end']);
for( my $c = ord('a'); $c <= ord('z'); $c++ ) {
$win->bind(('<Key-' . chr($c) . '>') => [$self, 'keyPressed', Ev('A'), Ev('s')]);
$list->bind(('<Key-' . chr($c) . '>') => [$self, 'keyPressed', Ev('A'), Ev('s')]);
}
#myline runter ---------------------------------------------------
# chosen frame
my $do=$win->LabFrame(-label => 'choose a Ref', -labelside => "acrosstop")->form(
-t => [$list, 0],
-l => ['%0', 0],
-r => ['%100', 0],
-b =>['%100', 0],
);#pack(qw/-expand yes -fill x -side bottom/); #myline
$self->{'searchchosen'} = $do;
$list = $do->Scrolled('TextUndo',
-scrollbars => 'se',
-wrap => 'word',
-setgrid => 'true',
-exportselection => 'true',
-height => 6,
)->form(
-t => ['%0',0],
-l => ['%0',0],
-r => ['%100',0],
-b => ['%100', 0]);
$self->{'chosenfromlist'} = $list;
# my $b3=$do->Frame()->form(
# -t => [$list,0],
# -l => ['%0',0],
# -r => ['%100',0],
# -b => ['%100',0]);
# my $bf3 = $b3->Frame()->pack();
#myline hoch ---------------------------------------------------
}
#myline runter ---------------------------------------------------
sub updateExpandedSelectedReference {
my $self = shift;
my $paper = $self->selectedBiblioReference();
return if !defined($paper) || $paper eq "";
my @entry = PBibTk::RefDialog->new($self->pBibTkUI())->formatRefInfos($paper);
$self->chosenLabel()->configure(-label => $entry[0]);
my $list = $self->chosen();
$list->delete("0.0", "end");
$list->insert("end", $entry[1]);
$self->resultList()->focus();
}
sub selectedBiblioReference {
my $self = shift;
my $list = $self->resultList();
my $idx = $list->curselection();
return if !defined($idx) || $idx eq "";
my $paper = $self->{'results'}->[$idx];
return $paper;
# print Dumper $paper;
}
sub chosenLabel { my $self = shift; return $self->{'searchchosen'}; }
sub chosen {
my $self = shift;
# access window first, to ensure it's created.
$self->window();
return $self->{'chosenfromlist'};
}
#myline hoch ---------------------------------------------------
sub initMenu {
my ($self, $mf, $win) = @_;
$self->pBibTkUI()->initBiblioMenu($mf, $win, $self);
}
sub resultList { return shift->{'resultList'}; }
sub refList { return shift->resultList(); }
#
# menu command methods
#
sub keyPressed {
my ($self, $key, $mod) = @_;
return if $mod && $mod ne '';
my $list = $self->resultList();
my $idx = $self->indexOfRefStartingWith($key); ##ord($key) - ord('a');
print "keyPressed $key ($mod) --> $idx\n";
$list->selectionClear(0, 'end');
$list->see($idx);
$list->activate($idx);
$list->selectionAnchor($idx);
$list->selectionSet($idx);
}
sub selectionMove {
# called on UP and Down key presses to be able to adjust the printed ref.
my ($self, $list, $inc) = @_;
$self->updateExpandedSelectedReference();
}
sub showSelectedBiblioReference {
my $self = shift;
my $paper = $self->selectedBiblioReference();
return unless defined($paper);
PBibTk::RefDialog
->new($self->pBibTkUI(), $paper)
->show();
}
sub clipboardSelectedBiblioReferenceId {
my $self = shift;
my $paper = $self->selectedBiblioReference();
return unless defined($paper);
my $ref = $paper->{'CiteKey'};
Win32::Clipboard()->Set("[$ref]");
}
sub searchSelectedBiblioReferenceId {
my $self = shift;
my $paper = $self->selectedBiblioReference();
return unless defined($paper);
$self->pBibTkUI()->searchReferenceId($paper->{'CiteKey'});
}
sub queryAuthor { my $self = shift;
$self->pBibTkUI()->queryAuthor();
}
sub queryKeyword { my $self = shift;
$self->pBibTkUI()->queryKeyword();
}
sub updateBiblioRefs { my $self = shift;
$self->updateResults();
}
#
# updating
#
sub updateResults {
my $self = shift;
my $list = $self->resultList();
$list->delete(0, "end");
my $papers = $self->biblio()->queryPapers($self->pattern(),
$self->queryFields(), $self->resultFields());
$self->{'refs'} = $papers;
my ($ref, $id, @results);
my @refIDs = sort(keys %$papers);
foreach $id (@refIDs) {
$ref = $papers->{$id};
push @results, $ref;
my $key = $ref->{'CiteKey'} || '<<no CiteKey!?>>';
my $cat = $ref->{'Category'} || '<<no Category>>';
my $title = $ref->{'Title'} || '';
my $author = $ref->{'Authors'} || $ref->{'Editors'} || $ref->{'Organization'} || '';
my $recom = $ref->{'Recommendation'};
my $year = $ref->{'Year'} || '';
if( length($title) > $maxlength_title )
{ $title = substr($title, 0, $maxlength_title) . ' ...' }
if( $author ) {
if( length($author) > $maxlength_author )
{ $author = substr($author, 0, $maxlength_author) . ' ...' }
if( $year )
{ $author .= ', '; }
}
my $text = $key . ($recom ? " ($recom)" : '') . " \"$title\" ($author$year) [$cat]";
$list->insert("end", $text);
}
$self->{'results'} = \@results;
$self->window()->configure(
-title => $self->title() . ' (' . scalar(@results) . ' found)',
);
my $height = $list->height();
if( scalar @results > $height ) {
# enlarge window
$height = scalar @results;
$height = $maxheight_list if $height > $maxheight_list;
$list->configure(-height => $height);
}
}
sub indexOfRefStartingWith {
my ($self, $char) = @_;
return undef unless defined($char);
my $refs = $self->{'results'};
my $idx = 0;
for( ; $idx < scalar(@$refs); $idx++ ) {
my $key = $refs->[$idx]->{'CiteKey'};
# print ord(lc($char)), ' ', ord(lc(substr($key, 0, 1))), " $idx - $key";
last if( ord(lc($char)) <= ord(lc(substr($key, 0, 1))) );
}
return $idx;
}
1;
#
# $Log: LitUI::SearchDialog.pm,v $
# Revision 1.15 2004/03/30 19:20:10 krugar
# refactored:
# LitUIRefDialog -> LitUI::RefDialog
# LitUISearchDialog -> LitUI::SearchDialog
#
# Revision 1.14 2004/03/29 13:12:34 tandler
# box to see refs
#
# Revision 1.13 2003/12/22 21:59:41 tandler
# toni's changes: include explaination field in UI
#
# Revision 1.12 2003/06/12 22:19:21 tandler
# no significant change :-)
#
# Revision 1.11 2003/02/20 09:19:26 ptandler
# ignore null recommendation in title & search list
#
# Revision 1.10 2002/06/30 08:48:14 Diss
# bugfix: open only one ref window
#
# Revision 1.9 2002/06/29 18:28:32 Diss
# new query style, focus + jump-to-by-key for all ref lists
#
# Revision 1.8 2002/06/19 15:59:20 Diss
# - window is opened with focus
# - menus restuctred
# - menu keyboard shortcuts (Alt-B)
# - return and double-click to show reference details window
# - keys a-z to jump to ref in list
#
# Revision 1.7 2002/06/11 11:14:12 Diss
# sort search results
#
# Revision 1.6 2002/06/10 17:13:10 Diss
# adapted initial window sizes + minor "searchInEditor" fix
#
# Revision 1.5 2002/06/07 11:21:41 Diss
# bugfix: 'PaperID' -> 'CiteKey'
# new menus for search dialog
#
# Revision 1.4 2002/03/22 17:31:02 Diss
# small changes
#
# Revision 1.3 2002/03/18 11:15:50 Diss
# major additions: replace [] refs, generate bibliography using [{}], ...
#
# Revision 1.2 2002/03/07 12:01:06 Diss
# menu bar, use LitUIRefDialog
#
# Revision 1.1 2002/02/11 11:57:06 Diss
# lit UI with search dialog, script to start/stop biblio, and more ...
#