Gdraw2-v0.0.3000755001750001750 012001671021 12775 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/META.json000444001750001750 1636612001671021 14607 0ustar00yangxiyangxi000000000000{ "abstract" : "Drawing genome graphs in various ways", "author" : [ "Xi Yang " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Gdraw2", "prereqs" : { "build" : { "requires" : { "Test::More" : "0" } }, "configure" : { "requires" : { "Module::Build" : "0.38" } }, "runtime" : { "requires" : { "Bio::SeqIO" : "0", "Cairo" : "0", "File::ShareDir" : "1.00", "Gtk2" : "0", "Moose" : "0", "Scalar::Util" : "0", "YAML" : "0", "common::sense" : "0" } } }, "provides" : { "Gdraw2::AbstractTrack" : { "file" : "lib/Gdraw2/AbstractTrack.pm", "version" : 0 }, "Gdraw2::AbstractTrackGroup" : { "file" : "lib/Gdraw2/AbstractTrackGroup.pm", "version" : 0 }, "Gdraw2::AbstractTrackPage" : { "file" : "lib/Gdraw2/AbstractTrackPage.pm", "version" : 0 }, "Gdraw2::CairoTrack" : { "file" : "lib/Gdraw2/CairoTrack.pm", "version" : 0 }, "Gdraw2::CairoTrackGroup" : { "file" : "lib/Gdraw2/CairoTrackGroup.pm", "version" : 0 }, "Gdraw2::CairoTrackPage" : { "file" : "lib/Gdraw2/CairoTrackPage.pm", "version" : 0 }, "Gdraw2::Element::AbstractBlock" : { "file" : "lib/Gdraw2/Element/AbstractBlock.pm", "version" : 0 }, "Gdraw2::Element::AbstractDataCurve" : { "file" : "lib/Gdraw2/Element/AbstractDataCurve.pm", "version" : 0 }, "Gdraw2::Element::AbstractElement" : { "file" : "lib/Gdraw2/Element/AbstractElement.pm", "version" : 0 }, "Gdraw2::Element::AbstractMapping" : { "file" : "lib/Gdraw2/Element/AbstractMapping.pm", "version" : 0 }, "Gdraw2::Element::AbstractPair" : { "file" : "lib/Gdraw2/Element/AbstractPair.pm", "version" : 0 }, "Gdraw2::Element::AbstractRuler" : { "file" : "lib/Gdraw2/Element/AbstractRuler.pm", "version" : 0 }, "Gdraw2::Element::AbstractTagset" : { "file" : "lib/Gdraw2/Element/AbstractTagset.pm", "version" : 0 }, "Gdraw2::Element::CairoBlock" : { "file" : "lib/Gdraw2/Element/CairoBlock.pm", "version" : 0 }, "Gdraw2::Element::CairoDataCurve" : { "file" : "lib/Gdraw2/Element/CairoDataCurve.pm", "version" : 0 }, "Gdraw2::Element::CairoMapping" : { "file" : "lib/Gdraw2/Element/CairoMapping.pm", "version" : 0 }, "Gdraw2::Element::CairoPair" : { "file" : "lib/Gdraw2/Element/CairoPair.pm", "version" : 0 }, "Gdraw2::Element::CairoRuler" : { "file" : "lib/Gdraw2/Element/CairoRuler.pm", "version" : 0 }, "Gdraw2::Element::CairoTagset" : { "file" : "lib/Gdraw2/Element/CairoTagset.pm", "version" : 0 }, "Gdraw2::Element::RoleArrangeable" : { "file" : "lib/Gdraw2/Element/RoleArrangeable.pm", "version" : 0 }, "Gdraw2::Element::RoleCairoDefaultNameLead" : { "file" : "lib/Gdraw2/Element/RoleCairoDefaultNameLead.pm", "version" : 0 }, "Gdraw2::Element::RoleCairoElement" : { "file" : "lib/Gdraw2/Element/RoleCairoElement.pm", "version" : 0 }, "Gdraw2::Meta::Attribute::Recordable" : { "file" : "lib/Gdraw2/Meta/Attribute/Recordable.pm", "version" : 0 }, "Gdraw2::Meta::Attribute::RecordableParam" : { "file" : "lib/Gdraw2/Meta/Attribute/RecordableParam.pm", "version" : 0 }, "Gdraw2::Util" : { "file" : "lib/Gdraw2/Util.pm", "version" : 0 }, "Gdraw2::Util::Arranger" : { "file" : "lib/Gdraw2/Util/Arranger.pm", "version" : 0 }, "Gdraw2::Util::GroupArranger" : { "file" : "lib/Gdraw2/Util/GroupArranger.pm", "version" : 0 }, "Gdraw2::Util::RGBAColor" : { "file" : "lib/Gdraw2/Util/RGBAColor.pm", "version" : 0 }, "Gdraw2::Util::RGBColor" : { "file" : "lib/Gdraw2/Util/RGBColor.pm", "version" : 0 }, "Gdraw2::Util::RoleAbstractChild" : { "file" : "lib/Gdraw2/Util/RoleAbstractChild.pm", "version" : 0 }, "Gdraw2::Util::RoleAbstractParent" : { "file" : "lib/Gdraw2/Util/RoleAbstractParent.pm", "version" : 0 }, "Gdraw2::Util::RoleArrangeable" : { "file" : "lib/Gdraw2/Util/RoleArrangeable.pm", "version" : 0 }, "Gdraw2::Util::RoleRecordable" : { "file" : "lib/Gdraw2/Util/RoleRecordable.pm", "version" : 0 }, "Gdraw2::Util::SharedObject" : { "file" : "lib/Gdraw2/Util/SharedObject.pm", "version" : 0 }, "Gdraw2Gtk::Act" : { "file" : "lib/Gdraw2Gtk/Act.pm", "version" : 0 }, "Gdraw2Gtk::Act::Add" : { "file" : "lib/Gdraw2Gtk/Act.pm", "version" : 0 }, "Gdraw2Gtk::Act::Config" : { "file" : "lib/Gdraw2Gtk/Act.pm", "version" : 0 }, "Gdraw2Gtk::Act::Indexed" : { "file" : "lib/Gdraw2Gtk/Act.pm", "version" : 0 }, "Gdraw2Gtk::Act::Move" : { "file" : "lib/Gdraw2Gtk/Act.pm", "version" : 0 }, "Gdraw2Gtk::Act::Remove" : { "file" : "lib/Gdraw2Gtk/Act.pm", "version" : 0 }, "Gdraw2Gtk::App" : { "file" : "lib/Gdraw2Gtk/App.pm", "version" : 0 }, "Gdraw2Gtk::BlastImportConfig" : { "file" : "lib/Gdraw2Gtk/BlastImportConfig.pm", "version" : 0 }, "Gdraw2Gtk::EleTypeWizard" : { "file" : "lib/Gdraw2Gtk/EleTypeWizard.pm", "version" : 0 }, "Gdraw2Gtk::ElementEditor" : { "file" : "lib/Gdraw2Gtk/ElementEditor.pm", "version" : 0 }, "Gdraw2Gtk::GroupEditor" : { "file" : "lib/Gdraw2Gtk/GroupEditor.pm", "version" : 0 }, "Gdraw2Gtk::PageEditor" : { "file" : "lib/Gdraw2Gtk/PageEditor.pm", "version" : 0 }, "Gdraw2Gtk::RichSeqImportConfig" : { "file" : "lib/Gdraw2Gtk/RichSeqImportConfig.pm", "version" : 0 }, "Gdraw2Gtk::Task" : { "file" : "lib/Gdraw2Gtk/Task.pm", "version" : 0 }, "Gdraw2Gtk::TrackEditor" : { "file" : "lib/Gdraw2Gtk/TrackEditor.pm", "version" : 0 }, "Gdrwa2::Version" : { "file" : "lib/Gdraw2/Version.pm", "version" : "v0.0.3" }, "Moose::Meta::Attribute::Custom::Recordable" : { "file" : "lib/Gdraw2/Util/RoleRecordable.pm", "version" : 0 } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "v0.0.3" } Gdraw2-v0.0.3/Build.PL000555001750001750 153512001671021 14435 0ustar00yangxiyangxi000000000000use strict; use warnings; use Module::Build; my $builder = Module::Build->new( module_name => 'Gdraw2', license => 'perl', dist_author => q{Xi Yang }, dist_version_from => 'lib/Gdraw2/Version.pm', dist_abstract => 'Drawing genome graphs in various ways', configure_requires => { 'Module::Build' => 0.38 }, build_requires => { 'Test::More' => 0 }, requires => { 'common::sense' => 0, 'File::ShareDir' => 0, 'Cairo' => 0, 'Gtk2' => 0, 'Moose' => 0, 'Scalar::Util' => 0, 'Bio::SeqIO' => 0, 'YAML' => 0 }, share_dir => 'data', add_to_cleanup => ['Gdraw2-*'], create_makefile_pl => 'traditional', ); $builder->create_build_script(); Gdraw2-v0.0.3/MANIFEST000444001750001750 416112001671021 14265 0ustar00yangxiyangxi000000000000.settings/org.eclipse.ltk.core.refactoring.prefs bin/Gdraw2.pl Build.PL Changes data/BlastImporter.glade data/block.png data/curve.png data/EleEditor.glade data/EleTypeWizard.glade data/FeatureImporter.glade data/FileDialogs.glade data/Gdraw2UI.glade data/GroupEditor.glade data/mapping.png data/PageEditor.glade data/ruler.png data/tagset.png data/TrackEditor.glade lib/Gdraw2/AbstractTrack.pm lib/Gdraw2/AbstractTrackGroup.pm lib/Gdraw2/AbstractTrackPage.pm lib/Gdraw2/CairoTrack.pm lib/Gdraw2/CairoTrackGroup.pm lib/Gdraw2/CairoTrackPage.pm lib/Gdraw2/Element/AbstractBlock.pm lib/Gdraw2/Element/AbstractDataCurve.pm lib/Gdraw2/Element/AbstractElement.pm lib/Gdraw2/Element/AbstractMapping.pm lib/Gdraw2/Element/AbstractPair.pm lib/Gdraw2/Element/AbstractRuler.pm lib/Gdraw2/Element/AbstractTagset.pm lib/Gdraw2/Element/CairoBlock.pm lib/Gdraw2/Element/CairoDataCurve.pm lib/Gdraw2/Element/CairoMapping.pm lib/Gdraw2/Element/CairoPair.pm lib/Gdraw2/Element/CairoRuler.pm lib/Gdraw2/Element/CairoTagset.pm lib/Gdraw2/Element/RoleArrangeable.pm lib/Gdraw2/Element/RoleCairoDefaultNameLead.pm lib/Gdraw2/Element/RoleCairoElement.pm lib/Gdraw2/Meta/Attribute/Recordable.pm lib/Gdraw2/Meta/Attribute/RecordableParam.pm lib/Gdraw2/Util.pm lib/Gdraw2/Util/Arranger.pm lib/Gdraw2/Util/GroupArranger.pm lib/Gdraw2/Util/RGBAColor.pm lib/Gdraw2/Util/RGBColor.pm lib/Gdraw2/Util/RoleAbstractChild.pm lib/Gdraw2/Util/RoleAbstractParent.pm lib/Gdraw2/Util/RoleArrangeable.pm lib/Gdraw2/Util/RoleRecordable.pm lib/Gdraw2/Util/SharedObject.pm lib/Gdraw2/Version.pm lib/Gdraw2Gtk/Act.pm lib/Gdraw2Gtk/App.pm lib/Gdraw2Gtk/BlastImportConfig.pm lib/Gdraw2Gtk/ElementEditor.pm lib/Gdraw2Gtk/EleTypeWizard.pm lib/Gdraw2Gtk/GroupEditor.pm lib/Gdraw2Gtk/PageEditor.pm lib/Gdraw2Gtk/RichSeqImportConfig.pm lib/Gdraw2Gtk/Task.pm lib/Gdraw2Gtk/TrackEditor.pm Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.json META.yml t/Arranger.t t/CairoTrack.t t/circ.svg t/circ.t t/circ_mapping.svg t/circ_mapping.t t/corona_sars.gb t/Element.t t/full_cairo.pdf t/full_cairo.t t/full_cairo.yaml t/group_layout.svg t/group_layout.t t/load.pdf t/load.t t/short.pdf t/short.t t/util.t Gdraw2-v0.0.3/MANIFEST.SKIP000444001750001750 30012001671021 15001 0ustar00yangxiyangxi000000000000^MYMETA.yml$ ^MYMETA\.json$ \.svn ~$ _build cds_graph.yaml circ.pdf foo.yaml Gdraw2_old.pl pod_creator.pl show_recordable.pl \.tar\.gz$ blib \.fasta$ MANIFEST.bak ^Build$ .project .includepathGdraw2-v0.0.3/Makefile.PL000444001750001750 124712001671021 15110 0ustar00yangxiyangxi000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.40 use ExtUtils::MakeMaker; WriteMakefile ( 'PL_FILES' => {}, 'INSTALLDIRS' => 'site', 'NAME' => 'Gdraw2', 'EXE_FILES' => [ 'bin/Gdraw2.pl' ], 'VERSION_FROM' => 'lib/Gdraw2/Version.pm', 'PREREQ_PM' => { 'Scalar::Util' => 0, 'YAML' => 0, 'Cairo' => 0, 'Bio::SeqIO' => 0, 'Test::More' => 0, 'File::ShareDir' => '1.00', 'common::sense' => 0, 'Gtk2' => 0, 'Moose' => 0 } ) ; Gdraw2-v0.0.3/META.yml000444001750001750 1162412001671021 14427 0ustar00yangxiyangxi000000000000--- abstract: 'Drawing genome graphs in various ways' author: - 'Xi Yang ' build_requires: Test::More: 0 configure_requires: Module::Build: 0.38 dynamic_config: 1 generated_by: 'Module::Build version 0.4, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Gdraw2 provides: Gdraw2::AbstractTrack: file: lib/Gdraw2/AbstractTrack.pm version: 0 Gdraw2::AbstractTrackGroup: file: lib/Gdraw2/AbstractTrackGroup.pm version: 0 Gdraw2::AbstractTrackPage: file: lib/Gdraw2/AbstractTrackPage.pm version: 0 Gdraw2::CairoTrack: file: lib/Gdraw2/CairoTrack.pm version: 0 Gdraw2::CairoTrackGroup: file: lib/Gdraw2/CairoTrackGroup.pm version: 0 Gdraw2::CairoTrackPage: file: lib/Gdraw2/CairoTrackPage.pm version: 0 Gdraw2::Element::AbstractBlock: file: lib/Gdraw2/Element/AbstractBlock.pm version: 0 Gdraw2::Element::AbstractDataCurve: file: lib/Gdraw2/Element/AbstractDataCurve.pm version: 0 Gdraw2::Element::AbstractElement: file: lib/Gdraw2/Element/AbstractElement.pm version: 0 Gdraw2::Element::AbstractMapping: file: lib/Gdraw2/Element/AbstractMapping.pm version: 0 Gdraw2::Element::AbstractPair: file: lib/Gdraw2/Element/AbstractPair.pm version: 0 Gdraw2::Element::AbstractRuler: file: lib/Gdraw2/Element/AbstractRuler.pm version: 0 Gdraw2::Element::AbstractTagset: file: lib/Gdraw2/Element/AbstractTagset.pm version: 0 Gdraw2::Element::CairoBlock: file: lib/Gdraw2/Element/CairoBlock.pm version: 0 Gdraw2::Element::CairoDataCurve: file: lib/Gdraw2/Element/CairoDataCurve.pm version: 0 Gdraw2::Element::CairoMapping: file: lib/Gdraw2/Element/CairoMapping.pm version: 0 Gdraw2::Element::CairoPair: file: lib/Gdraw2/Element/CairoPair.pm version: 0 Gdraw2::Element::CairoRuler: file: lib/Gdraw2/Element/CairoRuler.pm version: 0 Gdraw2::Element::CairoTagset: file: lib/Gdraw2/Element/CairoTagset.pm version: 0 Gdraw2::Element::RoleArrangeable: file: lib/Gdraw2/Element/RoleArrangeable.pm version: 0 Gdraw2::Element::RoleCairoDefaultNameLead: file: lib/Gdraw2/Element/RoleCairoDefaultNameLead.pm version: 0 Gdraw2::Element::RoleCairoElement: file: lib/Gdraw2/Element/RoleCairoElement.pm version: 0 Gdraw2::Meta::Attribute::Recordable: file: lib/Gdraw2/Meta/Attribute/Recordable.pm version: 0 Gdraw2::Meta::Attribute::RecordableParam: file: lib/Gdraw2/Meta/Attribute/RecordableParam.pm version: 0 Gdraw2::Util: file: lib/Gdraw2/Util.pm version: 0 Gdraw2::Util::Arranger: file: lib/Gdraw2/Util/Arranger.pm version: 0 Gdraw2::Util::GroupArranger: file: lib/Gdraw2/Util/GroupArranger.pm version: 0 Gdraw2::Util::RGBAColor: file: lib/Gdraw2/Util/RGBAColor.pm version: 0 Gdraw2::Util::RGBColor: file: lib/Gdraw2/Util/RGBColor.pm version: 0 Gdraw2::Util::RoleAbstractChild: file: lib/Gdraw2/Util/RoleAbstractChild.pm version: 0 Gdraw2::Util::RoleAbstractParent: file: lib/Gdraw2/Util/RoleAbstractParent.pm version: 0 Gdraw2::Util::RoleArrangeable: file: lib/Gdraw2/Util/RoleArrangeable.pm version: 0 Gdraw2::Util::RoleRecordable: file: lib/Gdraw2/Util/RoleRecordable.pm version: 0 Gdraw2::Util::SharedObject: file: lib/Gdraw2/Util/SharedObject.pm version: 0 Gdraw2Gtk::Act: file: lib/Gdraw2Gtk/Act.pm version: 0 Gdraw2Gtk::Act::Add: file: lib/Gdraw2Gtk/Act.pm version: 0 Gdraw2Gtk::Act::Config: file: lib/Gdraw2Gtk/Act.pm version: 0 Gdraw2Gtk::Act::Indexed: file: lib/Gdraw2Gtk/Act.pm version: 0 Gdraw2Gtk::Act::Move: file: lib/Gdraw2Gtk/Act.pm version: 0 Gdraw2Gtk::Act::Remove: file: lib/Gdraw2Gtk/Act.pm version: 0 Gdraw2Gtk::App: file: lib/Gdraw2Gtk/App.pm version: 0 Gdraw2Gtk::BlastImportConfig: file: lib/Gdraw2Gtk/BlastImportConfig.pm version: 0 Gdraw2Gtk::EleTypeWizard: file: lib/Gdraw2Gtk/EleTypeWizard.pm version: 0 Gdraw2Gtk::ElementEditor: file: lib/Gdraw2Gtk/ElementEditor.pm version: 0 Gdraw2Gtk::GroupEditor: file: lib/Gdraw2Gtk/GroupEditor.pm version: 0 Gdraw2Gtk::PageEditor: file: lib/Gdraw2Gtk/PageEditor.pm version: 0 Gdraw2Gtk::RichSeqImportConfig: file: lib/Gdraw2Gtk/RichSeqImportConfig.pm version: 0 Gdraw2Gtk::Task: file: lib/Gdraw2Gtk/Task.pm version: 0 Gdraw2Gtk::TrackEditor: file: lib/Gdraw2Gtk/TrackEditor.pm version: 0 Gdrwa2::Version: file: lib/Gdraw2/Version.pm version: v0.0.3 Moose::Meta::Attribute::Custom::Recordable: file: lib/Gdraw2/Util/RoleRecordable.pm version: 0 requires: Bio::SeqIO: 0 Cairo: 0 File::ShareDir: 1.00 Gtk2: 0 Moose: 0 Scalar::Util: 0 YAML: 0 common::sense: 0 resources: license: http://dev.perl.org/licenses/ version: v0.0.3 Gdraw2-v0.0.3/Changes000444001750001750 47312001671021 14411 0ustar00yangxiyangxi0000000000000.0.3: - PostScript export. - Removed deprecated module dependencies. - Downgraded Gtk+ requirement from 2.2.24 to 2.2.22. 0.0.2: - Import SearchIO-compatiable files, such as BLAST, FASTA. - PODs for some modules. 0.0.1: - Import SeqIO-compatible sequneces, such as Genbank, EMBL. - Undo/Redo for all operations. Gdraw2-v0.0.3/bin000755001750001750 012001671021 13545 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/bin/Gdraw2.pl000555001750001750 15112001671021 15345 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use common::sense; use Gdraw2Gtk::App; my $app = Gdraw2Gtk::App->new(); $app->run(); Gdraw2-v0.0.3/lib000755001750001750 012001671021 13543 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2000755001750001750 012001671021 14671 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2/CairoTrackGroup.pm000444001750001750 356412001671021 20433 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::CairoTrackGroup - track group impelemented using Cairo =head1 SYNOPSIS use Gdraw2::CairoTrackGroup; my $group = Gdraw2::CairoTrackGroup->new( start => $group_start, end => $group_end ); # add to a page $page->addChild($group); =head1 DESCRIPTION The concrete group class implemented using Cairo 2D drawing library. See Gdraw2::AbstractTrackGroup for more information. =cut package Gdraw2::CairoTrackGroup; use Moose; use Gdraw2::AbstractTrackGroup; use Gdraw2::Util::SharedObject; use Carp qw/cluck/; extends 'Gdraw2::AbstractTrackGroup'; override draw => sub { my $self = shift; my $cr = $self->parent->cairoContext; $self->arrangeAll; if ($self->isCircular) { $cr->save; foreach my $track ($self->getChildren) { $track->draw; } $cr->restore; } else { # debug my $page = $self->parent; # group # $cr->save; # $cr->set_source_rgba(0,1,0,0.5); # $cr->set_line_width(1); # $cr->move_to(0,0); # $cr->line_to($page->width - $self->leftMargin - $self->rightMargin, 0); # $cr->stroke; # $cr->restore; ########################################## # we have been translated to group init site my $track_count = 0; foreach my $track ($self->getChildren) { $cr->save; $cr->translate(0,$track->trackCascade); $track->draw; # debug # if ($track_count>0) { # my $gstart = $track->graphicStart; # my $gend = $track->graphicEnd; # my $name_c = $track->calcNameCascade($track->numCascadeNameLines); # $cr->set_source_rgba(0.5,1,0.5,0.5); # $cr->rectangle($gstart,-$name_c-$self->trackDistance,$gend-$gstart,$self->trackDistance); # $cr->fill; # } ############################### $cr->restore; } continue {$track_count++} } }; 1; =head1 SEE ALSO Gdraw2::AbstractTrackGroup =cut Gdraw2-v0.0.3/lib/Gdraw2/AbstractTrack.pm000444001750001750 2767412001671021 20154 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::AbstractTrack - a series of genomic features =head1 SYNOPSIS # This is only a abstract base class, you # won't use it for a drawing directly. # Instead, you should use implementations. # See Gdraw2::CairoTrackGroup for detail. # However, if you want to use drawing backends other than Cairo, # you can create your own page class by extending this class, # and provide implementation to some methods. package My::Track; use Moose; use Gdraw2::AbstractTrack; extends 'Gdraw2::AbstractTrack'; override draw => sub { }; =head1 DESCRIPTION Track is a set of elements that are aligned in one line. =cut package Gdraw2::AbstractTrack; use threads::shared; use Moose; use Gdraw2::Util::SharedObject; use Gdraw2::Util::Arranger; use Gdraw2::Util qw/load_module/; =head1 EXTENDS Gdraw2::Util::SharedObject =head1 WITH Gdraw2::Util::RoleAbstractChild Gdraw2::Util::RoleAbstractParent Gdraw2::Util::RoleArrangeable Gdraw2::Util::RoleRecordable =cut extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleAbstractChild'; with 'Gdraw2::Util::RoleAbstractParent'; with 'Gdraw2::Util::RoleArrangeable'; with 'Gdraw2::Util::RoleRecordable'; =head1 PUBLIC ATTRIBUTES =head2 displayName desc : name of this track. is : read/write isa : Str default: "" =cut has displayName => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => '' ); =head2 start desc : elements exceed this value will not be shown. is : read/write isa : Num default: 1 =cut has start => ( is => 'rw', metaclass => 'Recordable', isa => 'Int', default => 1 ); =head2 end desc : elements exceed this value will not be shown. is : read/write isa : Num default: 1000 =cut has end => ( is => 'rw', metaclass => 'Recordable', isa => 'Int', default => 1000 ); =head2 elementWidth desc : the size of all elements in this track. is : read/write isa : Num default: 15 =cut has elementWidth => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 15 ); =head2 showGuideLine desc : whether to draw a thick grey line from track start to end. is : read/write isa : Bool default: 1 =cut has 'showGuideLine' => ( is => 'rw', metaclass => 'Recordable', isa => 'Bool', default => 1 ); =head1 PRIVATE ATTRIBUTES =head2 trackCascade =cut has trackCascade => ( is => 'rw', isa => 'Num', ); =head2 arrangers =cut has 'arrangers' => ( is => 'bare', isa => 'ArrayRef[Gdraw2::Util::Arranger]', default => sub { return shared_clone [ Gdraw2::Util::Arranger->new ] } ); =head2 nameArrangers =cut has 'nameArrangers' => ( is => 'bare', isa => 'ArrayRef[Gdraw2::Util::Arranger]', default => sub { return shared_clone [] } ); =head1 PUBLIC METHODS =head2 draw usage : $track->draw(); desc : render current track. Subclasses that actually perform the drawing should override this method. args : none. return: none. =cut sub draw { confess "need to be overriden" } sub graphicStart { my $self = shift; return $self->parent->calcGraphicPosition( $self->start ) - $self->parent->bitGraphicLength; } sub graphicEnd { my $self = shift; return $self->parent->calcGraphicPosition( $self->end ); } sub arrangeOneChild { my ( $self, $child ) = @_; return if !$child->meta->does_role('Gdraw2::Util::RoleArrangeable'); my $num = $self->numCascadeLines; my $succ = 0; my $i = 0; foreach my $arranger ( @{ $self->{arrangers} } ) { if ( !$arranger->overlaps($child) ) { $arranger->addChild($child); $child->cascadeLine($i); $succ = 1; last; } } continue { $i++; } if ( !$succ ) { my $arranger = Gdraw2::Util::Arranger->new; push @{ $self->{arrangers} }, $arranger; $arranger->addChild($child); $child->cascadeLine($i); } $child->arranged(1); } sub unarrangeOneChild { my ( $self, $child ) = @_; return if !$child->meta->does_role('Gdraw2::Util::RoleArrangeable'); # remove from arranger my $line_num = $self->numCascadeLines; for ( my $i = $child->cascadeLine ; $i < $line_num ; $i++ ) { my $arranger = $self->{arrangers}[$i]; # remove from its arranger if ( $i == $child->cascadeLine ) { $arranger->removeChild($child); } # remove affected children else { foreach my $curr ($arranger->getChildren) { if ( $curr->overlaps($child) ) { $arranger->removeChild($curr); $curr->arranged(0); $curr->cascadeLine(0); } } } } $child->arranged(0); $child->cascadeLine(0); # remove potential lasting empty arrangers while (1) { if ( $self->{arrangers}[-1]->numChildren == 0 ) { if ( @{ $self->{arrangers} } > 1 ) { pop @{ $self->{arrangers} }; } } else { last; } last if @{ $self->{arrangers} } == 1; } } sub arrangeOneChildName { my ( $self, $child ) = @_; if ( $child->showName and length( $child->displayName ) > 0 ) { my $succ = 0; my $i = 0; foreach my $name_arranger ( @{ $self->{nameArrangers} } ) { if ( !$name_arranger->nameOverlaps($child) ) { $name_arranger->addChild($child); $child->cascadeNameLine($i); $succ = 1; last; } } continue { $i++ } if ( !$succ ) { my $name_arranger = Gdraw2::Util::Arranger->new; push @{ $self->{nameArrangers} }, $name_arranger; $name_arranger->addChild($child); $child->cascadeNameLine($i); } } $child->nameArranged(1); } sub unarrangeOneChildName { my ( $self, $child ) = @_; #print "unarrangeOneChildName: amount of arrangers: ", # scalar( @{ $self->{nameArrangers} } ), "\n"; # traverse through all name arrangers my $line_num = $self->numCascadeNameLines; for ( my $i = $child->cascadeNameLine ; $i < $line_num ; $i++ ) { my $name_arranger = $self->{nameArrangers}[$i]; # remove from its arranger if ( $i == $child->cascadeNameLine ) { $name_arranger->removeChild($child); } # remove affected children else { foreach my $curr ($name_arranger->getChildren) { if ( $curr->nameOverlaps($child) ) { $name_arranger->removeChild($curr); $curr->nameArranged(0); $curr->cascadeNameLine(0); } } } } $child->nameArranged(0); $child->cascadeNameLine(0); # remove potential lasting arrangers # notice that the amount of nameline arranger is able to get to 0, unlike the line arranger while (1) { last if @{ $self->{nameArrangers} } == 0; if ( $self->{nameArrangers}[-1]->numChildren == 0 ) { pop @{ $self->{nameArrangers} }; } else { last; } } } sub arrangeOK { } sub calcCascade { my $self = shift; my $line = shift; return $line * $self->elementWidth * 1.2; } sub calcNameCascade { confess "implement this method in concrete class"; } sub numCascadeLines { return scalar @{ $_[0]->{arrangers} }; } sub numCascadeLinesInRegin { my $self = shift; my $start = shift; my $end = shift; my $line = 0; foreach my $child ( $self->getChildren ) { if ( $child->meta->does_role('Gdraw2::Element::RoleArrangeable') and !( $child->start > $end or $start > $child->end ) and $child->cascadeLine > $line ) { $line = $child->cascadeLine; } } return $line; } sub numCascadeNameLines { return scalar @{ $_[0]->{nameArrangers} }; } sub getTrackPage { return $_[0]->parent->parent; } sub isCircular { my $page = $_[0]->getTrackPage; confess "track not assigned to a page" if !defined $page; return $page->isCircular; } sub radius { my $self = shift; return $self->parent->groupRadius + $self->trackCascade; } sub maxContentCascade { my $self = shift; return $self->calcCascade( $self->numCascadeLines - 1 ); } sub maxRadius { my $self = shift; return $self->radius + $self->maxContentCascade + $self->elementWidth / 2; } sub arrangeAll { my $self = shift; if ( $self->isCircular ) { foreach my $curr ( $self->getChildren ) { $self->arrangeOneChild($curr) if $curr->meta->does_role('Gdraw2::Element::RoleArrangeable') and !$curr->arranged; $curr->nameArranged(1); } } else { foreach my $curr ( $self->getChildren ) { $self->arrangeOneChild($curr) if $curr->meta->does_role('Gdraw2::Element::RoleArrangeable') and !$curr->arranged; $self->arrangeOneChildName($curr) if !$curr->nameArranged; } } } sub unarrangeAll { my $self = shift; $self->{arrangers} = [Gdraw2::Util::Arranger->new]; $self->{nameArrangers} = []; foreach my $curr($self->getChildren) { $curr->arranged(0) if $curr->meta->does_role('Gdraw2::Element::RoleArrangeable'); $curr->nameArranged(0); } } around addChildAt => sub { my $orig = shift; my $self = shift; my $child = shift; my $i = shift; $self->$orig( $child, $i ); $child->parent($self); if ( defined $child->parent and defined $child->parent->parent ) { $self->arrangeOneChild($child) if $child->meta->does_role('Gdraw2::Element::RoleArrangeable') and defined $self->parent and defined $self->parent->parent; $self->arrangeOneChildName($child) if $child->showName and $child->displayName ne '' and defined $self->parent and defined $self->parent->parent and !$self->isCircular; } }; around removeChildAt => sub { my $orig = shift; my $self = shift; my $i = shift; my $removed = $self->$orig($i); if ( defined $removed ) { #$removed->parent(undef); if ( $removed->meta->does_role('Gdraw2::Element::RoleArrangeable') and $removed->arranged ) { $self->unarrangeOneChild($removed); } if ( $removed->nameArranged ) { $self->unarrangeOneChildName($removed); } } return $removed; }; around loadHash => sub { my $orig = shift; my $self = shift; my $store = shift; confess "store don't has children" if !exists $store->{children}; my @children = @{ $store->{children} }; delete $store->{children}; my $obj = $self->$orig( $store, @_ ); foreach my $child (@children) { confess "element store don't has class" if !exists $child->{CLASS}; my $ele_class = $child->{CLASS}; load_module($ele_class); my $ele = $ele_class->loadHash($child); $obj->addChild($ele); } # restore children $store->{children} = [@children]; return $obj; }; around toHash => sub { my $orig = shift; my $self = shift; my $hash = $self->$orig(@_); $hash->{children} = shared_clone []; foreach my $element ( @{ $self->{children} } ) { push @{ $hash->{children} }, $element->toHash; } return $hash; }; 1; =head1 RECORDABLE ATTRIBUTES These attributes will be serialized while calling "toHash". See "Gdraw2::Util::RoleRecordable" for details. elementWidth end showGuideLine displayName start =head1 SEE ALSO Gdraw2::AbstractTrackGroup Gdraw2::CairoTrack Gdraw2::Util::RoleAbstractParent Gdraw2::Util::RoleAbstractChild Gdraw2::Util::RoleRecordable =cutGdraw2-v0.0.3/lib/Gdraw2/CairoTrack.pm000444001750001750 461712001671021 17416 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::CairoTrack - track impelemented using Cairo =head1 SYNOPSIS use Gdraw2::CairoTrack; my $track = Gdraw2::CairoTrack->new( start => $track_start, end => $track_end ); # add to a group group->addChild($track); =head1 DESCRIPTION The concrete track class implemented using Cairo 2D drawing library. See Gdraw2::AbstractTrack for more information. =cut package Gdraw2::CairoTrack; use common::sense; use threads::shared; use Moose; use Gdraw2::AbstractTrack; use Gdraw2::CairoTrackGroup; use Gdraw2::Util::SharedObject; use Gdraw2::Util::RoleAbstractChild; use Gdraw2::Util::RoleAbstractParent; use Gdraw2::Util::RoleArrangeable; use Carp qw/cluck confess/; extends 'Gdraw2::AbstractTrack'; override calcNameCascade => sub { my $self = shift; my $line = shift; my $page = $self->getTrackPage; my $extent = $page->textCairoFont->extents; return $self->elementWidth / 2 + $extent->{descent} + $line * ( $extent->{descent} + $extent->{ascent} ); }; override draw => sub { my $self = shift; my $cr = $self->getTrackPage->cairoContext; # arrange every un-arranged element $self->arrangeAll; if ( $self->isCircular ) { my $angle_start = $self->graphicStart; my $angle_end = $self->graphicEnd; if ( $self->showGuideLine ) { my $r = $self->radius; $cr->save; $cr->new_path; $cr->set_source_rgba( 0, 0, 0, 0.5 ); $cr->set_line_width( $self->elementWidth / 5 ); $cr->arc( 0, 0, $r, $angle_start, $angle_end ); $cr->stroke; $cr->restore; } } else { # assume we have been translated to track start position # TODO: draw track name # draw guide line my $gstart = $self->graphicStart; my $gend = $self->graphicEnd; if ( $self->showGuideLine ) { $cr->save; $cr->set_source_rgba( 0, 0, 0, 0.5 ); $cr->move_to( 0, 0 ); $cr->rectangle( $gstart, -$self->elementWidth / 10, $gend - $gstart, $self->elementWidth / 5 ); $cr->fill; $cr->restore; } } # draw elements my %layers = ( top => [], bottom => [], default => [] ); foreach my $ele ( $self->getChildren ) { push @{ $layers{ $ele->layer } }, $ele; } foreach my $layer (qw/bottom default top/) { foreach my $ele ( @{ $layers{$layer} } ) { $ele->draw; # draw linear names here if ( !$self->isCircular ) { $ele->drawName; $ele->drawNameLeadLine; } } } }; 1; =head1 SEE ALSO Gdraw2::AbstractTrack =cutGdraw2-v0.0.3/lib/Gdraw2/CairoTrackPage.pm000444001750001750 1302712001671021 20226 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::CairoTrackPage - a page of genomics drawings that impelemented using Cairo =head1 SYNOPSIS use Gdraw2::CairoTrackPage; # firstly create a Cairo context my $surface = Cairo::PdfSurface->create($file,$width,$height); my $context = Cairo::Context->create($surface); # create the page object using the Cairo context my $page = Gdraw2::CairoTrackPage->new( width => $width, height => $height, cairoContext => $context ); # # add groups, tracks # create elements # # render everything $page->draw; =head1 DESCRIPTION The concrete page class implemented using Cairo 2D drawing library. See Gdraw2::AbstractTrackPage for more information. =cut package Gdraw2::CairoTrackPage; use common::sense; use threads::shared; use Glib qw/TRUE FALSE/; use Cairo; use Moose; use Gdraw2::AbstractTrackPage; use Gdraw2::CairoTrackGroup; use Gdraw2::Util qw/polar_point/; =head1 EXTENDS Gdraw2::AbstractTrackPage =cut extends 'Gdraw2::AbstractTrackPage'; =head1 PUBLIC ATTRIBUTES =head2 cairoContext desc : the Cairo context. See Cairo's documents for more information. is : read/write isa : Cairo::Context default: must be given when construction. =cut has cairoContext => ( is => 'rw', isa => 'Cairo::Context', required => 1 ); =head2 titleCairoFont desc : the Cairo font object for titles. See Cairo's documents for more information. is : read only isa : Cairo::ScaledFont =cut has titleCairoFont => ( is => 'ro', isa => 'Cairo::ScaledFont', ); =head2 textCairoFont desc : the Cairo font object for text. See Cairo's documents for more information. is : read only isa : Cairo::ScaledFont =cut has textCairoFont => ( is => 'ro', isa => 'Cairo::ScaledFont' ); # the size of the surface should be changed as width or height changes my $rebuild_surface = sub { my $self = shift; say "old surface type:".$self->cairoContext->get_target->get_type; my $surface_new = $self->cairoContext->get_target->create_similar('color-alpha',$self->width,$self->height); say "new surface type:".$surface_new->get_type; my $cr_new = Cairo::Context->create($surface_new); $self->cairoContext($cr_new); }; override onTitleFontChange => sub { my $self = shift; $self->cairoContext->select_font_face( $self->titleFont, 'normal', 'normal' ); $self->cairoContext->set_font_size( $self->titleSize ); $self->{titleCairoFont} = $self->cairoContext->get_scaled_font; }; override onTextFontChange => sub { my $self = shift; $self->cairoContext->select_font_face( $self->textFont, 'normal', 'normal' ); $self->cairoContext->set_font_size( $self->textSize ); $self->{textCairoFont} = $self->cairoContext->get_scaled_font; }; my $ele_anchor_y = sub { my $ele = shift; return sin( $ele->anchorGraphicPosition ) * $ele->anchorRadius; }; my $arrange_one_side = sub { my $self = shift; my @ele_list = @_; my $cf = $self->textCairoFont; my $cf_ext = $cf->extents; my $height = $cf_ext->{descent} + $cf_ext->{ascent}; my $max_radius = $self->maxRadius; my $max_upper; my $max_lower; my $upper_i; my $lower_i; if ( @ele_list % 2 == 0 ) { $upper_i = @ele_list / 2 - 1; $lower_i = $upper_i + 1; } else { $upper_i = ( @ele_list - 1 ) / 2; $lower_i = $upper_i; } # arrange upper half for ( my $i = $upper_i ; $i >= 0 ; $i-- ) { my $curr = $ele_list[$i]; say "upper element: ",$curr->displayName; my $curr_y = &$ele_anchor_y($curr); if ( !defined $max_upper ) { $max_upper = $curr_y; } else { if ( $curr_y > $max_upper - $height ) { $max_upper -= $height; } else { $max_upper = $curr_y; } } $curr->circularNameCascade($max_upper); } # arrange lower half for ( my $i = $lower_i ; $i < @ele_list ; $i++ ) { my $curr = $ele_list[$i]; say "lower element: ",$curr->displayName; my $curr_y = &$ele_anchor_y($curr); if ( !defined $max_lower ) { $max_lower = $curr_y; } else { if ( $curr_y < $max_lower + $height ) { $max_lower += $height; } else { $max_lower = $curr_y; } } $curr->circularNameCascade($max_lower); } }; override arrangeCircularElementName => sub { my $self = shift; my $last_grp = $self->getChildAt(-1); my $last_track = $last_grp->getChildAt(-1); my @all_ele = $self->getAllElements; # sort from top to bottom @all_ele = sort { &$ele_anchor_y($a) <=> &$ele_anchor_y($b) } @all_ele; # divide into right and left side my @right_ele; my @left_ele; foreach my $ele (@all_ele) { if ( cos( $ele->anchorGraphicPosition ) > 0 ) { push @right_ele, $ele } else { push @left_ele, $ele } } $self->$arrange_one_side(@right_ele) if @right_ele > 0; $self->$arrange_one_side(@left_ele) if @left_ele > 0; }; override draw => sub { my $self = shift; my $cr = $self->cairoContext; $cr->new_path; $cr->rectangle(0,0,$self->width,$self->height); $cr->set_source_rgba(1,1,1,1); $cr->fill; $self->arrangeAll; if ( $self->isCircular ) { $cr->save; $cr->translate( $self->width / 2, $self->height / 2 ); foreach my $group ( $self->getChildren ) { $group->draw; } # draw all elements' name foreach my $ele ( $self->getAllElements ) { $ele->drawName; $ele->drawNameLeadLine; } $cr->restore; } else { # render all groups my $group_count = 0; foreach my $group ( $self->getChildren ) { $cr->save; $cr->translate( $group->leftMargin, $group->groupCascade ); $group->draw; $cr->restore; } continue { $group_count++ } } }; 1; =head1 SEE ALSO Gdraw2::AbstractTrackPage =cutGdraw2-v0.0.3/lib/Gdraw2/AbstractTrackGroup.pm000444001750001750 2331512001671021 21155 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::AbstractTrackGroup - the base class for a group of tracks that own the same zoom setting. =head1 SYNOPSIS # This is only a abstract base class, you # won't use it for a drawing directly. # Instead, you should use implementations. # See Gdraw2::CairoTrackGroup for detail. # However, if you want to use drawing backends other than Cairo, # you can create your own page class by extending this class, # and provide implementation to some methods. package My::Group; use Moose; use Gdraw2::AbstractTrackGroup; extends 'Gdraw2::AbstractTrackGroup'; override draw => sub { }; =head1 DESCRIPTION A group of tracks that own the same zooming. All tracks contained by this group are aligned by "leftMargin" and "rightMargin" by the group's "start" and "end". =cut package Gdraw2::AbstractTrackGroup; use threads::shared; use Moose; use Gdraw2::Util::SharedObject; use Gdraw2::Util::RoleAbstractChild; use Gdraw2::Util::RoleAbstractParent; use Gdraw2::Util qw/load_module/; use Math::Trig qw/pi pi2 pi4 pip2 pip4/; =head1 EXTENDS Gdraw2::Util::SharedObject =head1 WITH Gdraw2::Util::RoleAbstractChild Gdraw2::Util::RoleAbstractParent Gdraw2::Util::RoleArrangeable Gdraw2::Util::RoleRecordable =cut extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleAbstractChild'; with 'Gdraw2::Util::RoleAbstractParent'; with 'Gdraw2::Util::RoleArrangeable'; with 'Gdraw2::Util::RoleRecordable'; =head1 PUBLIC ATTRIBUTES =head2 displayName desc : name of this group. Won't be rendered on output, but would be showed in the Gdraw2.pl program. is : read/write isa : Str default: "" =cut has displayName => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => '' ); =head2 desc desc : useless at current. is : read/write isa : Str default: "" =cut has desc => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => '' ); =head2 trackDistance desc : distance between tracks in this group. is : read/write isa : Num default: 10 =cut has trackDistance => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 10 ); =head2 start desc : the sequence position that being aligned to "leftMargin". is : read/write isa : Num default: 1 =cut has start => ( is => 'rw', metaclass => 'Recordable', isa => 'Int', default => 1 ); =head2 end desc : the sequence position that being aligned to "rightMargin". is : read/write isa : Num default: 1000 =cut has end => ( is => 'rw', metaclass => 'Recordable', isa => 'Int', default => 1000 ); =head2 leftMargin desc : group start will be aligned to this position. Only affects linear drawing. is : read/write isa : Num default: 50 =cut has leftMargin => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 50, ); =head2 rightMargin desc : group end will be aligned to this position. Only affects linear drawing. is : read/write isa : Num default: 30 =cut has rightMargin => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 30, ); =head2 circStartIndent desc : group start will be aligned to this position. Only affects circular drawing. is : read/write isa : Num default: 0 =cut has circStartIndent => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 0 ); =head2 circEndIndent desc : group end will be aligned to this position. Only affects circular drawing. is : read/write isa : Num default: 0 =cut has circEndIndent => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 0 ); =head1 PRIVATE ATTRIBUTES =head2 groupCascade =cut has groupCascade => ( is => 'rw', isa => 'Num' ); =head2 cascadeLine =cut has cascadeLine => ( is => 'rw', isa => 'Int', default => 0 ); =head2 arranged =cut has arranged => ( is => 'rw', isa => 'Bool', default => 0 ); =head1 PUBLIC METHODS =head2 draw usage : $group->draw(); desc : render current group. Subclasses that actually perform the drawing should override this method. args : none. return: none. =cut sub draw { confess "need to be overriden" } =head2 length usage : my $length = $group->length(); desc : length from start to end. args : none. return: group length. =cut sub length { my $self = shift; my $start = $self->start; my $end = $self->end; # as nucleotide sequence don't have position 0, we should consider that if ( $start * $end > 0 ) { return $end - $start + 1; } else { return $end - $start; } } =head2 trackDisplayWidth usage : my $width = $group->trackDisplayWidth(); desc : graphical size from left margin to right margin. args : none. return: graphical size. =cut sub trackDisplayWidth { my $self = shift; return $self->parent->width - $self->leftMargin - $self->rightMargin; } =head2 isCircular usage : if ($group->isCircular) { # do something } desc : if the page being attached on is circular. args : none. return: 1 if is circular, 0 if not. =cut sub isCircular { my $self = shift; return $self->parent->isCircular; } sub bitGraphicLength { my $self = shift; if ( $self->isCircular ) { return ( pi2- $self->circStartIndent - $self->circEndIndent ) / $self->length; } else { return $self->trackDisplayWidth / $self->length; } } sub groupRadius { my $self = shift; return $self->parent->initRadius + $self->groupCascade; } sub maxContentCascade { my $self = shift; if ($self->numChildren>0) { my $last_track = ( $self->getChildren )[-1]; return $last_track->trackCascade + $last_track->maxContentCascade + $last_track->elementWidth / 2; } else { return 0; } } sub calcGraphicPosition { my ( $self, $pos ) = @_; my $start = $self->start; if ( $self->isCircular ) { if ( $start * $pos > 0 ) { return ( $pos - $start + 1 ) * ( pi2 - $self->circStartIndent - $self->circEndIndent ) / $self->length + $self->circStartIndent - pip2; } else { return ( $pos - $start ) * ( pi2 - $self->circStartIndent - $self->circEndIndent ) / $self->length + $self->circStartIndent - pip2; } } else { if ( $start * $pos > 0 ) { return ( $pos - $start + 1 ) * $self->trackDisplayWidth / $self->length; } else { return ( $pos - $start ) * $self->trackDisplayWidth / $self->length; } } } sub overlaps { my $self = shift; my $group = shift; if ( $self->isCircular ) { return 1 if !( $self->circStartIndent > pi2- $group->circEndIndent or pi2- $self->circEndIndent < $group->circStartIndent ); } else { my $width = $self->parent->width; return 1 if !( $self->leftMargin > $width - $group->rightMargin or $width - $self->rightMargin < $group->leftMargin ); } return 0; } sub arrangeAll { my $self = shift; my $page = $self->parent; my $i = 0; my $textSize = $self->parent->textSize; foreach my $track ( $self->getChildren ) { $track->arrangeAll; if ( $page->isCircular ) { if ( $i == 0 ) { $track->trackCascade( $track->elementWidth / 2 ); } else { my $prev = $self->{children}[ $i - 1 ]; $track->trackCascade( $prev->trackCascade + $prev->calcCascade( $prev->numCascadeLines - 1 ) + $prev->elementWidth / 2 + $self->trackDistance + $track->elementWidth / 2 ); } } else { if ( $i == 0 ) { $track->trackCascade( $track->calcNameCascade( $track->numCascadeNameLines ) ); } else { my $prev = $self->{children}[ $i - 1 ]; $track->trackCascade( $prev->trackCascade + $prev->calcCascade( $prev->numCascadeLines ) - $prev->elementWidth / 2 + $self->trackDistance + $track->calcNameCascade( $track->numCascadeNameLines ) ); } } } continue { $i++ } } sub unarrangeAll { my $self = shift; foreach my $track ($self->getChildren) { $track->unarrangeAll; } } around addChildAt => sub { my ( $orig, $self, $child, $i ) = @_; $self->$orig( $child, $i ); $child->parent($self); }; around removeChildAt => sub { my ( $orig, $self, $i ) = @_; my $removed = $self->$orig($i); if ( defined $removed ) { #$removed->parent(undef); } return $removed; }; around applyParams => sub { my $orig = shift; my $self = shift; my $page = $self->parent; if (defined $page) { $page->unarrangeOneGroup($self); } $self->$orig(@_); }; around loadHash => sub { my $orig = shift; my $self = shift; my $store = shift; confess "store don't has children" if !exists $store->{children}; my @children = @{ $store->{children} }; delete $store->{children}; my $obj = $self->$orig( $store, @_ ); foreach my $child (@children) { confess "track store don't has class" if !exists $child->{CLASS}; my $track_class = $child->{CLASS}; load_module($track_class); my $track = $track_class->loadHash($child); $obj->addChild($track); } # restore children $store->{children} = [@children]; return $obj; }; around toHash => sub { my $orig = shift; my $self = shift; my $hash = $self->$orig(@_); $hash->{children} = shared_clone []; foreach my $track ( @{ $self->{children} } ) { push @{ $hash->{children} }, $track->toHash; } return $hash; }; 1; =head1 RECORDABLE ATTRIBUTES These attributes will be serialized while calling "toHash". See "Gdraw2::Util::RoleRecordable" for details. trackDistance end circEndIndent circStartIndent desc rightMargin leftMargin displayName start =head1 SEE ALSO Gdraw2::AbstractTrackPage Gdraw2::CairoTrackGroup Gdraw2::Util::RoleAbstractParent Gdraw2::Util::RoleAbstractChild Gdraw2::Util::RoleRecordable =cutGdraw2-v0.0.3/lib/Gdraw2/Version.pm000444001750001750 6512001671021 16752 0ustar00yangxiyangxi000000000000package Gdrwa2::Version; our $VERSION = '0.0.3'; 1;Gdraw2-v0.0.3/lib/Gdraw2/AbstractTrackPage.pm000444001750001750 2457012001671021 20741 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::AbstractTrackPage - the base class for a page of genomics drawings =head1 SYNOPSIS # This is only a abstract base class, you # won't use it for a drawing directly. # Instead, you should use implementations. # See Gdraw2::CairoTrackPage for detail. # However, if you want to use drawing backends other than Cairo, # you can create your own page class by extending this class, # and provide implementation to some methods. package My::Page; use Moose; use Gdraw2::AbstractTrackPage; extends 'Gdraw2::AbstractTrackPage'; override draw => sub { }; override onTitleFontChange => sub { }; override onTextFontChange => sub { }; override arrangeCircularElementName => sub { }; =head1 DESCRIPTION Represents global parameters for a genomics drawing, such as page size, font, etc. =cut package Gdraw2::AbstractTrackPage; use common::sense; use threads::shared; use Carp qw/cluck confess/; use Moose; use Gdraw2::Util::SharedObject; use Gdraw2::Util::GroupArranger; use Gdraw2::Util qw/load_module/; use List::Util qw/max/; =head1 EXTENDS Gdraw2::Util::SharedObject =head1 WITH Gdraw2::Util::RoleAbstractParent Gdraw2::Util::RoleRecordable =cut extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleAbstractParent'; with 'Gdraw2::Util::RoleRecordable'; =head1 PUBLIC ATTRIBUTES =head2 groupDistance desc : distance between TrackGroups. is : read/write isa : Num default: 10 =cut has groupDistance => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 10 ); =head2 topMargin desc : distance to the top edge of the page. is : read/write isa : Num default: 50 =cut has topMargin => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 50 ); =head2 width desc : page width. is : read/write isa : Num default: 600 =cut has width => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 600, trigger => sub { my $self = shift; $self->onPageWidthChange(@_) if $_[0] != $_[1]; } ); =head2 height desc : page height. is : read/write isa : Num default: 842 =cut has height => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 842, trigger => sub { my $self = shift; $self->onPageHeightChange(@_) if $_[0] != $_[1]; } ); =head2 isCircular desc : whether to draw the genome in circular. is : read/write isa : Bool default: 0 (for false) =cut has isCircular => ( is => 'rw', metaclass => 'Recordable', isa => 'Bool', default => 0 ); =head2 initRadius desc : when drawing in circular, the radius of innermost track. is : read/write isa : Num default: 80 =cut has initRadius => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 80 ); =head2 titleSize desc : font size for titles. is : read/write isa : Num default: 20arrangeCircularElementName =cut has titleSize => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 20, lazy => 1, trigger => sub { $_[0]->onTitleFontChange } ); =head2 titleFont desc : font family for titles. is : read/write isa : Str default: Courier for windows, otherwise Courier_new. =cut has titleFont => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => $^O eq 'MSWin32' ? 'Courier' : 'Courier_new', lazy => 1, trigger => sub { $_[0]->onTitleFontChange } ); =head2 textSize desc : font size for texts, such as feature labels. is : read/write isa : Num default: 12 =cut has textSize => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 12, lazy => 1, trigger => sub { $_[0]->onTextFontChange } ); =head2 textFont desc : font family for texts, such as feature labels. is : read/write isa : Str default: Courier for windows, otherwise Courier_new. =cut has textFont => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => $^O eq 'MSWin32' ? 'Courier' : 'Courier_new', lazy => 1, trigger => sub { $_[0]->onTextFontChange } ); =head1 PRIVATE ATTRIBUTES =head2 groupArrangers =cut has groupArrangers => ( is => 'bare', isa => 'ArrayRef[Gdraw2::Util::GroupArranger]', default => sub { return shared_clone [ Gdraw2::Util::GroupArranger->new ] } ); around new => sub { my $orig = shift; my $class = shift; my $self = $class->$orig(@_); $self->onTitleFontChange; $self->onTextFontChange; return $self; }; around addChildAt => sub { my ( $orig, $self, $child, $i ) = @_; #say "page add group: $child"; $self->$orig( $child, $i ); $child->parent($self); $self->arrangeOneGroup($child); }; around removeChildAt => sub { my ( $orig, $self, $i ) = @_; my $removed = $self->$orig($i); if ( defined $removed ) { #$removed->parent(undef); if ( $removed->arranged ) { $self->unarrangeOneGroup($removed); } } return $removed; }; around loadHash => sub { my $orig = shift; my $self = shift; my $store = shift; confess "store don't has children" if !exists $store->{children}; my @children = @{ $store->{children} }; delete $store->{children}; my $obj = $self->$orig( $store, @_ ); foreach my $child (@children) { confess "group store don't has class" if !exists $child->{CLASS}; my $group_class = $child->{CLASS}; load_module($group_class); my $group = $group_class->loadHash($child); $obj->addChild($group); } return $obj; }; around toHash => sub { my $orig = shift; my $self = shift; my $hash = $self->$orig(@_); $hash->{children} = shared_clone []; foreach my $group ( @{ $self->{children} } ) { push @{ $hash->{children} }, $group->toHash; } return $hash; }; =head1 PUBLIC METHODS =head2 draw usage : $page->draw(); desc : draw every thing. Subclasses that actually perform the drawing should override this method. args : none. return: none. =cut sub draw { confess "need to be overriden" } =head2 getAllElements usage : my @elements = $page->getAllElements(); desc : recursively access all groups and tracks, and return all elements from all tracks. args : none. return: an array of elements. =cut sub getAllElements { my $self = shift; my @elements; foreach my $grp ( $self->getChildren ) { foreach my $trk ( $grp->getChildren ) { push @elements, $trk->getChildren; } } return @elements; } =head1 PRIVATE METHODS =cut sub onPageWidthChange { } sub onPageHeightChange { } sub onTitleFontChange { confess "This method needs to be overriden"; } sub onTextFontChange { confess "This method needs to be overriden"; } sub arrangeCircularElementName { confess "This method needs to be overrided"; } sub maxRadius { my $self = shift; my $last_grp = $self->getChildAt(-1); my $last_track = $last_grp->getChildAt(-1); return $self->initRadius + $last_grp->groupCascade + $last_track->trackCascade + $last_track->calcCascade( $last_track->numCascadeLines ); } sub arrangeOneGroup { my $self = shift; my $group = shift; my $num = $self->numCascadeLines; my $arrange_succ = 0; my $i = 0; foreach my $arranger ( @{ $self->{groupArrangers} } ) { if ( !$arranger->overlaps($group) ) { $arranger->addChild($group); $group->cascadeLine($i); $arrange_succ = 1; last; } } continue { $i++ } if ( !$arrange_succ ) { my $arranger = Gdraw2::Util::GroupArranger->new; push @{ $self->{groupArrangers} }, $arranger; $arranger->addChild($group); $group->cascadeLine($i); } $group->arranged(1); } sub unarrangeOneGroup { my $self = shift; my $group = shift; #cluck "unarrange group $group"; # remove from arranger my $line_amount = $self->numCascadeLines; for ( my $i = $group->cascadeLine ; $i < $line_amount ; $i++ ) { my $arranger = $self->{groupArrangers}[$i]; # remove from its arranger if ( $i == $group->cascadeLine ) { $arranger->removeChild($group); } # remove affected children else { my $child_num = $arranger->numChildren; for ( my $j = 0 ; $j < $child_num ; $j++ ) { my $curr = $arranger->getChildAt($j); if ( $curr->overlaps($group) ) { $arranger->removeChildAt($j); $curr->arranged(0); $curr->cascadeLine(0); } } } } $group->arranged(0); $group->cascadeLine(0); # remove potential lasting empty arrangers while (1) { if ( $self->{groupArrangers}[-1]->numChildren == 0 ) { if ( @{ $self->{groupArrangers} } > 1 ) { pop @{ $self->{groupArrangers} }; } } else { last; } last if @{ $self->{groupArrangers} } == 1; } } sub numCascadeLines { return scalar @{ $_[0]->{groupArrangers} }; } sub arrangeAll { my $self = shift; my @all_groups = $self->getChildren; # assign group cascade line # arrange tracks before group cascade being calculated foreach (@all_groups) { $_->arrangeAll; $self->arrangeOneGroup($_) if !$_->arranged; } # calculate group cascade my @arrangers = @{ $self->{groupArrangers} }; for ( my $i = 0 ; $i < @arrangers ; $i++ ) { my $arranger = $arrangers[$i]; # first line if ( $i == 0 ) { foreach my $group ( $arranger->getChildren ) { if ( $self->isCircular ) { $group->groupCascade(0); } else { $group->groupCascade( $self->topMargin ); } } } # not first line else { my $prev_arranger = $arrangers[ $i - 1 ]; my $prev_cascade = $prev_arranger->getChildAt(0)->groupCascade; my $prev_max_content_cascade = max( map { $_->maxContentCascade } $prev_arranger->getChildren ); foreach my $group ( $arranger->getChildren ) { $group->groupCascade( $prev_cascade + $prev_max_content_cascade + $self->groupDistance ); } } } if ( $self->isCircular ) { $self->arrangeCircularElementName; } } sub unarrangeAll { my $self = shift; foreach my $arranger ( @{ $self->{groupArrangers} } ) { $arranger->removeAllChildren; } $self->{groupArrangers} = [ Gdraw2::Util::GroupArranger->new ]; foreach my $group ($self->getChildren) { $group->arranged(0); $group->unarrangeAll; } } 1; =head1 RECORDABLE ATTRIBUTES These attributes will be serialized while calling "toHash". See "Gdraw2::Util::RoleRecordable" for details. width titleSize titleFont topMargin textSize height isCircular textFont groupDistance initRadius =head1 SEE ALSO Gdraw2::CairoTrackPage Gdraw2::Util::RoleAbstractParent Gdraw2::Util::RoleRecordable =cutGdraw2-v0.0.3/lib/Gdraw2/Util.pm000444001750001750 734512001671021 16312 0ustar00yangxiyangxi000000000000 =head1 NAME Gdraw2::Util - Miscellaneous utility functions =head1 SYNOPSIS use Gdraw2::Util qw/polar_point load_model/; =head1 DESCRIPTION Contains several utility functions. =cut package Gdraw2::Util; use common::sense; use Exporter; use Carp qw/cluck confess/; use File::Spec::Functions; use Math::Trig qw/pi pi2 pi4 pip2 pip4/; use POSIX qw/ceil floor/; our @ISA = qw/Exporter/; our @EXPORT_OK = qw/polar_point load_module calc_gc_content calc_gc_skew parse_color_str_8 parse_color_str_16 calc_tick_size/; =head1 FUNCTIONS =head2 load_module usage : load_module('Foo::Bar'); desc : load an module at run time, so you won't need to has the module being founded at the very beginning. args : an module name. return: nothing. =cut sub load_module { # this function is derived from Bio::Root::Root my $name = shift; my $module = "_<$name.pm"; return 1 if $main::{$module}; # untaint operation for safe web-based running (modified after a fix # a fix by Lincoln) HL if ( $name !~ /^([\w:]+)$/ ) { confess "$name is an illegal perl package name"; } else { $name = $1; } my $load = "$name.pm"; $load = catfile( split /::/, $load ); eval { require $load; }; if ($@) { confess "Failed to load module $name. " . $@; } return 1; } =head2 polar_point usage : my ($x,$y) = polar_point( $angle, $radius ); desc : calculate points of rectangular coordinates from polar coordinates. args : angle, radius return: x, y =cut sub polar_point { my ( $angle, $radius ) = @_; return ( $radius * cos $angle, $radius * sin $angle ); } =head2 calc_gc_content usage : my $frac_gc = calc_gc_content($seq); desc : calculate GC content from a nucleotide sequence. args : the sequence. return: fraction of GC content. =cut sub calc_gc_content { my $seq = shift; my $num_gc; my $len = length $seq; for ( my $i = 0 ; $i < $len ; $i++ ) { my $char = substr $seq, $i, 1; $num_gc++ if $char eq 'G' or $char eq 'C' or $char eq 'g' or $char eq 'c'; } return $num_gc / $len; } =head2 calc_gc_skew usage : my $frac_gc_skew = calc_gc_skew($seq); desc : calculate GC skew from a nucleotide sequence. args : the sequence. return: fraction of GC skew. =cut sub calc_gc_skew { my $seq = shift; my $num_g; my $num_c; my $len = length $seq; for ( my $i = 0 ; $i < $len ; $i++ ) { my $char = substr $seq, $i, 1; $num_g++ if $char eq 'G' or $char eq 'g'; $num_c++ if $char eq 'C' or $char eq 'c'; } return ( $num_g - $num_c ) / ( $num_g + $num_c ); } =head2 parse_color_str_8 usage : my ($r, $g, $b) = parse_color_str_8('#rrggbb'); desc : parse an GdkColor string, each channel in 8 bit hex. args : the string representation. return: red, green, blue color value, each from 0 to 255. =cut sub parse_color_str_8 { my $str = shift; my @result = map { hex($_) } substr( $str, 1, 2 ), substr( $str, 3, 2 ), substr( $str, 5, 2 ); return @result; } =head2 parse_color_str_16 usage : my ($r, $g, $b) = parse_color_str_16('#rrrrggggbbbb'); desc : parse an GdkColor string, each channel in 16 bit hex. args : the string representation. return: red, green, blue color value, each from 0 to 65535. =cut sub parse_color_str_16 { my $str = shift; my @result = map { hex($_) } substr( $str, 1, 4 ), substr( $str, 5, 4 ), substr( $str, 9, 4 ); return @result; } sub calc_tick_size { my $length = shift; my $scale = floor( log($length) / log(10) ); my $tick_size = 10**$scale; my $num_step = $length/$tick_size; $tick_size *= 2 if $num_step > 15; return $tick_size; } 1; Gdraw2-v0.0.3/lib/Gdraw2/Meta000755001750001750 012001671021 15557 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2/Meta/Attribute000755001750001750 012001671021 17522 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2/Meta/Attribute/Recordable.pm000444001750001750 13612001671021 22237 0ustar00yangxiyangxi000000000000package Gdraw2::Meta::Attribute::Recordable; use Moose; extends 'Moose::Meta::Attribute'; 1; Gdraw2-v0.0.3/lib/Gdraw2/Meta/Attribute/RecordableParam.pm000444001750001750 23112001671021 23214 0ustar00yangxiyangxi000000000000package Gdraw2::Meta::Attribute::RecordableParam; use Moose; use Gdraw2::Meta::Attribute::Recordable; extends 'Gdraw2::Meta::Attribute::Recordable'; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element000755001750001750 012001671021 16262 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractDataCurve.pm000555001750001750 142112001671021 22320 0ustar00yangxiyangxi000000000000package Gdraw2::Element::AbstractDataCurve; use common::sense; use threads::shared; use Moose; use Gdraw2::Util::RGBAColor; extends 'Gdraw2::Element::AbstractElement'; has fillColor2 => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::Util::RGBColor', default => sub { return Gdraw2::Util::RGBAColor->new( 1, 0, 1, 1 ) } ); has data => ( is => 'rw', metaclass=> 'Recordable', isa => 'ArrayRef[Num]', default => sub { return shared_clone [] } ); has middleLine => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 0 ); sub singleDataGraphicLength { my $self = shift; return ( $self->graphicEnd - $self->graphicStart ) / @{ $self->data }; } sub setMiddleLineToMedian { } sub setMiddleLineToMean { } 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/CairoRuler.pm000555001750001750 607012001671021 21032 0ustar00yangxiyangxi000000000000package Gdraw2::Element::CairoRuler; use Moose; use common::sense; use Math::Trig qw/pi pi2 pi4 pip2 pip4/; use Gdraw2::Util qw/polar_point/; extends 'Gdraw2::Element::AbstractRuler'; with 'Gdraw2::Element::RoleCairoElement'; with 'Gdraw2::Element::RoleCairoDefaultNameLead'; override draw => sub { my $self = shift; my $tick = $self->tickSize; my $group = $self->getTrackGroup; my $page = $group->parent; my $cr = $page->cairoContext; my $cr_font = $page->textCairoFont; my @list_pos = sort { $a <=> $b } $self->tickPositionList; my @list_g_pos = map { $group->calcGraphicPosition( $_ - 0.5 ) } @list_pos; my @list_tick_text; if ( $self->abbrevTickText ) { @list_tick_text = map { $self->abbrev($_) } @list_pos; } else { @list_tick_text = @list_pos; } $cr->save; # set stroke color my $stroke = $self->strokeColor; if ( $stroke->isa('Gdraw2::Util::RGBAColor') ) { $cr->set_source_rgba( $stroke->red, $stroke->green, $stroke->blue, $stroke->alpha ); } else { $cr->set_source_rgb( $stroke->red, $stroke->green, $stroke->blue ); } # set stroke line width $cr->set_line_width( $self->lineWidth ); $cr->set_line_join('round'); # make the drawing if ( $page->isCircular ) { my $r = $self->radius; # ruler main line $cr->save; $cr->arc( 0, 0, $r, $list_g_pos[0], $list_g_pos[-1] ); $cr->stroke; $cr->restore; # ticks for ( my $i = 0 ; $i < @list_pos ; $i++ ) { my $gpos = $list_g_pos[$i]; # tick line $cr->save; $cr->move_to( polar_point( $list_g_pos[$i], $r ) ); $cr->line_to( polar_point( $list_g_pos[$i], $r + $tick ) ); $cr->stroke; $cr->restore; # tick text my $ext = $cr_font->text_extents( $list_tick_text[$i] ); $cr->save; my ( $pt_x, $pt_y ) = polar_point( $gpos, $r + $tick ); # lower half if ( sin($gpos) > 0 ) { if ( cos($gpos) > 0 ) { $cr->move_to( $pt_x, $pt_y + $ext->{height} ); } else { $cr->move_to( $pt_x - $ext->{width}, $pt_y + $ext->{height} ); } } # upper half else { if ( cos($gpos) > 0 ) { $cr->move_to( $pt_x, $pt_y ); } else { $cr->move_to( $pt_x - $ext->{width}, $pt_y ); } } $cr->show_text( $list_tick_text[$i] ); $cr->restore; } } else { my $cascade = $self->cascade; # ruler main line $cr->save; $cr->move_to( $list_g_pos[0], $cascade ); $cr->line_to( $list_g_pos[-1], $cascade ); $cr->stroke; $cr->restore; # ticks for ( my $i = 0 ; $i < @list_pos ; $i++ ) { # tick line $cr->save; $cr->move_to( $list_g_pos[$i], $cascade ); $cr->line_to( $list_g_pos[$i], $cascade - $tick ); $cr->stroke; $cr->restore; # tick text my $extent = $cr_font->text_extents( $list_tick_text[$i] ); my $x = $list_g_pos[$i] - $extent->{x_bearing} - $extent->{width} / 2; my $y = $cascade - $tick * 2; $cr->save; $cr->move_to( $x, $y ); $cr->show_text( $list_tick_text[$i] ); $cr->restore; } } $cr->restore; }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/CairoDataCurve.pm000555001750001750 731412001671021 21621 0ustar00yangxiyangxi000000000000package Gdraw2::Element::CairoDataCurve; use Moose; use Gdraw2::Util qw/polar_point/; use List::Util qw/max min/; extends 'Gdraw2::Element::AbstractDataCurve'; with 'Gdraw2::Element::RoleCairoElement'; with 'Gdraw2::Element::RoleCairoDefaultNameLead'; #override drawNameLeadLine => sub { }; override draw => sub { my $self = shift; my $gstart = $self->graphicStart; my $gend = $self->graphicEnd; my @data = @{ $self->data }; my $data_l = $self->singleDataGraphicLength; my $track = $self->parent; my $group = $track->parent; my $cr = $self->getTrackPage->cairoContext; my $w = $track->elementWidth; my $min = min @data,$self->middleLine; my $max = max @data,$self->middleLine; my $mid_height = ( $self->middleLine - $min ) / ( $max - $min ) * $w; if ( $self->isCircular ) { my $r = $self->radius; my $circ_shape = sub { $cr->new_path; $cr->move_to( polar_point( $gstart, $r - $w / 2 + $mid_height ) ); my $theta = $gstart; for ( my $i = 0 ; $i < @data ; $i++ ) { my $curr_height = ( $data[$i] - $min ) / ( $max - $min ) * $w; $cr->arc(0,0,$r-$w/2+$curr_height,$theta,$theta+$data_l); $theta += $data_l; } $cr->line_to( polar_point( $gend, $r - $w / 2 + $mid_height ) ); $cr->arc_negative( 0, 0, $r - $w / 2 + $mid_height, $gend, $gstart ); $cr->close_path; }; # clip inner half $cr->save; { $cr->new_path; $cr->arc( 0, 0, $r - $w / 2, $gstart, $gend ); $cr->arc_negative( 0, 0, $r-$w/2+$mid_height, $gend, $gstart ); $cr->close_path; $cr->clip; &$circ_shape; $self->setContextColor( $cr, $self->fillColor ); $cr->fill; } $cr->restore; # clip outer half $cr->save; { $cr->new_path; $cr->arc( 0, 0, $r-$w/2+$mid_height, $gstart, $gend ); $cr->arc_negative( 0, 0, $r + $w / 2, $gend, $gstart ); $cr->close_path; $cr->clip; &$circ_shape; $self->setContextColor( $cr, $self->fillColor2 ); $cr->fill; } $cr->restore; } else { my $linear_shape = sub { my $x = $gstart; $cr->move_to( $gstart, $w / 2 - $mid_height ); foreach my $value (@data) { my $curr_h = ( $value - $min ) / ( $max - $min ) * $w; $cr->line_to( $x, $w / 2 - $curr_h ); $x += $data_l; $cr->line_to( $x, $w / 2 - $curr_h ); } $cr->line_to( $gend, $w / 2 - $mid_height ); $cr->close_path; }; # clip upper half $cr->save; { $cr->move_to( $gstart, $w / 2 - $mid_height ); $cr->line_to( $gstart, -$w / 2 ); $cr->line_to( $gend, -$w / 2 ); $cr->line_to( $gend, $w / 2 - $mid_height ); $cr->close_path; $cr->clip; &$linear_shape(); $self->setContextColor( $cr, $self->fillColor ); $cr->fill; } $cr->restore; # clip lower half $cr->save(); { $cr->move_to( $gstart, $w / 2 - $mid_height ); $cr->line_to( $gstart, $w / 2 ); $cr->line_to( $gend, $w / 2 ); $cr->line_to( $gend, $w / 2 - $mid_height ); $cr->close_path; $cr->clip; &$linear_shape(); $self->setContextColor( $cr, $self->fillColor2 ); $cr->fill; } $cr->restore; } }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/CairoMapping.pm000555001750001750 1135512001671021 21356 0ustar00yangxiyangxi000000000000package Gdraw2::Element::CairoMapping; use threads::shared; use common::sense; use Moose; extends 'Gdraw2::Element::AbstractMapping'; with 'Gdraw2::Element::RoleCairoElement'; with 'Gdraw2::Element::RoleCairoDefaultNameLead'; use Gdraw2::Util qw/polar_point/; override draw => sub { my $self = shift; my $cr = $self->getTrackPage->cairoContext; my $track = $self->parent; my $group = $track->parent; my $page = $group->parent; my $ext_group = $page->getChildAt( $self->extGroupIndex ); my $ext_track = $ext_group->getChildAt( $self->extTrackIndex ); my $halfw = $track->elementWidth / 2; my $ext_halfw = $ext_track->elementWidth / 2; if ( $page->isCircular ) { my $r = $track->radius; my $ext_r = $ext_track->radius; my $gstart = $self->graphicStart; my $gend = $self->graphicEnd; my $ext_gstart = $ext_group->calcGraphicPosition( $self->extStart ) - $ext_group->bitGraphicLength; my $ext_gend = $ext_group->calcGraphicPosition( $self->extEnd ); my ( $r1, $r2 ); # outer radius my ( $r3, $r4 ); # inner radius my ( $g1, $g2 ); # outer graphical position my ( $g3, $g4 ); # inner graphical position #-- determine actual drawing points --# # current track at outside if ( $r > $ext_r ) { $r1 = $r + $halfw; $r2 = $r - $halfw; $r3 = $ext_r + $ext_halfw; $r4 = $ext_r - $ext_halfw; $g1 = $gstart; $g2 = $gend; $g3 = $ext_gstart; $g4 = $ext_gend; } # current track at inside else { $r1 = $ext_r + $ext_halfw; $r2 = $ext_r - $ext_halfw; $r3 = $r + $halfw; $r4 = $r - $halfw; $g1 = $ext_gstart; $g2 = $ext_gend; $g3 = $gstart; $g4 = $gend; } #-- fill --# $cr->save; $cr->move_to( polar_point( $g1, $r2 ) ); $cr->arc( 0, 0, $r1, $g1, $g2 ); $cr->line_to( polar_point( $g2, $r2 ) ); $cr->line_to( polar_point( $g4, $r3 ) ); $cr->arc_negative( 0, 0, $r4, $g4, $g3 ); $cr->line_to( polar_point( $g3, $r3 ) ); $cr->close_path; my $fill = $self->fillColor; if ( $fill->isa('Gdraw2::Util::RGBAColor') ) { $cr->set_source_rgba( $fill->flat ); } else { $cr->set_source_rgb( $fill->flat ); } $cr->fill; $cr->restore; #-- stroke --# $cr->save; $cr->move_to( polar_point( $g3, $r4 ) ); $cr->line_to( polar_point( $g3, $r3 ) ); $cr->line_to( polar_point( $g1, $r2 ) ); $cr->line_to( polar_point( $g1, $r1 ) ); $cr->move_to( polar_point( $g4, $r4 ) ); $cr->line_to( polar_point( $g4, $r3 ) ); $cr->line_to( polar_point( $g2, $r2 ) ); $cr->line_to( polar_point( $g2, $r1 ) ); $cr->set_line_width( $self->lineWidth ); my $stroke = $self->strokeColor; if ( $stroke->isa('Gdraw2::Util::RGBAColor') ) { $cr->set_source_rgba( $stroke->flat ); } else { $cr->set_source_rgb( $stroke->flat ); } $cr->stroke; $cr->restore; } else { # first of all, we need to get the location of external track my $ext_left = $ext_group->leftMargin - $group->leftMargin; my $ext_top = ( $ext_group->groupCascade + $ext_track->trackCascade ) - ( $group->groupCascade + $track->trackCascade ); my $ext_g_start = $ext_left + $ext_group->calcGraphicPosition( $self->extStart ) - $ext_group->bitGraphicLength; my $ext_g_end = $ext_left + $ext_group->calcGraphicPosition( $self->extEnd ); # determine actual drawing points my ( $x1, $x2, $x3, $x4, $y1, $y2, $y3, $y4 ); if ( $ext_top < 0 ) { $x1 = $ext_g_start; $x2 = $ext_g_end; $x3 = $self->graphicStart; $x4 = $self->graphicEnd; $y1 = $ext_top - $ext_halfw; $y2 = $ext_top + $ext_halfw; $y3 = -$halfw; $y4 = $halfw; } else { $x1 = $self->graphicStart; $x2 = $self->graphicEnd; $x3 = $ext_g_start; $x4 = $ext_g_end; $y1 = -$halfw; $y2 = $halfw; $y3 = $ext_top - $ext_halfw; $y4 = $ext_top + $ext_halfw; } #-- fill --# $cr->save; $cr->move_to( $x1, $y2 ); $cr->line_to( $x1, $y1 ); $cr->line_to( $x2, $y1 ); $cr->line_to( $x2, $y2 ); $cr->line_to( $x4, $y3 ); $cr->line_to( $x4, $y4 ); $cr->line_to( $x3, $y4 ); $cr->line_to( $x3, $y3 ); $cr->close_path; my $fill = $self->fillColor; if ( $fill->isa('Gdraw2::Util::RGBAColor') ) { $cr->set_source_rgba( $fill->flat ); } else { $cr->set_source_rgb( $fill->flat ); } $cr->fill; $cr->restore; #-- stroke --# $cr->save; $cr->move_to( $x1, $y1 ); $cr->line_to( $x1, $y2 ); $cr->line_to( $x3, $y3 ); $cr->line_to( $x3, $y4 ); $cr->move_to( $x2, $y1 ); $cr->line_to( $x2, $y2 ); $cr->line_to( $x4, $y3 ); $cr->line_to( $x4, $y4 ); $cr->set_line_width( $self->lineWidth ); my $stroke = $self->strokeColor; if ( $stroke->isa('Gdraw2::Util::RGBAColor') ) { $cr->set_source_rgba( $stroke->flat ); } else { $cr->set_source_rgb( $stroke->flat ); } $cr->stroke; $cr->restore; } }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractPair.pm000555001750001750 63512001671021 21323 0ustar00yangxiyangxi000000000000package Gdraw2::Element::AbstractPair; use common::sense; use threads::shared; use Gdraw2::Element::AbstractElement; use Moose; extends 'Gdraw2::Element::AbstractElement'; has '+elementAnchor' => (default => 'center'); has '+layer' => ( default => 'top' ); override anchorCascade => sub { my $self = shift; my $track = $self->parent; return $track->maxContentCascade + $track->elementWidth / 2; }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/RoleCairoDefaultNameLead.pm000444001750001750 404612001671021 23534 0ustar00yangxiyangxi000000000000package Gdraw2::Element::RoleCairoDefaultNameLead; use common::sense; use threads::shared; use Moose::Role; use Carp qw/cluck/; use Gdraw2::Util qw/polar_point/; around drawNameLeadLine => sub { my $orig = shift; my $self = shift; my $track = $self->parent; my $page = $self->getTrackPage; my $cr = $page->cairoContext; my $track_gstart = $track->graphicStart; my $track_gend = $track->graphicEnd; if ( $self->isCircular ) { if ( $self->showName and length( $self->displayName ) > 0 ) { #say "draw name lead for ",$self->displayName; my $angle = $self->anchorGraphicPosition; my $angle_cos = cos $angle; my $text_cr_f = $page->textCairoFont; my $ext = $text_cr_f->text_extents( $self->displayName ); my ( $anchor_x, $anchor_y ) = polar_point($angle,$self->anchorRadius); my $max_radius = $page->maxRadius; my $vertex_x = $max_radius; $vertex_x *= -1 if $angle_cos <= 0; my $name_x = $angle_cos > 0 ? $vertex_x + $page->groupDistance : $vertex_x - $page->groupDistance; my $name_y = $self->circularNameCascade; $cr->save; $cr->set_line_width( 0.6 * $self->lineWidth ); $self->setContextColor( $cr, $self->strokeColor ); #say "\t$anchor_x, $anchor_y"; #say "\t$vertex_x, $name_y"; #say "\t$name_x, $name_y"; $cr->move_to( $anchor_x, $anchor_y ); $cr->line_to( $vertex_x, $name_y ); $cr->line_to( $name_x, $name_y ); $cr->stroke; $cr->restore; } } else { if ( $self->showName and length( $self->displayName ) > 0 ) { my $y = $self->nameCascade; my $anchor = $self->anchorGraphicPosition; goto DRAW_END if $anchor<$track_gstart or $anchor>$track_gend; my $cascade = 0; if ( $self->meta->does_role('Gdraw2::Element::RoleArrangeable') ) { $cascade = $self->cascade; } $cr->save; $cr->set_line_width( 0.6 * $self->lineWidth ); $self->setContextColor( $cr, $self->strokeColor ); $cr->move_to( $anchor, $cascade ); $cr->line_to( $anchor, -$y ); $cr->stroke; $cr->restore; DRAW_END: } } }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractTagset.pm000555001750001750 63612001671021 21660 0ustar00yangxiyangxi000000000000package Gdraw2::Element::AbstractTagset; use common::sense; use threads::shared; use Gdraw2::Element::AbstractElement; use Moose; extends 'Gdraw2::Element::AbstractElement'; has '+elementAnchor' => (default => 'center'); has '+layer' => ( default => 'top' ); override anchorCascade => sub { my $self = shift; my $track = $self->parent; return $track->maxContentCascade + $track->elementWidth / 2; }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/CairoBlock.pm000444001750001750 1717712001671021 21022 0ustar00yangxiyangxi000000000000package Gdraw2::Element::CairoBlock; use common::sense; use Moose; extends 'Gdraw2::Element::AbstractBlock'; with 'Gdraw2::Element::RoleCairoElement'; with 'Gdraw2::Element::RoleCairoDefaultNameLead'; use Gdraw2::Util qw/polar_point/; override draw => sub { my $self = shift; my $track = $self->parent; my $group = $self->getTrackGroup; my $track_start = $track->start; my $track_end = $track->end; my $track_gstart = $track->graphicStart; my $track_gend = $track->graphicEnd; # skip if whole block is outside track return if $self->start > $track_end or $self->end < $track_start; my $cr = $self->getTrackPage->cairoContext; $cr->new_path; my $w = $self->parent->elementWidth; my $arrow_len = $w / 4; my $cascade = $self->cascade; my $numPosition = @{ $self->{position} }; my $is_circ = $self->isCircular; if ( $self->isCircular ) { my $r = $self->radius; $cr->save; $cr->set_line_width( $self->lineWidth ); $cr->set_line_join('round'); # traverse through segments for ( my $i = 0 ; $i <= $numPosition - 2 ; $i += 2 ) { my $seg_start = $self->{position}[$i]; my $seg_end = $self->{position}[ $i + 1 ]; # skip if segment location is outside track next if $seg_start > $track_end or $seg_end < $track_start; # create path for current segment my $gstart = $group->calcGraphicPosition($seg_start) - $group->bitGraphicLength; my $gend = $group->calcGraphicPosition($seg_end); # short directed blocks if ( $self->strand != 0 and $gend - $gstart < $arrow_len / $r ) { if ( $i == 0 and $self->strand == -1 ) { $cr->move_to( polar_point( $gstart, $r ) ); $cr->line_to( polar_point( $gend, $r + $w / 2 ) ); $cr->line_to( polar_point( $gend, $r - $w / 2 ) ); } elsif ( $i == $numPosition - 2 and $self->strand == 1 ) { $cr->move_to( polar_point( $gstart, $r - $w / 2 ) ); $cr->line_to( polar_point( $gstart, $r + $w / 2 ) ); $cr->line_to( polar_point( $gend, $r ) ); } } # long blocks else { #--- draw left path ---# my $angle_start; # truncated left path if ( $seg_start < $track_start ) { $angle_start = $track_gstart; $cr->move_to( polar_point( $track_gstart, $r - $w / 2 ) ); for ( 0.1, 0.3, 0.5, 0.7, 0.9 ) { $cr->line_to( polar_point( $track_gstart - $w / 10 / $r, $r + ( $_ - 0.5 ) * $w ) ); $cr->line_to( polar_point( $track_gstart, $r + ( $_ - 0.4 ) * $w ) ); } } # directed left path elsif ( $i == 0 and $self->strand == -1 ) { $angle_start = $gstart + $arrow_len / $r; $cr->move_to( polar_point( $gstart, $r ) ); } # normal left path else { $angle_start = $gstart; } #--- draw right side path ---# my $angle_end; # truncated right path if ( $seg_end > $track_end ) { $angle_end = $track_gend; $cr->arc( 0, 0, $r + $w / 2, $angle_start, $angle_end ); for ( 0.1, 0.3, 0.5, 0.7, 0.9 ) { $cr->line_to( polar_point( $angle_end + $w / 10 / $r, $r + ( 0.5 - $_ ) * $w ) ); $cr->line_to( polar_point( $angle_end, $r + ( 0.4 - $_ ) * $w ) ); } } # directed right path elsif ( $i == $numPosition - 2 and $self->strand == 1 ) { $angle_end = $gend - $arrow_len / $r; $cr->arc( 0, 0,, $r + $w / 2, $angle_start, $angle_end ); $cr->line_to( polar_point( $gend, $r ) ); } # normal right path else { $angle_end = $gend; $cr->arc( 0, 0,, $r + $w / 2, $angle_start, $angle_end ); } #--- arc back ---# $cr->arc_negative( 0, 0, $r - $w / 2, $angle_end, $angle_start ); } $cr->close_path; # stroke and fill current segment $self->fillColor->applyToCairoContext($cr); $cr->fill_preserve; $self->strokeColor->applyToCairoContext($cr); $cr->stroke; # draw the linking line between multiple segments if ( $i != 0 ) { my $prev_gend = $group->calcGraphicPosition( $self->{position}[ $i - 1 ] ); my $mid = ( $prev_gend + $gstart ) / 2; # at lower half if ( sin($mid) > 0 ) { $cr->move_to( polar_point( $prev_gend, $r - $w / 6 ) ); $cr->line_to( polar_point( $mid, $r - $w / 2 ) ); $cr->line_to( polar_point( $gstart, $r - $w / 6 ) ); } # at upper half else { $cr->move_to( polar_point( $prev_gend, $r + $w / 6 ) ); $cr->line_to( polar_point( $mid, $r + $w / 2 ) ); $cr->line_to( polar_point( $gstart, $r + $w / 6 ) ); } $self->strokeColor->applyToCairoContext($cr); $cr->stroke; } } $cr->restore; } else { $cr->save; $cr->set_line_width( $self->lineWidth ); $cr->set_line_join('round'); # traverse through segments for ( my $i = 0 ; $i <= $numPosition - 2 ; $i += 2 ) { my $seg_start = $self->{position}[$i]; my $seg_end = $self->{position}[ $i + 1 ]; # skip if segment location is outside track next if $seg_start > $track_end or $seg_end < $track_start; my $gstart = $group->calcGraphicPosition($seg_start) - $group->bitGraphicLength; my $gend = $group->calcGraphicPosition($seg_end); # very short directed segment if ( $self->strand != 0 and $gend - $gstart < $arrow_len ) { if ( $self->strand == 1 ) { $cr->move_to( $gstart, $cascade - $w / 2 ); $cr->line_to( $gstart, $cascade + $w / 2 ); $cr->line_to( $gend, $cascade ); } elsif ( $self->strand == -1 ) { $cr->move_to( $gstart, $cascade ); $cr->line_to( $gend, $cascade + $w / 2 ); $cr->line_to( $gend, $cascade - $w / 2 ); } } # long segment else { #--- draw left path ---# #--- from up to down # truncated left path if ( $seg_start < $track_start ) { $cr->move_to( $track_gstart, $cascade - $w / 2 ); for ( 0.1, 0.3, 0.5, 0.7, 0.9 ) { $cr->line_to( $track_gstart - $w / 10, $cascade + ( $_ - 0.5 ) * $w ); $cr->line_to( $track_gstart, $cascade + ( $_ - 0.4 ) * $w ); } } # directed left path elsif ( $i == 0 and $self->strand == -1 ) { $cr->move_to( $gstart + $arrow_len, $cascade - $w / 2 ); $cr->line_to( $gstart, $cascade ); $cr->line_to( $gstart + $arrow_len, $cascade + $w / 2 ); } # normal left path else { $cr->move_to($gstart,$cascade-$w/2); $cr->line_to($gstart,$cascade+$w/2); } #--- draw right side path ---# #--- from down to up # truncated right path if ( $seg_end > $track_end ) { $cr->line_to($track_gend,$cascade+$w/2); for ( 0.1, 0.3, 0.5, 0.7, 0.9 ) { $cr->line_to( $track_gend + $w / 10, $cascade + ( 0.5-$_ ) * $w ); $cr->line_to( $track_gend, $cascade + ( 0.4-$_ ) * $w ); } } # directed right path elsif ( $i == $numPosition - 2 and $self->strand == 1 ) { $cr->line_to($gend-$arrow_len,$cascade+$w/2); $cr->line_to($gend,$cascade); $cr->line_to($gend-$arrow_len,$cascade-$w/2); } # normal right path else { $cr->line_to($gend,$cascade+$w/2); $cr->line_to($gend,$cascade-$w/2); } } $cr->close_path; # stroke and fill $self->setContextColor($cr,$self->fillColor); $cr->fill_preserve; $self->setContextColor($cr,$self->strokeColor); $cr->stroke; # draw the linking line between multiple segments if ( $i != 0 ) { my $prev_gend = $group->calcGraphicPosition( $self->{position}[ $i - 1 ] ); $cr->move_to( $prev_gend, $cascade - $w / 6 ); $cr->line_to( ( $gstart + $prev_gend ) / 2, $cascade - $w / 2 ); $cr->line_to( $gstart, $cascade - $w / 6 ); $self->setContextColor($cr,$self->strokeColor); $cr->stroke; } } $cr->restore; } }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/RoleCairoElement.pm000444001750001750 624612001671021 22156 0ustar00yangxiyangxi000000000000package Gdraw2::Element::RoleCairoElement; use common::sense; use threads::shared; use Moose::Role; use Carp qw/cluck/; use Gdraw2::Util qw/polar_point/; use Gdraw2::Element::AbstractElement; around drawName => sub { my $orig = shift; my $self = shift; my $track = $self->parent; my $page = $self->getTrackPage; my $cr = $page->cairoContext; my $text_cr_f = $page->textCairoFont; my $track_gstart = $track->graphicStart; my $track_gend = $track->graphicEnd; # test if we are arranged confess "Element <" . $self->displayName . "> not arranged before drawing" if !$self->arrangeOK; if ( $self->isCircular ) { if ( $self->showName and length( $self->displayName ) > 0 ) { my $angle = $self->anchorGraphicPosition; my $angle_cos = cos $angle; my $ext = $text_cr_f->text_extents( $self->displayName ); my $max_radius = $page->maxRadius; my $name_x = $angle_cos > 0 ? $max_radius + $page->groupDistance : -$max_radius - $page->groupDistance; my $name_y = $self->circularNameCascade; $cr->save; $cr->set_scaled_font($text_cr_f); if ( $angle_cos > 0 ) { $cr->move_to( $name_x, $name_y + $ext->{height} / 2 ); } else { $cr->move_to( $name_x - $ext->{width}, $name_y + $ext->{height} / 2 ); } $self->textColor->applyToCairoContext($cr); $cr->show_text( $self->displayName ); $cr->restore; } } else { # assume we have been translated to track start position: # (left_margin, track_dev) # draw name if ( $self->showName and length( $self->displayName ) > 0 ) { my ($nameStart,$nameEnd) = $self->nameGraphicPosition; goto NAME_END if $nameEnd<$track_gstart or $track_gend<$nameStart; my $y = $self->nameCascade; my $anchor = $self->anchorGraphicPosition; my $cascade = 0; if ( $self->meta->does_role('Gdraw2::Element::RoleArrangeable') ) { $cascade = $self->cascade; } $cr->save; $cr->set_scaled_font($text_cr_f); $cr->move_to( $nameStart, -$y ); $self->textColor->applyToCairoContext($cr); $cr->show_text( $self->displayName ); $cr->restore; NAME_END: } } }; around nameGraphicLength => sub { my $orig = shift; my $self = shift; my $extents = $self->getTrackPage->textCairoFont->text_extents( $self->displayName ); return $extents->{width}; }; around nameGraphicPosition => sub { my $orig = shift; my $self = shift; my $name_width = $self->nameGraphicLength; if ( $self->isCircular ) { confess "circular graphics should not use this method"; } my $ele_anchor_gpos = $self->anchorGraphicPosition; my $start; my $end; given ( $self->nameAnchor ) { when ('left') { $start = $ele_anchor_gpos; $end = $ele_anchor_gpos + $name_width; } when ('center') { $start = $ele_anchor_gpos - $name_width / 2; $end = $ele_anchor_gpos + $name_width / 2; } when ('right') { $start = $ele_anchor_gpos - $name_width; $end = $ele_anchor_gpos; } } return ( $start, $end ); }; sub setContextColor { my $self = shift; my $cr = shift; my $color = shift; if ( $color->isa('Gdraw2::Util::RGBAColor') ) { $cr->set_source_rgba( $color->flat ); } else { $cr->set_source_rgb( $color->flat ); } } 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/CairoPair.pm000555001750001750 514712001671021 20640 0ustar00yangxiyangxi000000000000package Gdraw2::Element::CairoPair; use Moose; use common::sense; extends 'Gdraw2::Element::AbstractPair'; with 'Gdraw2::Element::RoleCairoElement'; use Gdraw2::Util qw/polar_point/; override draw => sub { my $self = shift; my $track = $self->parent; my $group = $track->parent; my $cr = $self->getTrackPage->cairoContext; my $bitSize = $group->bitGraphicLength; my @stroke_rgb = ( $self->strokeColor->red, $self->strokeColor->green, $self->strokeColor->blue ); $cr->save; $cr->set_line_width( $self->lineWidth ); $cr->set_line_join('round'); $cr->set_source_rgb(@stroke_rgb); if ( $self->isCircular ) { my $r0 = $self->radius - $track->elementWidth / 2; my $r1 = $track->radius + $track->calcCascade( $track->numCascadeLines - 1 ) + $track->elementWidth / 2; foreach my $curr ( @{ $self->position } ) { my $angle; if ( $curr > 0 ) { $angle = $group->calcGraphicPosition($curr) - $bitSize / 2; } else { $angle = $group->calcGraphicPosition($curr) + $bitSize / 2; } $cr->move_to( polar_point( $angle, $r0 ) ); $cr->line_to( polar_point( $angle, $r1 ) ); } } else { confess "linear not implemented"; } $cr->stroke; $cr->restore; }; override drawNameLeadLine => sub { my $self = shift; my $track = $self->parent; my $group = $track->parent; my $page = $group->parent; my $cr = $page->cairoContext; my $bitSize = $group->bitGraphicLength; if ( $self->isCircular ) { if ( $self->showName and length( $self->displayName ) > 0 ) { my $r_anchor = $self->anchorRadius; my $angle = $self->anchorGraphicPosition; my $angle_cos = cos $angle; my $text_cr_f = $page->textCairoFont; my $ext = $text_cr_f->text_extents( $self->displayName ); my $max_radius = $page->maxRadius; my $vertex_x = $max_radius; $vertex_x *= -1 if $angle_cos <= 0; my $name_x = $angle_cos > 0 ? $vertex_x + $page->groupDistance : $vertex_x - $page->groupDistance; my $name_y = $self->circularNameCascade; $cr->save; for my $pos ( @{ $self->position } ) { my $gpos; if ( $pos > 0 ) { $gpos = $group->calcGraphicPosition($pos) - $bitSize / 2; } else { $gpos = $group->calcGraphicPosition($pos) + $bitSize / 2; } $cr->move_to( polar_point( $gpos, $r_anchor ) ); $cr->line_to( $vertex_x, $name_y ); } $cr->move_to( $vertex_x, $name_y ); $cr->line_to( $name_x, $name_y ); $cr->set_line_width( 0.6 * $self->lineWidth ); $cr->stroke; $cr->restore; } } else { if ( $self->showName and length( $self->displayName ) > 0 ) { confess "needs to be implemented"; } } }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/RoleArrangeable.pm000555001750001750 106112001671021 22003 0ustar00yangxiyangxi000000000000package Gdraw2::Element::RoleArrangeable; use common::sense; use Moose::Role; has cascadeLine => ( is => 'rw', isa => 'Int', default => 0 ); has arranged => ( is => 'rw', isa => 'Bool', default => 0 ); sub cascade { my $self = shift; return $self->parent->calcCascade( $self->cascadeLine ); } sub overlaps { my ( $self, $ele ) = @_; # if ( $self->isCircular ) { # die "circular graphic not implemented"; # } # else { if ( $self->start > $ele->end or $ele->start > $self->end ) { return 0; } else { return 1 } # } } 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractRuler.pm000444001750001750 307512001671021 21537 0ustar00yangxiyangxi000000000000package Gdraw2::Element::AbstractRuler; use threads::shared; use common::sense; use Moose; use Gdraw2::Element::AbstractElement; use POSIX qw/floor/; extends 'Gdraw2::Element::AbstractElement'; with 'Gdraw2::Element::RoleArrangeable'; has '+showName' => ( default => 0 ); has tickSize => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 2 ); has gridLength => ( is => 'rw', metaclass => 'Recordable', isa => 'Int', default => 1000 ); has integralTick => ( is => 'rw', metaclass => 'Recordable', isa => 'Bool', default => 1 ); has abbrevTickText => ( is => 'rw', metaclass => 'Recordable', isa => 'Bool', default => 1 ); sub tickPositionList { my $self = shift; my @result; my $start = $self->start; my $end = $self->end; my $step = $self->gridLength; push @result, $start; my $cyc_start; if ( $self->integralTick ) { $cyc_start = ( floor( $start / $step ) + 1 ) * $step; } else { $cyc_start = $start + $step; } for ( my $i = $cyc_start ; $i < $end ; $i += $step ) { if ( $i == 0 ) { push @result, 1; } else { push @result, $i; } } push @result, $end; return @result; } sub abbrev { my $self = shift; my $num = shift; my $str; if ( $num >= 1e9 and $num % 1e9 == 0 ) { $str = int( $num / 1e9 ) . 'G'; return $str; } elsif ( $num >= 1e6 and $num % 1e6 == 0 ) { $str = int( $num / 1e6 ) . 'M'; return $str; } elsif ( $num >= 1000 and $num % 1000 == 0 ) { $str = int( $num / 1e3 ) . 'K'; return $str; } else { return $num; } } 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractElement.pm000444001750001750 1201612001671021 22052 0ustar00yangxiyangxi000000000000 package Gdraw2::Element::AbstractElement; use threads::shared; use feature qw/say switch/; use Moose; use Moose::Util::TypeConstraints; use Carp qw/cluck/; use Gdraw2::Util::RGBAColor; use Gdraw2::Util::SharedObject; use List::Util qw/max min/; extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleAbstractChild'; with 'Gdraw2::Util::RoleArrangeable'; with 'Gdraw2::Util::RoleRecordable'; sub BUILD { my $self = shift; @{ $self->{position} } = sort { $a <=> $b } @{ $self->{position} }; } has displayName => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => '', ); has showName => ( is => 'rw', metaclass => 'Recordable', isa => 'Bool', default => 1 ); enum( 'Gdraw2::HorizontalAnchorEnum', qw/left center right/ ); has nameAnchor => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::HorizontalAnchorEnum', default => 'left', ); has elementAnchor => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::HorizontalAnchorEnum', default => 'left', ); enum( 'Gdraw2::SimpleLayerEnum', qw/top default bottom/ ); has layer => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::SimpleLayerEnum', default => 'default' ); has desc => ( is => 'rw', metaclass => 'Recordable', isa => 'Str', default => '' ); has position => ( is => 'rw', metaclass => 'Recordable', isa => 'ArrayRef[Int]', default => sub { shared_clone [1,100] }, trigger => sub { my ( $self, $list ) = @_; @$list = sort { $a <=> $b } @$list; } ); has strand => ( is => 'rw', metaclass => 'Recordable', isa => 'Int', default => 0 ); has fillColor => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::Util::RGBColor', default => sub { return Gdraw2::Util::RGBAColor->new( 0, 0.5, 0.5, 1 ) } ); has strokeColor => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::Util::RGBColor', default => sub { return Gdraw2::Util::RGBAColor->new( 0, 0, 0, 1 ) } ); has textColor => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::Util::RGBColor', default => sub { return Gdraw2::Util::RGBAColor->new( 0, 0, 0, 1 ) } ); has lineWidth => ( is => 'rw', metaclass => 'Recordable', isa => 'Num', default => 0.5 ); has cascadeNameLine => ( is => 'rw', isa => 'Int', default => 0 ); has circularNameCascade => ( is => 'rw', isa => 'Num', default => 0 ); has nameArranged => ( is => 'rw', isa => 'Bool', default => 0 ); around applyParams => sub { my $orig = shift; my $self = shift; my $track = $self->parent; if (defined $track) { $track->unarrangeOneChild($self); $track->unarrangeOneChildName($self); } $self->$orig(@_); }; sub nameGraphicLength { confess "need to be overriden" } sub nameGraphicPosition { confess "need to be overriden" } sub draw { confess "need to be overriden" } sub drawName { confess "need to be overriden" } sub drawNameLeadLine { confess "need to be overriden" } sub start { my $self = shift; return $self->{position}[0]; } sub end { my $self = shift; return $self->{position}[-1]; } sub positionString { my $self = shift; return join ', ',@{$self->{position}}; } sub graphicStart { my $self = shift; my $group = $self->getTrackGroup; return $group->calcGraphicPosition( $self->start ) - $group->bitGraphicLength; } sub graphicEnd { my $self = shift; return $self->getTrackGroup->calcGraphicPosition( $self->end ); } sub anchorGraphicPosition { my $self = shift; given ( $self->elementAnchor ) { when ('left') { return $self->graphicStart; } when ('center') { return ( $self->graphicStart + $self->graphicEnd ) / 2; } when ('right') { return $self->graphicEnd; } } } sub nameCascade { my $self = shift; return $self->parent->calcNameCascade( $self->cascadeNameLine ); } sub nameOverlaps { my ( $self, $ele ) = @_; my ( $start, $end ) = $self->nameGraphicPosition; my ( $ele_start, $ele_end ) = $ele->nameGraphicPosition; if ( $self->isCircular ) { die "circular graphic not implemented"; } else { if ( $start > $ele_end or $ele_start > $end ) { return 0; } else { return 1 } } } sub getTrackGroup { return $_[0]->parent->parent; } sub radius { my $self = shift; my $track = $self->parent; if ( $self->meta->does_role('Gdraw2::Element::RoleArrangeable') ) { return $track->radius + $track->calcCascade( $self->cascadeLine ); } else { return $track->radius; } } sub anchorCascade { my $self = shift; return $self->parent->elementWidth/2; } sub anchorRadius { my $self = shift; return $self->radius + $self->anchorCascade; } sub getTrackPage { return $_[0]->parent->parent->parent; } sub isCircular { return $_[0]->getTrackPage->isCircular; } sub arrangeOK { my $self = shift; if ( $self->meta->does_role('Gdraw2::Element::RoleArrangeable') ) { return $self->arranged and $self->nameArranged; } else { return $self->nameArranged; } } 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractBlock.pm000555001750001750 72612001671021 21463 0ustar00yangxiyangxi000000000000package Gdraw2::Element::AbstractBlock; use common::sense; use threads::shared; use Gdraw2::Element::AbstractElement; use Gdraw2::Element::RoleArrangeable; use Moose; extends 'Gdraw2::Element::AbstractElement'; with 'Gdraw2::Element::RoleArrangeable'; override 'positionString' => sub { my $self = shift; my @tmp; for (my $i=0; $i<@{$self->{position}}-1; $i+=2) { push @tmp,$self->{position}[$i].'..'.$self->{position}[$i+1]; } return join ', ',@tmp; }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/CairoTagset.pm000555001750001750 544012001671021 21170 0ustar00yangxiyangxi000000000000package Gdraw2::Element::CairoTagset; use Moose; use common::sense; extends 'Gdraw2::Element::AbstractTagset'; with 'Gdraw2::Element::RoleCairoElement'; use Gdraw2::Util qw/polar_point/; override draw => sub { my $self = shift; my $track = $self->parent; my $group = $track->parent; my $cr = $self->getTrackPage->cairoContext; my $bitSize = $group->bitGraphicLength; $cr->save; $cr->set_line_width( $self->lineWidth ); $cr->set_line_join('round'); $self->setContextColor($cr,$self->strokeColor); if ( $self->isCircular ) { my $r0 = $self->radius - $track->elementWidth / 2; my $r1 = $track->radius + $track->calcCascade( $track->numCascadeLines - 1 ) + $track->elementWidth / 2; foreach my $curr ( @{ $self->position } ) { my $angle; if ( $curr > 0 ) { $angle = $group->calcGraphicPosition($curr) - $bitSize / 2; } else { $angle = $group->calcGraphicPosition($curr) + $bitSize / 2; } $cr->move_to( polar_point( $angle, $r0 ) ); $cr->line_to( polar_point( $angle, $r1 ) ); } } else { my $y0 = -$track->elementWidth/2; my $y1 = $track->calcCascade( $track->numCascadeLines - 1 ) + $track->elementWidth/2; foreach my $curr (@{$self->position}) { my $g_pos = $group->calcGraphicPosition($curr) - $bitSize/2; $cr->move_to($g_pos,$y0); $cr->line_to($g_pos,$y1); } } $cr->stroke; $cr->restore; }; override drawNameLeadLine => sub { my $self = shift; my $track = $self->parent; my $group = $track->parent; my $page = $group->parent; my $cr = $page->cairoContext; my $bitSize = $group->bitGraphicLength; if ( $self->isCircular ) { if ( $self->showName and length( $self->displayName ) > 0 ) { my $r_anchor = $self->anchorRadius; my $angle = $self->anchorGraphicPosition; my $angle_cos = cos $angle; my $text_cr_f = $page->textCairoFont; my $ext = $text_cr_f->text_extents( $self->displayName ); my $max_radius = $page->maxRadius; my $vertex_x = $max_radius; $vertex_x *= -1 if $angle_cos <= 0; my $name_x = $angle_cos > 0 ? $vertex_x + $page->groupDistance : $vertex_x - $page->groupDistance; my $name_y = $self->circularNameCascade; $cr->save; for my $pos ( @{ $self->position } ) { my $gpos; if ( $pos > 0 ) { $gpos = $group->calcGraphicPosition($pos) - $bitSize / 2; } else { $gpos = $group->calcGraphicPosition($pos) + $bitSize / 2; } $cr->move_to( polar_point( $gpos, $r_anchor ) ); $cr->line_to( $vertex_x, $name_y ); } $cr->move_to( $vertex_x, $name_y ); $cr->line_to( $name_x, $name_y ); $cr->set_line_width( 0.6 * $self->lineWidth ); $cr->stroke; $cr->restore; } } else { if ( $self->showName and length( $self->displayName ) > 0 ) { confess "needs to be implemented"; } } }; 1; Gdraw2-v0.0.3/lib/Gdraw2/Element/AbstractMapping.pm000555001750001750 154712001671021 22046 0ustar00yangxiyangxi000000000000package Gdraw2::Element::AbstractMapping; use threads::shared; use common::sense; use Moose; use Gdraw2::Element::AbstractElement; extends 'Gdraw2::Element::AbstractElement'; has extStart => ( is => 'rw', isa => 'Int', metaclass => 'Recordable', default => 1 ); has extEnd => ( is => 'rw', isa => 'Int', metaclass => 'Recordable', default => 1 ); has extGroupIndex => ( is => 'rw', isa => 'Int', metaclass => 'Recordable', default => 0 ); has extTrackIndex => ( is => 'rw', isa => 'Int', metaclass => 'Recordable', default => 0 ); sub extGroup { my $self = shift; my $page = $self->getTrackPage; return $page->getChildAt( $self->extGroupIndex ); } sub extTrack { my $self = shift; my $ext_group = $self->extGroup; return $ext_group->getChildAt( $self->extTrackIndex ); } 1; Gdraw2-v0.0.3/lib/Gdraw2/Util000755001750001750 012001671021 15606 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2/Util/RoleRecordable.pm000444001750001750 710412001671021 21167 0ustar00yangxiyangxi000000000000package Moose::Meta::Attribute::Custom::Recordable; use Gdraw2::Meta::Attribute::Recordable; sub register_implementation { 'Gdraw2::Meta::Attribute::Recordable' } package Gdraw2::Util::RoleRecordable; use common::sense; use mro 'c3'; use threads::shared; use Moose::Role; use Gdraw2::Util qw/load_module/; use Scalar::Util qw/blessed/; use YAML::Syck; sub loadHash { my $self = shift; my $store = shift; my %extra = @_; # get class confess "No class information on store" if !exists $store->{CLASS}; my $class = $store->{CLASS}; # prepare attributes my %attr_ready; foreach my $key ( keys %$store ) { next if $key eq 'CLASS'; my $value = $store->{$key}; if ( my $value_type = ref $value ) { if ( $value_type eq 'HASH' and exists $value->{CLASS} ) { my $value_class = $value->{CLASS}; load_module($value_class); $attr_ready{$key} = $value_class->loadHash($value); } else { $attr_ready{$key} = Load Dump $store->{$key}; } } else { $attr_ready{$key} = $store->{$key}; } } $attr_ready{$_} = $extra{$_} foreach keys %extra; # create object my $obj = $class->new(%attr_ready); return $obj; } sub toHash { my $self = shift; my $store = shared_clone {}; $store->{CLASS} = blessed $self; my $meta = $self->meta; my $class = blessed $self; my @linear_isa = @{ mro::get_linear_isa( $class, 'c3' ) }; my @super_meta = map { $_->meta } @linear_isa; foreach my $curr_meta ( $meta, @super_meta ) { foreach my $attr_name ( $curr_meta->get_attribute_list ) { my $attr = $curr_meta->get_attribute($attr_name); if ( !$attr->isa('Gdraw2::Meta::Attribute::Recordable') ) { next; } my $value = $self->{$attr_name}; if ( ref $value ) { if ( blessed $value and $value->meta->does_role('Gdraw2::Util::RoleRecordable') ) { $store->{$attr_name} = $self->{$attr_name}->toHash; } else { $store->{$attr_name} = Load Dump $self->{$attr_name}; } } else { $store->{$attr_name} = $self->{$attr_name}; } } } return $store; } sub getParams { my $hash = toHash(@_); return $hash; } sub applyParams { my ( $self, $params ) = @_; my $meta = $self->meta; my $class = blessed $self; my @linear_isa = @{ mro::get_linear_isa( $class, 'c3' ) }; my @super_meta = map { $_->meta } @linear_isa; foreach my $curr_meta ( $meta, @super_meta ) { foreach my $attr_name ( $curr_meta->get_attribute_list ) { next if !exists $params->{$attr_name}; my $attr = $curr_meta->get_attribute($attr_name); next if !$attr->isa('Gdraw2::Meta::Attribute::Recordable'); my $value = $self->{$attr_name}; if ( ref $value ) { if ( blessed $value and $value->meta->does_role('Gdraw2::Util::RoleRecordable') ) { $self->{$attr_name}->applyParams( $params->{$attr_name} ); } else { $self->{$attr_name} = Load Dump $params->{$attr_name}; } } else { $self->{$attr_name} = $params->{$attr_name}; } } } } 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/RoleAbstractChild.pm000555001750001750 32312001671021 21613 0ustar00yangxiyangxi000000000000package Gdraw2::Util::RoleAbstractChild; use threads::shared; use Moose::Role; use Carp qw/cluck/; has parent => ( is => 'rw', does => 'Gdraw2::Util::RoleAbstractParent', weak_ref => 1 ); 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/GroupArranger.pm000444001750001750 51212001671021 21035 0ustar00yangxiyangxi000000000000package Gdraw2::Util::GroupArranger; use common::sense; use feature qw/say/; use Moose; extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleAbstractParent'; sub overlaps { my $self = shift; my $group = shift; foreach my $child ( $self->getChildren ) { return 1 if $child->overlaps($group); } return 0; } 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/RGBAColor.pm000444001750001750 430012001671021 20010 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::Util::RGBAColor =head1 SYNOPSIS # pure blue, with no transparency my $color1 = Gdraw2::Util::RGBAColor->new( 0, 0, 1, 1 ); # dark red, with half transparency my $color2 = Gdraw2::Util::RGBColor->new( 0.5, 0, 0, 0.5 ); # get the values in list my ($red,$green,$blue,$alpha) = $color1->flat; =head1 DESCRIPTION Represents a 4-channel color, each from 0 to 1, corresponding with the Cairo API. =cut package Gdraw2::Util::RGBAColor; use threads::shared; use Moose; use Gdraw2::Util::RGBColor; =head1 EXTENDS Gdraw2::Util::RGBColor =head1 WITH Gdraw2::Util::RoleRecordable =cut extends 'Gdraw2::Util::RGBColor'; with 'Gdraw2::Util::RoleRecordable'; =head1 PUBLIC ATTRIBUTES =head2 alpha desc : transparency value, 0 means fully transparent, 1 means opaque. is : read/write isa : number between [ 0, 1 ] default: 0 =cut has alpha => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::RGBColorValue', default => 0 ); =head1 SPECIFIC CONSTRUCTORS =head2 new( $red, $green, $blue, $alpha ) Gets four color value directly from arguments, so you don't need to write ( red=>$red, green=>$green, blue=>$blue, alpha=>$alpha ) =cut around BUILDARGS => sub { my ( $orig, $class, $red, $green, $blue, $alpha ) = @_; my $self = $class->$orig( $red, $green, $blue ); $self->{alpha} = $alpha; return $self; }; around loadHash => sub { my $orig = shift; my $class = shift; my $hash = shift; return Gdraw2::Util::RGBAColor->new( $hash->{red}, $hash->{green}, $hash->{blue}, $hash->{alpha} ); }; override applyToCairoContext => sub { my ($self,$cr) = @_; $cr->set_source_rgba($self->red,$self->green,$self->blue,$self->alpha); }; override flat => sub { my $self = shift; my @result = super(); push @result, $self->alpha; return @result; }; override flat_uint16 => sub { my $self = shift; my @result = super(); push @result, int( 65535 * $self->alpha ); return @result; }; 1; =head1 RECORDABLE ATTRIBUTES These attributes will be serialized while calling "toHash". See "Gdraw2::Util::RoleRecordable" for details. alpha =head1 SEE ALSO Cairo function set_source_rgba Gdraw2::Util::RGBColor Gdraw2::Util::RoleRecordable =cutGdraw2-v0.0.3/lib/Gdraw2/Util/SharedObject.pm000444001750001750 71712001671021 20623 0ustar00yangxiyangxi000000000000package Gdraw2::Util::SharedObject; use threads::shared; use Moose; use Scalar::Util qw/refaddr blessed/; around new => sub { my $orig = shift; my $class = shift; my $self = $class->$orig(@_); return bless( shared_clone($self), ref($self) ); }; sub addr { my $self = shift; return is_shared($self) || refaddr($self); } sub equals { my ( $self, $comp ) = @_; if ( !defined $comp ) { return 0 } else { return addr($self) eq addr($comp) } } 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/Arranger.pm000444001750001750 111512001671021 20040 0ustar00yangxiyangxi000000000000package Gdraw2::Util::Arranger; use feature qw/say/; use threads::shared; use Moose; use Gdraw2::Util::RoleAbstractParent; extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleAbstractParent'; sub overlaps { my $self = shift; my $child = shift; foreach my $curr ( $self->getChildren ) { if ( $curr->overlaps($child) ) { return 1; } } return 0; } sub nameOverlaps { my $self = shift; my $child = shift; foreach my $curr ( $self->getChildren ) { if ( $curr->nameOverlaps($child) ) { return 1; } } return 0; } 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/RoleArrangeable.pm000555001750001750 13212001671021 21305 0ustar00yangxiyangxi000000000000package Gdraw2::Util::RoleArrangeable; use threads::shared; use Moose::Role; 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/RoleAbstractParent.pm000444001750001750 565512001671021 22053 0ustar00yangxiyangxi000000000000package Gdraw2::Util::RoleAbstractParent; use threads::shared; use Moose::Role; use Gdraw2::Util::RoleAbstractChild; use Carp qw/cluck/; has children => ( is => 'bare', isa => 'ArrayRef', default => sub { return shared_clone [] } ); sub addChild { my $self = shift; my $child = shift; $self->addChildAt( $child, $self->numChildren ); } sub addChildAt { my $self = shift; my $child = shift; my $index = shift; confess "$child not a RoleAbstractChild" if !$child->meta->does_role('Gdraw2::Util::RoleAbstractChild'); if ( $self->hasChild($child) ) { cluck "attempt to add exist child: ", $child->addr; return; } # length check my $max = $self->numChildren; if ( $index > $max ) { cluck "index $index out of children num $max, append child to tail"; push @{ $self->{children} }, $child; } elsif ($index==$max) { push @{ $self->{children} }, $child; } else { # TODO: thread sharing support if ($threads::threads) { my $new = shared_clone []; my $i = 0; foreach my $curr ( @{ $self->{children} } ) { push @$new, $child if $i == $index; push @$new, $curr; } continue { $i++ } $self->{children} = $new; } else { splice @{ $self->{children} }, $index, 0, $child; } } } sub hasChild { my $self = shift; my $child = shift; foreach my $curr ( @{ $self->{children} } ) { return 1 if ( $curr->equals($child) ); } return 0; } sub childIndex { my $self = shift; my $child = shift; my $num = $self->numChildren; for ( my $i = 0 ; $i < $num ; $i++ ) { my $curr = $self->{children}[$i]; if ($curr->equals($child)) { return $i; } } return -1; } sub removeChild { my $self = shift; my $child = shift; my $max = $self->numChildren; for ( my $i = 0 ; $i < $max ; $i++ ) { if ( $child->equals( $self->{children}[$i] ) ) { return $self->removeChildAt($i); } } cluck "attempt to remove non-exist child: ", $child->addr; } sub removeChildAt { my $self = shift; my $index = shift; # length check my $max = $self->numChildren; if ( $index >= $max ) { cluck "index $index out of range: $max"; return; } # thread support: shared array cannot be spliced if ($threads::threads) { my $new = shared_clone []; my $deleted; for ( my $i = 0 ; $i < $max ; $i++ ) { if ( $i eq $index ) { $deleted = $self->{children}[$i]; } else { push @$new, $self->{children}[$i]; } } $self->{children} = $new; return $deleted; } else { return splice @{ $self->{children} }, $index, 1; } } sub removeAllChildren { my $self = shift; my @tmp = @{ $self->{children} }; $self->{children} = shared_clone []; return @tmp; } sub getChildAt { my $self = shift; my $index = shift; my $max = $self->numChildren; if ( $index >= $max ) { cluck "index $index out of range: $max"; return; } return $self->{children}[$index]; } sub getChildren { return @{ $_[0]->{children} }; } sub numChildren { return scalar @{ $_[0]->{children} }; } 1; Gdraw2-v0.0.3/lib/Gdraw2/Util/RGBColor.pm000444001750001750 1030512001671021 17731 0ustar00yangxiyangxi000000000000=head1 NAME Gdraw2::Util::RGBColor =head1 SYNOPSIS # pure blue my $color1 = Gdraw2::Util::RGBColor->new( 0, 0, 1 ); # dark cyan my $color2 = Gdraw2::Util::RGBColor->new( 0, 0.5, 0.5 ); # get the values in list my ($red,$green,$blue) = $color1->flat; =head1 DESCRIPTION Represents a 3-channel color, each from 0 to 1, corresponding with the Cairo API. =cut package Gdraw2::Util::RGBColor; use threads::shared; use Moose; use Moose::Util::TypeConstraints; use Gdraw2::Util::SharedObject; =head1 EXTENDS Gdraw2::Util::SharedObject =head1 WITH Gdraw2::Util::RoleRecordable =cut extends 'Gdraw2::Util::SharedObject'; with 'Gdraw2::Util::RoleRecordable'; subtype 'Gdraw2::RGBColorValue' => as 'Num' => where { $_ >= 0 and $_ <= 1 } => message { "RGB color value must between 0-1: $_" }; =head1 PUBLIC ATTRIBUTES =head2 red desc : red value is : read/write isa : number between [ 0, 1 ] default: 0 =cut has red => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::RGBColorValue', default => 0, ); =head2 green desc : green value is : read/write isa : number between [ 0, 1 ] default: 0 =cut has green => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::RGBColorValue', default => 0 ); =head2 blue desc : blue value is : read/write isa : number between [ 0, 1 ] default: 0 =cut has blue => ( is => 'rw', metaclass => 'Recordable', isa => 'Gdraw2::RGBColorValue', default => 0 ); =head1 SPECIFIC CONSTRUCTORS =head2 new( $red, $green, $blue ) Gets three color value directly from arguments, so you don't need to write ( red=>$red, green=>$green, blue=>$blue ) =cut around BUILDARGS => sub { my ( $orig, $class, $red, $green, $blue ) = @_; return $class->$orig( red => $red, green => $green, blue => $blue ); }; =head1 PUBLIC METHODS =head1 applyToCairoContext usage : $color->applyToCairoContext($cr); desc : apply color to a Cairo context. See Cairo. args : a Cairo context. return: none. =cut sub applyToCairoContext { my ($self,$cr) = @_; $cr->set_source_rgb($self->red,$self->green,$self->blue); } =head2 flat usage : my ($r,$g,$b) = $color->flat; desc : get the color values in a list. args : none. return: red, green, blue values. =cut sub flat { my $self = shift; return ( $self->red, $self->green, $self->blue ); } =head2 flat_uint8 usage : my ($r,$g,$b) = $color->flat_uint8; desc : get the color values in a list, each is an integer between [0,255]. args : none. return: red, green, blue values. =cut sub flat_uint8 { my $self = shift; return map { int (255 * $_) } ( $self->red, $self->green, $self->blue ); } =head2 flat_uint16 usage : my ($r,$g,$b) = $color->flat_uint16; desc : get the color values in a list, each is an integer between [0,65535]. args : none. return: red, green, blue values. =cut sub flat_uint16 { my $self = shift; return map { int (65535 * $_) } ( $self->red, $self->green, $self->blue ); } =head2 toGdkString8 usage : my $color_string = $color->toGdkString8; desc : get the color values in "#rrggbb" format which is compatiable with GdkColor. See flat_uint8. args : none. return: color string. =cut sub toGdkString8 { my $self = shift; my @int_color = $self->flat_uint8; my $re = sprintf("#%02x%02x%02x",@int_color[0,1,2]); return $re; } =head2 toGdkString8 usage : my $color_string = $color->toGdkString16; desc : get the color values in "#rrrrggggbbbb" format which is compatiable with GdkColor. See flat_uint16. args : none. return: color string. =cut sub toGdkString16 { my $self = shift; my @int_color = $self->flat_uint16; my $re = sprintf("#%04x%04x%04x",@int_color[0,1,2]); return $re; } around loadHash => sub { my $orig = shift; my $class = shift; my $hash = shift; return Gdraw2::Util::RGBColor->new( $hash->{red}, $hash->{green}, $hash->{blue} ); }; 1; =head1 RECORDABLE ATTRIBUTES These attributes will be serialized while calling "toHash". See "Gdraw2::Util::RoleRecordable" for details. red green blue =head1 SEE ALSO Cairo function set_source_rgb Gdraw2::Util::RGBAColor Gdraw2::Util::RoleRecordable =cut Gdraw2-v0.0.3/lib/Gdraw2Gtk000755001750001750 012001671021 15337 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/lib/Gdraw2Gtk/GroupEditor.pm000444001750001750 634412001671021 20304 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::GroupEditor; use strict; use feature qw/say switch/; use Moose; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use constant { CLASS_BLOCK => 'Gdraw2::Element::CairoBlock', CLASS_TAGSET => 'Gdraw2::Element::CairoTagset', CLASS_MAPPING => 'Gdraw2::Element::CairoMapping', CLASS_RULER => 'Gdraw2::Element::CairoRuler', CLASS_CURVE => 'Gdraw2::Element::CairoDataCurve', }; has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { Gtk2::Builder->new } ); sub BUILD { my $self = shift; my $builder = $self->uiBuilder; my $file_ui = dist_file( 'Gdraw2', 'GroupEditor.glade' ); $builder->add_from_file($file_ui); } sub run { my ( $self, $params, $is_circ ) = @_; # create dialog my $builder = $self->uiBuilder; my $editor = $builder->get_object('GroupEditor'); $editor->signal_connect( 'delete-event', sub { $editor->response(1); } ); # get widgets from builder my $name_entry = $builder->get_object('GroupEditor_NameEntry'); my $desc_entry = $builder->get_object('GroupEditor_DescEntry'); my $track_dist_spin = $builder->get_object('GroupEditor_TrackDistSpin'); my $start_spin = $builder->get_object('GroupEditor_StartSpin'); my $end_spin = $builder->get_object('GroupEditor_EndSpin'); my $left_margin_spin = $builder->get_object('GroupEditor_LeftMarginSpin'); my $right_margin_spin = $builder->get_object('GroupEditor_RightMarginSpin'); my $circ_start_indent_spin = $builder->get_object('GroupEditor_CircStartIndentSpin'); my $circ_end_indent_spin = $builder->get_object('GroupEditor_CircEndIndentSpin'); # set properties to widget $name_entry->set_text( $params->{displayName} ); $desc_entry->set_text( $params->{desc} ); $track_dist_spin->set_value( $params->{trackDistance} ); $start_spin->set_value( $params->{start} ); $end_spin->set_value( $params->{end} ); $left_margin_spin->set_value( $params->{leftMargin} ); $right_margin_spin->set_value( $params->{rightMargin} ); $circ_start_indent_spin->set_value( $params->{circStartIndent} ); $circ_end_indent_spin->set_value( $params->{circEndIndent} ); # apply topology if ($is_circ) { $left_margin_spin->set_sensitive(FALSE); $right_margin_spin->set_sensitive(FALSE); } else { $circ_start_indent_spin->set_sensitive(FALSE); $circ_end_indent_spin->set_sensitive(FALSE); } # run dialog my $re = $editor->run; $editor->hide; # accept changes if ( $re == 0 ) { $params->{displayName} = $name_entry->get_text; $params->{desc} = $desc_entry->get_text; $params->{trackDistance} = $track_dist_spin->get_value; $params->{start} = $start_spin->get_value; $params->{end} = $end_spin->get_value; $params->{leftMargin} = $left_margin_spin->get_value; $params->{rightMargin} = $right_margin_spin->get_value; $params->{circStartIndent} = $circ_start_indent_spin->get_value; $params->{circEndIndent} = $circ_end_indent_spin->get_value; } return $re; } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/RichSeqImportConfig.pm000444001750001750 4426712001671021 21746 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::RichSeqImportConfig; use strict; use feature qw/say switch/; use Moose; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use Gdraw2::Util qw/parse_color_str_16/; use constant { COL_TRACK => 0, COL_FEATURE => 1, COL_ELE_TYPE => 2, COL_TAG_NAME => 3, COL_STROKE => 4, COL_FILL => 5, COL_COLOR_SET => 6 }; has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { return Gtk2::Builder->new } ); sub BUILD { my $self = shift; # # load GUI resources # my $builder = $self->uiBuilder; my $file_ui = dist_file( 'Gdraw2', 'FeatureImporter.glade' ); $builder->add_from_file($file_ui); # # setup table # # create cell renderers my $col_track = $builder->get_object('TrackList_TrackCol'); my $col_feature = $builder->get_object('TrackList_FeatureCol'); my $col_ele_type = $builder->get_object('TrackList_EleTypeCol'); my $col_tag_name = $builder->get_object('TrackList_TagNameCol'); my $col_stroke = $builder->get_object('TrackList_StrokeCol'); my $col_fill = $builder->get_object('TrackList_FillCol'); my $r_name = Gtk2::CellRendererText->new; $col_track->pack_start( $r_name, TRUE ); $col_track->add_attribute( $r_name, 'text', COL_TRACK ); my $r_feature = Gtk2::CellRendererText->new; $col_feature->pack_start( $r_feature, TRUE ); $col_feature->add_attribute( $r_feature, 'text', COL_FEATURE ); my $r_ele_type = Gtk2::CellRendererText->new; $col_ele_type->pack_start( $r_ele_type, TRUE ); $col_ele_type->add_attribute( $r_ele_type, 'text', COL_ELE_TYPE ); my $r_tag_name = Gtk2::CellRendererText->new; $col_tag_name->pack_start( $r_tag_name, TRUE ); $col_tag_name->add_attribute( $r_tag_name, 'text', COL_TAG_NAME ); my $r_stroke = Gtk2::CellRendererText->new; $col_stroke->pack_start( $r_stroke, TRUE ); $col_stroke->add_attribute( $r_stroke, 'cell-background', COL_STROKE ); $col_stroke->add_attribute( $r_stroke, 'cell-background-set', COL_COLOR_SET ); my $r_fill = Gtk2::CellRendererText->new; $col_fill->pack_start( $r_fill, TRUE ); $col_fill->add_attribute( $r_fill, 'cell-background', COL_FILL ); $col_fill->add_attribute( $r_fill, 'cell-background-set', COL_COLOR_SET ); # add some tracks my $model = $builder->get_object('FeatureImporter_TrackModel'); my $iter_track = $model->append(undef); $model->set( $iter_track, COL_TRACK, 'CDS track', COL_COLOR_SET, FALSE ); my $iter_feat = $model->append($iter_track); $model->set( $iter_feat, COL_FEATURE, 'CDS', COL_ELE_TYPE, 'block', COL_TAG_NAME, 'locus_tag', COL_STROKE, '#000000000000', COL_FILL, '#00007fff7fff' ); # init UI state $self->on_FeatureImporter_RulerCheck_toggled; $self->on_FeatureImporter_RangeCheck_toggled; $self->on_FeatImporter_GCContentCheck_toggled; $self->on_FeatImporter_GCSkewCheck_toggled; # # connect signals # $builder->connect_signals( undef, $self ); } sub drawGC { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatImporter_GCContentCheck')->get_active; } sub gcWindowSize { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatImporter_GCContentSizeSpin')->get_value; } sub gcWindowStep { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatImporter_GCContentStepSpin')->get_value; } sub drawSkew { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatImporter_GCSkewCheck')->get_active; } sub skewWindowSize { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatImporter_GCSkewSizeSpin')->get_value; } sub skewWindowStep { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatImporter_GCSkewStepSpin')->get_value; } sub drawRuler { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatureImporter_RulerCheck')->get_active; } sub rulerTickInterval { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatureImporter_RulerSpin')->get_value; } sub importPartial { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatureImporter_RangeCheck')->get_active; } sub partialStart { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatureImporter_StartSpin')->get_value; } sub partialEnd { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('FeatureImporter_EndSpin')->get_value; } sub updateTableAt { my ( $self, $i ) = @_; } sub configTrackTemplate { my ( $self, $template ) = @_; # get objects my $builder = $self->uiBuilder; my $editor = $builder->get_object('ImportTrackEditor'); my $rbut_block = $builder->get_object('ImportTrackEditor_BlockTypeRadio'); my $rbut_tagset = $builder->get_object('ImportTrackEditor_TagsetTypeRadio'); my $entry_name = $builder->get_object('ImportTrackEditor_TrackNameEntry'); my $entry_desc = $builder->get_object('ImportTrackEditor_TrackDescEntry'); my $entry_name_tag = $builder->get_object('ImportTrackEditor_EleNameEntry'); my $colorbut_stroke = $builder->get_object('ImportTrackEditor_StrokeColorBut'); my $colorbut_fill = $builder->get_object('ImportTrackEditor_FillColorBut'); my $list = $builder->get_object('FeatImporter_TrackListModel'); # set data to editor given ( $template->eleType ) { when ('block') { $rbut_block->set_active(TRUE) } when ('tagset') { $rbut_tagset->set_active(TRUE) } } $entry_name->set_text( $template->name ); $entry_desc->set_text( join ', ', @{ $template->features } ); $entry_name_tag->set_text( join ', ', @{ $template->nameTags } ); my $color_s = $template->strokeColor; my $color_f = $template->fillColor; $colorbut_stroke->set_color( Gtk2::Gdk::Color->new( 65535 * $color_s->[0], 65535 * $color_s->[1], 65535 * $color_s->[2], ) ); $colorbut_fill->set_color( Gtk2::Gdk::Color->new( 65535 * $color_f->[0], 65535 * $color_f->[1], 65535 * $color_f->[2], ) ); $colorbut_stroke->set_alpha( 65535 * $color_s->[3] ); $colorbut_fill->set_alpha( 65535 * $color_f->[3] ); # run editor my $re = $editor->run; $editor->hide; # apply changes if ( $re == 0 ) { $template->name( $entry_name->get_text ); $template->features( [ split /,\s*/, $entry_desc->get_text ] ); $template->nameTags( [ split /,\s*/, $entry_name_tag->get_text ] ); if ( $rbut_block->get_active ) { $template->eleType('block') } elsif ( $rbut_tagset->get_active ) { $template->eleType('tagset') } my $re_s = $colorbut_stroke->get_color; $color_s->[0] = $re_s->red / 65535; $color_s->[1] = $re_s->green / 65535; $color_s->[2] = $re_s->blue / 65535; $color_s->[3] = $colorbut_stroke->get_alpha / 65535; my $re_f = $colorbut_fill->get_color; $color_f->[0] = $re_f->red / 65535; $color_f->[1] = $re_f->green / 65535; $color_f->[2] = $re_f->blue / 65535; $color_f->[3] = $colorbut_fill->get_alpha / 65535; } return $re; } sub clearTrackTemplate { my $self = shift; my $builder = $self->uiBuilder; my $list = $builder->get_object('FeatImporter_TrackListModel'); $list->clear; $self->{trackTemplates} = []; } sub run { my $self = shift; my $builder = $self->uiBuilder; # # run dialog # my $ui = $builder->get_object('FeatImporter'); my $re = $ui->run; $ui->hide; return $re; } sub getSelectedPath { my $self = shift; my $builder = $self->uiBuilder; my $table = $builder->get_object('FeatImporter_TrackList'); my $sel = $table->get_selection; return ( $sel->get_selected_rows )[-1]; } sub setFeatTemplate { my ( $self, $iter ) = @_; my $builder = $self->uiBuilder; my $entry_tag_name = $builder->get_object('ImportTrackEditor_TagNameEntry'); my $entry_feature = $builder->get_object('ImportTrackEditor_FeatureEntry'); my $rbut_type_block = $builder->get_object('ImportTrackEditor_BlockTypeRadio'); my $rbut_type_tagset = $builder->get_object('ImportTrackEditor_TagsetTypeRadio'); my $color_stroke = $builder->get_object('ImportTrackEditor_StrokeColorBut')->get_color; my $color_fill = $builder->get_object('ImportTrackEditor_FillColorBut')->get_color; my $str_stroke = sprintf( '#%04x%04x%04x', $color_stroke->red, $color_stroke->green, $color_stroke->blue ); my $str_fill = sprintf( '#%04x%04x%04x', $color_fill->red, $color_fill->green, $color_fill->blue ); my $ele_type; if ( $rbut_type_block->get_active ) { $ele_type = 'block'; } elsif ( $rbut_type_tagset->get_active ) { $ele_type = 'tags'; } $builder->get_object('FeatureImporter_TrackModel')->set( $iter, COL_FEATURE, $entry_feature->get_text, COL_TAG_NAME, $entry_tag_name->get_text, COL_ELE_TYPE, $ele_type, COL_STROKE, $str_stroke, COL_FILL, $str_fill, COL_COLOR_SET, TRUE ); } sub loadFeatTemplate { my ( $self, $iter ) = @_; my $builder = $self->uiBuilder; my $model = $builder->get_object('FeatureImporter_TrackModel'); my $entry_tag_name = $builder->get_object('ImportTrackEditor_TagNameEntry'); my $entry_feature = $builder->get_object('ImportTrackEditor_FeatureEntry'); my $rbut_type_block = $builder->get_object('ImportTrackEditor_BlockTypeRadio'); my $rbut_type_tagset = $builder->get_object('ImportTrackEditor_TagsetTypeRadio'); my $colorbut_stroke = $builder->get_object('ImportTrackEditor_StrokeColorBut'); my $colorbut_fill = $builder->get_object('ImportTrackEditor_FillColorBut'); $entry_feature->set_text( $model->get( $iter, COL_FEATURE ) ); $entry_tag_name->set_text( $model->get( $iter, COL_TAG_NAME ) ); my $ele_type = $model->get( $iter, COL_ELE_TYPE ); if ( $ele_type eq 'block' ) { $rbut_type_block->set_active(TRUE) } elsif ( $ele_type eq 'tags' ) { $rbut_type_tagset->set_active(TRUE) } else { confess "invalid element type: $ele_type" } my $color_stroke = Gtk2::Gdk::Color->parse( $model->get( $iter, COL_STROKE ) ); my $color_fill = Gtk2::Gdk::Color->parse( $model->get( $iter, COL_FILL ) ); $colorbut_stroke->set_color($color_stroke); $colorbut_fill->set_color($color_fill); } sub on_FeatImporter_AddTrackBut_clicked { my $self = shift; my $builder = $self->uiBuilder; my $dialog_track = $builder->get_object('TrackEditor'); my $name_entry = $builder->get_object('TrackEditor_TrackNameEntry'); my $model = $builder->get_object('FeatureImporter_TrackModel'); my $table = $builder->get_object('FeatImporter_TrackList'); my $re = $dialog_track->run; $dialog_track->hide; if ( $re == 0 ) { my $name = $name_entry->get_text; my $path_sel = $self->getSelectedPath; my $iter; if ($path_sel) { my @i_sel = $path_sel->get_indices; my $iter_rel = $model->get_iter_from_string( $i_sel[0] ); $iter = $model->insert_after( undef, $iter_rel ); } else { $iter = $model->append(undef); } $model->set( $iter, COL_TRACK, $name ); my $path = $model->get_path($iter); $table->expand_to_path($path); $table->set_cursor($path); } } sub on_FeatureImporter_AddFeatureBut_clicked { my $self = shift; my $path_sel = $self->getSelectedPath; return if ( !defined $path_sel ); my $builder = $self->uiBuilder; my $dialog_feat = $builder->get_object('FeatureEditor'); my $model = $builder->get_object('FeatureImporter_TrackModel'); my $table = $builder->get_object('FeatImporter_TrackList'); my $re = $dialog_feat->run; $dialog_feat->hide; if ( $re == 0 ) { my @i = $path_sel->get_indices; my $iter; if ( @i == 2 ) { my $iter_ref = $model->get_iter($path_sel); $iter = $model->insert_after( undef, $iter_ref ); } elsif ( @i == 1 ) { my $iter_parent = $model->get_iter($path_sel); $iter = $model->append($iter_parent); } else { confess "invalid indices"; } $self->setFeatTemplate($iter); my $path = $model->get_path($iter); $table->expand_to_path($path); $table->set_cursor($path); } } sub on_FeatImporter_EditBut_clicked { my $self = shift; my $path_sel = $self->getSelectedPath; return if ( !defined $path_sel ); my $builder = $self->uiBuilder; my $model = $builder->get_object('FeatureImporter_TrackModel'); my $iter_sel = $model->get_iter($path_sel); my $depth = $model->iter_depth($iter_sel); if ( $depth == 0 ) { my $dialog_track = $builder->get_object('TrackEditor'); my $entry_name = $builder->get_object('TrackEditor_TrackNameEntry'); $entry_name->set_text( $model->get( $iter_sel, COL_TRACK ) ); my $re = $dialog_track->run; $dialog_track->hide; if ( $re == 0 ) { $model->set( $iter_sel, COL_TRACK, $entry_name->get_text ); } } elsif ( $depth == 1 ) { my $dialog_feat = $builder->get_object('FeatureEditor'); $self->loadFeatTemplate($iter_sel); my $re = $dialog_feat->run; $dialog_feat->hide; if ( $re == 0 ) { $self->setFeatTemplate($iter_sel); } } else { confess "invalid depth $depth"; } } sub on_FeatImporter_UpBut_clicked { my $self = shift; my $path_sel = $self->getSelectedPath; return if !defined $path_sel; my @i_ref = $path_sel->get_indices; return if $i_ref[-1] == 0; $i_ref[-1]--; my $builder = $self->uiBuilder; my $model = $builder->get_object('FeatureImporter_TrackModel'); my $table = $builder->get_object('FeatImporter_TrackList'); my $iter_sel = $model->get_iter($path_sel); my $iter_ref = $model->get_iter_from_string( join ':', @i_ref ); $model->swap( $iter_sel, $iter_ref ); } sub on_FeatImporter_DownBut_clicked { my $self = shift; my $path_sel = $self->getSelectedPath; return if !defined $path_sel; my $builder = $self->uiBuilder; my $model = $builder->get_object('FeatureImporter_TrackModel'); my $table = $builder->get_object('FeatImporter_TrackList'); my $iter_sel = $model->get_iter($path_sel); my $iter_ref = $model->iter_next($iter_sel); return if !defined $iter_ref; $model->swap( $iter_sel, $iter_ref ); } sub on_FeatImporter_DelBut_clicked { my $self = shift; my $path_sel = $self->getSelectedPath; return if !defined $path_sel; # ask for sure my $builder = $self->uiBuilder; my $dialog = $builder->get_object('DelObjMsg'); my $re = $dialog->run; $dialog->hide; return if $re eq 'yes'; # do removal my $model = $builder->get_object('FeatureImporter_TrackModel'); my $iter = $model->get_iter($path_sel); $model->remove($iter); } sub on_FeatureImporter_RulerCheck_toggled { my $self = shift; my $builder = $self->uiBuilder; my $check = $builder->get_object('FeatureImporter_RulerCheck'); my $state = $check->get_active; $builder->get_object('FeatureImporter_RulerSpin')->set_sensitive($state); } sub on_FeatureImporter_RangeCheck_toggled { my $self = shift; my $builder = $self->uiBuilder; my $check = $builder->get_object('FeatureImporter_RangeCheck'); my $state = $check->get_active; $builder->get_object('FeatureImporter_StartSpin')->set_sensitive($state); $builder->get_object('FeatureImporter_EndSpin')->set_sensitive($state); } sub on_FeatImporter_GCContentCheck_toggled { my $self = shift; my $builder = $self->uiBuilder; my $check = $builder->get_object('FeatImporter_GCContentCheck'); my $state = $check->get_active; $builder->get_object('FeatImporter_GCContentSizeSpin')->set_sensitive($state); $builder->get_object('FeatImporter_GCContentStepSpin')->set_sensitive($state); } sub on_FeatImporter_GCSkewCheck_toggled { my $self = shift; my $builder = $self->uiBuilder; my $check = $builder->get_object('FeatImporter_GCSkewCheck'); my $state = $check->get_active; $builder->get_object('FeatImporter_GCSkewSizeSpin')->set_sensitive($state); $builder->get_object('FeatImporter_GCSkewStepSpin')->set_sensitive($state); } sub getTrackTemplates { my ( $self, $track_store, $feat_store ) = @_; my $i_track = 0; my $builder = $self->uiBuilder; my $model = $builder->get_object('FeatureImporter_TrackModel'); my $iter_track = $model->get_iter_first; while ( defined $iter_track ) { my $track_name = $model->get( $iter_track, COL_TRACK ); push @$track_store, $track_name; my $iter_feat = $model->iter_children($iter_track); while ( defined $iter_feat ) { my ( $feat, $ele_type, $tags_str, $stroke_str, $fill_str ) = $model->get( $iter_feat, COL_FEATURE, COL_ELE_TYPE, COL_TAG_NAME, COL_STROKE, COL_FILL ); my @tags = split /,\s*/, $tags_str; my @stroke = map { $_ / 65535 } parse_color_str_16($stroke_str); my @fill = map { $_ / 65535 } parse_color_str_16($fill_str); $feat_store->{$feat} = [] if !exists $feat_store->{$feat}; push @{ $feat_store->{$feat} }, [ $i_track, $ele_type, [@tags], [ @stroke, 1 ], [ @fill, 1 ] ]; } continue { $iter_feat = $model->iter_next($iter_feat); } } continue { $iter_track = $model->iter_next($iter_track); $i_track++; } } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/BlastImportConfig.pm000444001750001750 461512001671021 21426 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::BlastImportConfig; use strict; use feature qw/say switch/; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use Moose; use Gdraw2::Element::CairoBlock has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { return Gtk2::Builder->new } ); sub BUILD { my $self = shift; # load GUI resources my $builder = $self->uiBuilder; my $file_ui = dist_file( 'Gdraw2', 'BlastImporter.glade' ); $builder->add_from_file($file_ui); # connect signals $builder->connect_signals( undef, $self ); # update UI $self->on_BlastImporter_EValueCheck_toggled; $self->on_BlastImporter_BitScoreCheck_toggled; } sub run { my $self = shift; my $builder = $self->uiBuilder; my $dialog = $builder->get_object('BlastImporter'); my $re = $dialog->run; $dialog->hide; return $re; } sub doFiltEValue { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('BlastImporter_EValueCheck')->get_active; } sub doFiltBitScore { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('BlastImporter_BitScoreCheck')->get_active; } sub eValueCutoff { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('BlastImporter_EValueEntry')->get_text; } sub bitScoreCutoff { my $self = shift; my $builder = $self->uiBuilder; return $builder->get_object('BlastImporter_BitScoreSpin')->get_value; } sub stackHSPs { my $self = shift; my $builder = $self->uiBuilder; if ( $builder->get_object('BlastImporter_TrackLayout')->get_active ) { return 0; } elsif ( $builder->get_object('BlastImporter_ElemLayout')->get_active ) { return 1; } else { confess ""; } } sub on_BlastImporter_EValueCheck_toggled { my $self = shift; my $builder = $self->uiBuilder; my $check = $builder->get_object('BlastImporter_EValueCheck'); my $widget = $builder->get_object('BlastImporter_EValueEntry'); $widget->set_sensitive( $check->get_active ); } sub on_BlastImporter_BitScoreCheck_toggled { my $self = shift; my $builder = $self->uiBuilder; my $check = $builder->get_object('BlastImporter_BitScoreCheck'); my $widget = $builder->get_object('BlastImporter_BitScoreSpin'); $widget->set_sensitive( $check->get_active ); } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/App.pm000444001750001750 11412712001671021 16620 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::App; use Moose; use feature qw/say switch/; use Cairo; use File::ShareDir qw/:ALL/; use File::Basename; use File::Path; use File::Spec::Functions qw/:ALL/; use Gdraw2::CairoTrack; use Gdraw2::CairoTrackGroup; use Gdraw2::CairoTrackPage; use Gdraw2::Element::CairoBlock; use Gdraw2::Element::CairoTagset; use Gdraw2::Element::CairoDataCurve; use Gdraw2::Element::CairoMapping; use Gdraw2::Element::CairoRuler; use Gdraw2::Util qw/load_module/; use Gdraw2Gtk::Task; use Gdraw2Gtk::RichSeqImportConfig; use Gdraw2Gtk::BlastImportConfig; use Gdraw2Gtk::EleTypeWizard; use Gdraw2Gtk::ElementEditor; use Gdraw2Gtk::TrackEditor; use Gdraw2Gtk::GroupEditor; use Gdraw2Gtk::PageEditor; use Gdraw2Gtk::Act; use Glib qw/TRUE FALSE/; use Gtk2 qw/init/; use Scalar::Util qw/blessed/; use YAML qw/Load Dump LoadFile DumpFile/; use constant { CLASS_BLOCK => 'Gdraw2::Element::CairoBlock', CLASS_TAGSET => 'Gdraw2::Element::CairoTagset', CLASS_MAPPING => 'Gdraw2::Element::CairoMapping', CLASS_RULER => 'Gdraw2::Element::CairoRuler', CLASS_CURVE => 'Gdraw2::Element::CairoDataCurve', }; my $PAGEUI_TASK_KEY = 'gdraw2_task_id'; my $TASK_ID_SEED = 0; has tasks => ( is => 'bare', isa => 'HashRef[Gdraw2Gtk::Task]', default => sub { {} } ); has clip => ( is => 'rw', default => undef ); has uiBuilder => ( is => 'rw', isa => 'Gtk2::Builder', default => sub { return Gtk2::Builder->new } ); has elementEditor => ( is => 'ro', isa => 'Gdraw2Gtk::ElementEditor', default => sub { Gdraw2Gtk::ElementEditor->new } ); has eleTypeWizard => ( is => 'ro', isa => 'Gdraw2Gtk::EleTypeWizard', default => sub { Gdraw2Gtk::EleTypeWizard->new } ); has trackEditor => ( is => 'ro', isa => 'Gdraw2Gtk::TrackEditor', default => sub { Gdraw2Gtk::TrackEditor->new } ); has groupEditor => ( is => 'ro', isa => 'Gdraw2Gtk::GroupEditor', default => sub { Gdraw2Gtk::GroupEditor->new } ); has pageEditor => ( is => 'ro', isa => 'Gdraw2Gtk::PageEditor', default => sub { Gdraw2Gtk::PageEditor->new } ); has richSeqImporter => ( is => 'ro', isa => 'Gdraw2Gtk::RichSeqImportConfig', default => sub { Gdraw2Gtk::RichSeqImportConfig->new } ); has blastImporter => ( is => 'ro', isa => 'Gdraw2Gtk::BlastImportConfig', default => sub { Gdraw2Gtk::BlastImportConfig->new } ); sub BUILD { my $self = shift; # # load GUI resources # my $file_ui_mw = dist_file( 'Gdraw2', 'Gdraw2UI.glade' ); my $file_ui_group_editor = dist_file( 'Gdraw2', 'GroupEditor.glade' ); my $file_ui_page_editor = dist_file( 'Gdraw2', 'PageEditor.glade' ); my $file_ui_dialogs = dist_file( 'Gdraw2', 'FileDialogs.glade' ); my $builder = $self->uiBuilder; $builder->add_objects_from_file( $file_ui_mw, qw/ AppMW AskSaveDialog AddElementAction AddGroupAction AddTrackAction DeleteObjAction EditObjAction MoveUpAction MoveDownAction NewFileAction OpenFileAction SaveFileAction SaveAsAction CloseFileAction ImportSeqAction ImportBlastAction ExportFileAction ConfigPageAction CopyAction CutAction PasteAction UndoAction RedoAction MainExitAction ForceRefreshAction/ ); $builder->add_from_file($file_ui_group_editor); $builder->add_from_file($file_ui_page_editor); $builder->add_from_file($file_ui_dialogs); $builder->connect_signals( undef, $self ); # # bind shortcuts # my $mw = $builder->get_object('AppMW'); my $accel = Gtk2::AccelGroup->new(); $accel->connect( ord('o'), 'control-mask', 'visible', sub { $builder->get_object('OpenFileAction')->activate; return TRUE; } ); $accel->connect( ord('s'), 'control-mask', 'visible', sub { $builder->get_object('SaveFileAction')->activate; return TRUE; } ); $accel->connect( ord('s'), [ 'control-mask', 'shift-mask' ], 'visible', sub { $builder->get_object('SaveAsAction')->activate; return TRUE; } ); $accel->connect( ord('x'), 'control-mask', 'visible', sub { $builder->get_object('CutAction')->activate; return TRUE; } ); $accel->connect( ord('c'), 'control-mask', 'visible', sub { $builder->get_object('CopyAction')->activate; return TRUE; } ); $accel->connect( ord('v'), 'control-mask', 'visible', sub { $builder->get_object('PasteAction')->activate; return TRUE; } ); $accel->connect( ord('z'), 'control-mask', 'visible', sub { $builder->get_object('UndoAction')->activate; return TRUE; } ); $accel->connect( ord('z'), [ 'control-mask', 'shift-mask' ], 'visible', sub { $builder->get_object('RedoAction')->activate; return TRUE; } ); $accel->connect( 127, 'release-mask', 'visible', sub { $builder->get_object('DeleteObjAction')->activate; return TRUE; } ); $mw->add_accel_group($accel); # update UI state $self->_notebook_modify; } sub newTask { my $self = shift; my $builder_mw = $self->uiBuilder; # create cairo context my $buff_surface = Cairo::ImageSurface->create( 'argb32', 2000, 2000 ); my $buff_cr = Cairo::Context->create($buff_surface); # create TrackPage object my $page = Gdraw2::CairoTrackPage->new( cairoContext => $buff_cr ); if ( $self->pageEditor->run($page) == 0 ) { my $id = $TASK_ID_SEED++; my $nb_label = Gtk2::Label->new('Untitled'); my $task = Gdraw2Gtk::Task->new( app => $self, id => $id, page => $page, label => $nb_label ); my $builder = $task->uiBuilder; $builder->connect_signals( undef, $self ); # add to main window my $page_ui = $builder->get_object('PageComp'); $page_ui->{$PAGEUI_TASK_KEY} = $id; my $notebook = $builder_mw->get_object('AppMW_Pages'); my $page_i = $notebook->append_page( $page_ui, $nb_label ); $notebook->set_tab_reorderable( $page_ui, TRUE ); my $tree = $builder->get_object('PageComp_PageTree'); # set DrawingArea size my $area = $builder->get_object('PageComp_PreviewArea'); $area->set_size_request( $page->width, $page->height ); # store them in the app $self->{tasks}{$id} = $task; # connect signals $area->signal_connect_swapped( 'expose-event', \&Gdraw2Gtk::Task::on_area_expose, $task ); $builder->get_object('but_dbg') ->signal_connect( 'clicked', \&dbg_cb, $task ); $builder->get_object('but_dbg_clip') ->signal_connect( 'clicked', \&dbg_clip_cb, $task ); $task->saved(0); $task->page->draw; $notebook->set_current_page( $notebook->get_n_pages - 1 ); } } sub openTask { my ( $self, $file ) = @_; # create cairo context my ($store) = LoadFile($file); my $buff_surface = Cairo::ImageSurface->create( 'argb32', 2000, 2000 ); my $buff_cr = Cairo::Context->create($buff_surface); # create page object my $page = Gdraw2::CairoTrackPage->loadHash( $store, cairoContext => $buff_cr ); # create task object my $id = $TASK_ID_SEED++; my $nb_label = Gtk2::Label->new( basename($file) ); my $task = Gdraw2Gtk::Task->new( app => $self, id => $id, file => $file, page => $page, label => $nb_label, saved => 1 ); $self->{tasks}{$id} = $task; # add to main window my $builder = $task->uiBuilder; my $builder_mw = $self->uiBuilder; my $page_ui = $builder->get_object('PageComp'); $page_ui->{$PAGEUI_TASK_KEY} = $id; my $notebook = $builder_mw->get_object('AppMW_Pages'); $notebook->append_page( $page_ui, $nb_label ); # set DrawingArea size my $area = $builder->get_object('PageComp_PreviewArea'); $area->set_size_request( $page->width, $page->height ); # connect signals $builder->connect_signals( undef, $self ); $area->signal_connect_swapped( 'expose-event', \&Gdraw2Gtk::Task::on_area_expose, $task ); $builder->get_object('but_dbg') ->signal_connect( 'clicked', \&dbg_cb, $task ); $builder->get_object('but_dbg_clip') ->signal_connect( 'clicked', \&dbg_clip_cb, $task ); # redraw $task->page->draw; $task->on_area_expose( undef, $area ); # swich to that task $notebook->set_current_page( $notebook->get_n_pages - 1 ); } sub closeTask { my ( $self, $task ) = @_; # remove from store delete $self->{tasks}{ $task->id }; # remove from UI my $notebook = $self->uiBuilder->get_object('AppMW_Pages'); $notebook->remove_page( $notebook->get_current_page ); } sub getCurrentTaskUI { my $self = shift; my $book = $self->uiBuilder->get_object('AppMW_Pages'); if ( $book->get_n_pages > 0 ) { return $book->get_nth_page( $book->get_current_page ); } else { return undef; } } sub getCurrentTask { my $self = shift; my $page_ui = $self->getCurrentTaskUI; return undef if !defined $page_ui; my $key = $page_ui->{$PAGEUI_TASK_KEY}; if ( exists $self->{tasks}{$key} ) { return $self->{tasks}{$key}; } else { confess "failed to fetch Task object from $page_ui via key '$key'"; } } sub areYouSure { my $self = shift; my $dialog = Gtk2::MessageDialog->new( undef, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_QUESTION', 'GTK_BUTTONS_YES_NO', @_ ); my $re = $dialog->run; $dialog->destroy; return $re; } sub askForSave { my ( $self, $task ) = @_; my $file = $task->file; my $builder = $self->uiBuilder; my $disp_name = $file eq '' ? 'Untitled' : basename($file); my $label = $builder->get_object('AskSaveDialog_Label'); $label->set_text("Save changes for ($disp_name)?"); my $dialog = $builder->get_object('AskSaveDialog'); my $re = $dialog->run; $dialog->hide; return $re; } sub showWarn { my $self = shift; my $dialog = Gtk2::MessageDialog->new( undef, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_WARNING', 'GTK_BUTTONS_OK', @_ ); $dialog->run; $dialog->destroy; } sub showError { my $self = shift; my $dialog = Gtk2::MessageDialog->new( undef, 'GTK_DIALOG_MODAL', 'GTK_MESSAGE_ERROR', 'GTK_BUTTONS_OK', @_ ); $dialog->run; $dialog->destroy; } sub run { my $self = shift; my $builder = $self->uiBuilder; $builder->get_object('AppMW')->show; Gtk2->main(); } sub on_MainExitAction_activate { my $self = shift; my $builder = $self->uiBuilder; my $file_dialog = $builder->get_object('SaveTaskFileDialog'); my $all_saved = 1; foreach my $task ( values %{ $self->{tasks} } ) { if ( !$task->saved ) { my $re = $self->askForSave($task); # yes: 0 if ( $re == 0 ) { if ( $task->file ne '' ) { $task->save_task( $task->file ); } else { # ask for a file my $re_file = $file_dialog->run; $file_dialog->hide; if ( $re_file == 0 ) { $task->save_task( $file_dialog->get_filename ); } else { $all_saved = 0; last; } } } # no: 1 elsif ( $re == 1 ) { # do nothing if not save } # cancel: 2 elsif ( $re == 2 ) { $all_saved = 0; last; } } } Gtk2::main_quit() if $all_saved; return TRUE; } sub on_NewFileAction_activate { my ( $self, $action ) = @_; $self->newTask; } sub on_OpenFileAction_activate { my ( $self, $action ) = @_; # select the file to open my $file_dialog = Gtk2::FileChooserDialog->new( 'Open file', $self->uiBuilder->get_object('AppMW'), 'open', 'Ok' => 'ok', 'Cancel' => 'cancel' ); my $filter = Gtk2::FileFilter->new; $filter->set_name('yaml'); $filter->add_pattern('*.yaml'); $filter->add_pattern('*.yml'); $file_dialog->add_filter($filter); my $re = $file_dialog->run; if ( $re eq 'ok' ) { my $file = $file_dialog->get_filename; # find if this file is already opened if ( !file_name_is_absolute($file) ) { $file = rel2abs($file); } foreach my $exist_task ( values %{ $self->{tasks} } ) { my $exist_file = $exist_task->file; $exist_file = rel2abs($exist_file) if !file_name_is_absolute($exist_file); if ( $exist_file eq $file ) { $file_dialog->destroy; $self->showWarn("File '$file' is already opened"); return; } } # open $self->openTask($file); } $file_dialog->destroy; } sub on_SaveAsAction_activate { my ( $self, $action ) = @_; my $task = $self->getCurrentTask; return if !defined $task; my $builder = $self->uiBuilder; my $dialog = $builder->get_object('SaveTaskFileDialog'); my $re = $dialog->run; $dialog->hide; if ( $re == 0 ) { my $file = $dialog->get_filename; $task->save_task($file); } } sub on_SaveFileAction_activate { my ( $self, $action ) = @_; my $task = $self->getCurrentTask; return if !defined $task; my $file = $task->file; if ( $file eq '' ) { $self->on_SaveAsAction_activate(undef); } else { $task->save_task($file); } } sub on_ImportSeqAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # create file dialog my $chooser = Gtk2::FileChooserDialog->new( 'Import sequence features', $self->uiBuilder->get_object('AppMW'), 'open', 'Ok' => 'ok', 'Cancel' => 'cancel' ); # run my $re = $chooser->run; my $file = $chooser->get_filename; $chooser->destroy; if ( $re eq 'ok' ) { # create input handle eval { load_module('Bio::SeqIO') }; if ($@) { $self->showError("Failed to load Bioperl module 'Bio::SeqIO':\n$@"); return undef; } my $IN; eval { $IN = Bio::SeqIO->new( -file => $file ) }; if ($@) { $self->showError("Bioperl failed to parse file '$file':\n$@"); return undef; } my $re2 = $self->richSeqImporter->run; if ( $re2 == 0 ) { eval { $task->importRichSeq( $self->richSeqImporter, $IN ); }; if ($@) { $self->showError("Failed to import '$file':\n$@"); } } $IN->close; } } sub on_ImportBlastAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # create file dialog my $chooser = Gtk2::FileChooserDialog->new( 'Import blast result', $self->uiBuilder->get_object('AppMW'), 'open', 'Ok' => 'ok', 'Cancel' => 'cancel' ); # run my $re = $chooser->run; my $file = $chooser->get_filename; $chooser->destroy; if ( $re eq 'ok' ) { # create input handle eval { load_module('Bio::SearchIO') }; if ($@) { $self->showError( "Failed to load Bioperl module 'Bio::SearchIO':\n$@"); return undef; } my $IN; eval { $IN = Bio::SearchIO->new( -file => $file ) }; if ($@) { $self->showError("Bioperl failed to parse file '$file':\n$@"); return undef; } my $re2 = $self->blastImporter->run; if ( $re2 == 0 ) { eval { $task->importBlast( $self->blastImporter, $IN ); }; if ($@) { $self->showError("Failed to import '$file':\n$@"); } } $IN->close; } } sub on_ExportFileAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $chooser = Gtk2::FileChooserDialog->new( 'Export image', $self->uiBuilder->get_object('AppMW'), 'save', 'Ok' => 'ok', 'Cancel' => 'cancel' ); my $filter_png = Gtk2::FileFilter->new; $filter_png->set_name('Portable Network Graphics (*.png)'); $filter_png->add_pattern('*.png'); $filter_png->add_mime_type('image/png'); my $filter_pdf = Gtk2::FileFilter->new; $filter_pdf->set_name('Portable Document Format (*.pdf)'); $filter_pdf->add_pattern('*.pdf'); $filter_pdf->add_mime_type('application/pdf'); my $filter_svg = Gtk2::FileFilter->new; $filter_svg->set_name('Scalable Vector Graphics (*.svg)'); $filter_svg->add_pattern('*.svg'); $filter_svg->add_mime_type('image/svg+xml'); my $filter_ps = Gtk2::FileFilter->new; $filter_ps->set_name('PostScript (*.ps)'); $filter_ps->add_pattern('*.ps'); $chooser->add_filter($filter_pdf); $chooser->add_filter($filter_svg); $chooser->add_filter($filter_ps); $chooser->add_filter($filter_png); my $re = $chooser->run; if ( $re eq 'ok' ) { my $file = $chooser->get_filename; my $filter = $chooser->get_filter; my $format; if ( $filter == $filter_png ) { $format = 'png'; } elsif ( $filter == $filter_pdf ) { $format = 'pdf'; } elsif ( $filter == $filter_svg ) { $format = 'svg'; } elsif ( $filter == $filter_ps ) { $format = 'ps'; } else { confess "invalid export filter: $filter"; } eval { $task->export( $file, $format ) }; if ($@) { $self->showError("Failure on export image:\n$@"); } } $chooser->destroy; } sub on_CloseFileAction_activate { my ( $self, $action ) = @_; my $task = $self->getCurrentTask; return if !defined $task; if ( !$task->saved ) { my $re = $self->askForSave($task); # yes: 0 if ( $re == 0 ) { $self->on_SaveFileAction_activate(undef); $self->closeTask($task) if ( $task->saved ); } # no: 1 elsif ( $re == 1 ) { $self->closeTask($task); } # cancel: 2, do nothing } else { say ""; $self->closeTask($task); } } sub on_AddGroupAction_activate { my ( $self, $action ) = @_; my $task = $self->getCurrentTask; # create group my $group = Gdraw2::CairoTrackGroup->new(); # configure group my $params = $group->getParams(); my $re = $self->groupEditor->run( $params, $task->page->isCircular ); if ( $re == 0 ) { # apply parameters $group->applyParams($params); # get currently selected index # add to parent my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; my $path; if ( defined $last_path ) { my @i_list = $last_path->get_indices; $path = $task->add_group_at( $group, $i_list[0] + 1 ); } else { $path = $task->append_group($group); } # save act my $act = Gdraw2Gtk::Act::Add->new( task => $task, object => $group, indices => [ $path->get_indices ], ); $task->add_act($act); # update $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } sub on_AddTrackAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; if ( !defined $last_path ) { $self->showWarn("add track: no parent selected"); return; } # create track, and config my $track = Gdraw2::CairoTrack->new(); my $params = $track->getParams; my $re = $self->trackEditor->run($params); # get currently selected index, and # add track to parent if ( $re == 0 ) { $track->applyParams($params); my @i_list = $last_path->get_indices; my $path; # add this track after current track if ( @i_list > 1 ) { $i_list[1]++; $path = $task->add_track_at( $track, @i_list[ 0, 1 ] ); } # append this track at end of current group else { $path = $task->append_track( $track, $i_list[0] ); } # save act my $act = Gdraw2Gtk::Act::Add->new( task => $task, object => $track, indices => [ $path->get_indices ], ); $task->add_act($act); # mark as changed $task->saved(0); # update preview $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } sub on_AddElementAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # validate selection if ( !defined $last_path ) { $self->showWarn( "Select a track to add at, or an element to add after!"); return; } my @i_list = $last_path->get_indices; if ( @i_list < 2 ) { $self->showWarn( "Select a track to add at, or an element to add after!"); return; } # get the type to create # create element my $ele_type = $self->eleTypeWizard->run; my $ele; if ( defined $ele_type ) { $ele = $ele_type->new; } else { return; } # configure element # add element to parents my $params = $ele->getParams; if ( $self->elementEditor->run($params) == 0 ) { $ele->applyParams($params); # add after an element my $path; if ( @i_list == 3 ) { $i_list[2]++; $path = $task->add_element_at( $ele, @i_list[ 0, 1, 2 ] ); } # append on tail of a track else { $path = $task->append_element( $ele, @i_list[ 0, 1 ] ); } # save act my $act = Gdraw2Gtk::Act::Add->new( task => $task, object => $ele, indices => [ $path->get_indices ], ); $task->add_act($act); # mark as unsaved $task->saved(0); # update preview $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } sub on_ConfigPageAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $page = $task->page; my $params_old = $page->getParams; # run editor my $re = $self->pageEditor->run($page); if ( $re == 0 ) { $task->saved(0); # store act my $act = Gdraw2Gtk::Act::Config->new( task => $task, indices => [], params_old => $params_old, params_new => $page->getParams ); $task->add_act($act); # change size of DrawingArea $task->uiBuilder->get_object('PageComp_PreviewArea') ->set_size_request( $page->width, $page->height ); # update preview $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } sub on_EditObjAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $page = $task->page; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # validate selection if ( !defined $last_path ) { $self->showWarn("Select an object to config!"); return; } my @i_list = $last_path->get_indices; if ( @i_list == 3 ) { my $ele = $page->getChildAt( $i_list[0] )->getChildAt( $i_list[1] ) ->getChildAt( $i_list[2] ); my $params = $ele->getParams; if ( $self->elementEditor->run($params) == 0 ) { # save act my $act = Gdraw2Gtk::Act::Config->new( task => $task, indices => [@i_list], params_old => $ele->getParams, params_new => $params ); $task->add_act($act); # apply changes $ele->applyParams($params); # update GUI $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); $task->update_table_at(@i_list); $task->saved(0); } } elsif ( @i_list == 2 ) { my $track = $page->getChildAt( $i_list[0] )->getChildAt( $i_list[1] ); my $params = $track->getParams; if ( $self->trackEditor->run($params) == 0 ) { # save act my $act = Gdraw2Gtk::Act::Config->new( task => $task, indices => [@i_list], params_old => $track->getParams, params_new => $params ); $task->add_act($act); # apply changes $track->applyParams($params); # update preview $task->update_table_at(@i_list); $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } elsif ( @i_list == 1 ) { my $grp = $page->getChildAt( $i_list[0] ); my $params = $grp->getParams; if ( $self->groupEditor->run( $params, $page->isCircular ) == 0 ) { # save act my $act = Gdraw2Gtk::Act::Config->new( task => $task, indices => [@i_list], params_old => $grp->getParams, params_new => $params ); $task->add_act($act); # modify group $grp->applyParams($params); $task->update_table_at(@i_list); $task->saved(0); # update preview $page->arrangeAll; $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } else { confess "invalid indices: @i_list\n"; } } sub on_DeleteObjAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; if ( !defined $last_path ) { $self->showWarn("Select an object to delete!"); return; } # ask if sure if ( $self->areYouSure("Are you sure to delete selected object?") eq 'no' ) { return; } # delete element, track, or group my @i_list = $last_path->get_indices; my $obj; if ( @i_list == 3 ) { $obj = $task->remove_element_at(@i_list); $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } elsif ( @i_list == 2 ) { $obj = $task->remove_track_at(@i_list); $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } elsif ( @i_list == 1 ) { $obj = $task->remove_group_at(@i_list); $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } else { confess "invalid selection index amount: @i_list"; } my $act = Gdraw2Gtk::Act::Remove->new( task => $task, indices => [@i_list], object => $obj ); $task->add_act($act); } sub on_MoveUpAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $page = $task->page; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # validate selection if ( !defined $last_path ) { $self->showWarn("Select an object to move!"); return; } my @i_list = $last_path->get_indices; return if $i_list[-1] == 0; # save an act my $act = Gdraw2Gtk::Act::Move->new( task => $task, indices => [@i_list], direction => 'up' ); $task->add_act($act); # do move $task->move_at( @i_list, 'up' ); $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } sub on_MoveDownAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $page = $task->page; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # validate selection if ( !defined $last_path ) { $self->showWarn("Select an object to move!"); return; } my @i_list = $last_path->get_indices; my $amount; if ( @i_list == 3 ) { my $grp = $page->getChildAt( $i_list[0] ); my $trk = $grp->getChildAt( $i_list[1] ); $amount = $trk->numChildren; } elsif ( @i_list == 2 ) { my $grp = $page->getChildAt( $i_list[0] ); $amount = $grp->numChildren; } elsif ( @i_list == 1 ) { $amount = $page->numChildren; } return if $i_list[-1] == $amount - 1; # save an act my $act = Gdraw2Gtk::Act::Move->new( task => $task, indices => [@i_list], direction => 'down' ); $task->add_act($act); # do move $task->move_at( @i_list, 'down' ); $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } sub on_CutAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # validate selection if ( !defined $last_path ) { $self->showWarn("Select an object to cut!"); return; } my @i_list = $last_path->get_indices; my $page = $task->page; my $obj; if ( @i_list == 3 ) { $obj = $task->remove_element_at(@i_list); $self->clip( $obj->toHash ); } elsif ( @i_list == 2 ) { $obj = $task->remove_track_at(@i_list); $self->clip( $obj->toHash ); } elsif ( @i_list == 1 ) { $obj = $task->remove_group_at(@i_list); $self->clip( $obj->toHash ); } else { confess "invalid index list: @i_list"; } $task->saved(0); # save undo/redo my $act = Gdraw2Gtk::Act::Remove->new( task => $task, indices => [@i_list], object => $obj ); $task->add_act($act); # update preview $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } sub on_CopyAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # validate selection if ( !defined $last_path ) { $self->showWarn("Select an object to copy!"); return; } my @i_list = $last_path->get_indices; my $page = $task->page; if ( @i_list == 3 ) { $self->clip( $page->getChildAt( $i_list[0] )->getChildAt( $i_list[1] ) ->getChildAt( $i_list[2] )->toHash ); } elsif ( @i_list == 2 ) { $self->clip( $page->getChildAt( $i_list[0] )->getChildAt( $i_list[1] )->toHash ); } elsif ( @i_list == 1 ) { $self->clip( $page->getChildAt( $i_list[0] )->toHash ); } else { confess "invalid index list: @i_list"; } } sub on_PasteAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; return if !defined $self->clip; # get current selection index my $builder = $task->uiBuilder; my $treeview = $builder->get_object('PageComp_PageTree'); my $sel = $treeview->get_selection; my $last_path = ( $sel->get_selected_rows )[-1]; # add clip object to task my @i_list = defined $last_path ? $last_path->get_indices : (); my $obj = $self->clip->{CLASS}->loadHash( $self->clip ); my $path; if ( $obj->does('Gdraw2::Element::RoleCairoElement') ) { if ( @i_list == 3 ) { $i_list[2]++; $path = $task->add_element_at( $obj, @i_list ); } elsif ( @i_list == 2 ) { $path = $task->append_element( $obj, @i_list ); } else { $self->showWarn( "Select a track to append element,\nor a element to add after!" ); return; } } elsif ( $obj->isa('Gdraw2::CairoTrack') ) { if ( @i_list >= 2 ) { $i_list[1]++; $path = $task->add_track_at( $obj, @i_list[ 0, 1 ] ); } elsif ( @i_list == 1 ) { $path = $task->append_track( $obj, $i_list[0] ); } else { $self->showWarn( "Select a group to append track,\nor a track to add after!"); return; } } elsif ( $obj->isa('Gdraw2::CairoTrackGroup') ) { if ( @i_list >= 1 ) { $i_list[0]++; $path = $task->add_group_at( $obj, $i_list[0] ); } else { $path = $task->append_group($obj); } } else { confess "invalid clip object: \n", Dump( $self->clip ); } # save undo/redo my $act = Gdraw2Gtk::Act::Add->new( task => $task, object => $obj, indices => [ $path->get_indices ] ); $task->add_act($act); # update task $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } sub on_UndoAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $re = $task->undo; # update UI if ($re) { $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } sub on_RedoAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; my $re = $task->redo; # update task if ($re) { $task->saved(0); $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } } sub on_ForceRefreshAction_activate { my $self = shift; my $task = $self->getCurrentTask; return if !defined $task; say "redo typesetting"; $task->page->unarrangeAll; $task->page->arrangeAll; $task->page->draw; $task->on_area_expose( undef, $task->get_preview_area ); } sub _notebook_modify { my $self = shift; my $builder = $self->uiBuilder; my $pages = $builder->get_object('AppMW_Pages'); my $state = $pages->get_n_pages > 0 ? TRUE : FALSE; $builder->get_object('AddElementAction')->set_sensitive($state); $builder->get_object('AddGroupAction')->set_sensitive($state); $builder->get_object('AddTrackAction')->set_sensitive($state); $builder->get_object('DeleteObjAction')->set_sensitive($state); $builder->get_object('EditObjAction')->set_sensitive($state); $builder->get_object('MoveDownAction')->set_sensitive($state); $builder->get_object('MoveUpAction')->set_sensitive($state); $builder->get_object('SaveFileAction')->set_sensitive($state); $builder->get_object('SaveAsAction')->set_sensitive($state); $builder->get_object('ImportSeqAction')->set_sensitive($state); $builder->get_object('ImportBlastAction')->set_sensitive($state); $builder->get_object('ExportFileAction')->set_sensitive($state); $builder->get_object('CloseFileAction')->set_sensitive($state); $builder->get_object('ConfigPageAction')->set_sensitive($state); $builder->get_object('ForceRefreshAction')->set_sensitive($state); $builder->get_object('CutAction')->set_sensitive($state); $builder->get_object('CopyAction')->set_sensitive($state); $builder->get_object('PasteAction')->set_sensitive($state); $builder->get_object('RedoAction')->set_sensitive($state); $builder->get_object('UndoAction')->set_sensitive($state); return TRUE; } sub on_AppMW_Pages_page_added { my $self = shift; return $self->_notebook_modify; } sub on_AppMW_Pages_page_removed { my $self = shift; return $self->_notebook_modify; } sub dbg_cb { my ( undef, $task ) = @_; my $data = $task->page->toHash; print Dump $data; } sub dbg_clip_cb { #print Dump $clip_obj; } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/TrackEditor.pm000444001750001750 421112001671021 20243 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::TrackEditor; use strict; use feature qw/say switch/; use Moose; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use constant { CLASS_BLOCK => 'Gdraw2::Element::CairoBlock', CLASS_TAGSET => 'Gdraw2::Element::CairoTagset', CLASS_MAPPING => 'Gdraw2::Element::CairoMapping', CLASS_RULER => 'Gdraw2::Element::CairoRuler', CLASS_CURVE => 'Gdraw2::Element::CairoDataCurve', }; has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { Gtk2::Builder->new } ); sub BUILD { my $self = shift; my $file_ui = dist_file( 'Gdraw2', 'TrackEditor.glade' ); $self->uiBuilder->add_from_file($file_ui); } sub run { my ( $self, $params ) = @_; my $builder = $self->uiBuilder; my $editor = $builder->get_object('TrackEditor'); $editor->signal_connect( 'delete-event', sub { $editor->response(1); } ); # get widgets my $name_entry = $builder->get_object('TrackEditor_NameEntry'); my $start_spin = $builder->get_object('TrackEditor_StartSpin'); my $end_spin = $builder->get_object('TrackEditor_EndSpin'); my $ele_width_spin = $builder->get_object('TrackEditor_EleWidthSpin'); my $guide_line_check = $builder->get_object('TrackEditor_GuideLineCheck'); # set track properties to UI $name_entry->set_text( $params->{displayName} ); $start_spin->set_value( $params->{start} ); $end_spin->set_value( $params->{end} ); $ele_width_spin->set_value( $params->{elementWidth} ); if ( $params->{showGuideLine} ) { $guide_line_check->set_active(TRUE); } else { $guide_line_check->set_active(FALSE); } # run dialog my $re = $editor->run; # apply if accepted if ( $re == 0 ) { $params->{displayName} = $name_entry->get_text; $params->{start} = $start_spin->get_value; $params->{end} = $end_spin->get_value; $params->{elementWidth} = $ele_width_spin->get_value; $params->{showGuideLine} = $guide_line_check->get_active ? 1 : 0; } $editor->hide; return $re; } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/Act.pm000444001750001750 741312001671021 16546 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::Act; use Moose; has task => ( is => 'ro', isa => 'Gdraw2Gtk::Task', weak_ref => 1, required => 1 ); sub redo { confess "override this function"; } sub undo { confess "override this function"; } package Gdraw2Gtk::Act::Indexed; use Moose; extends 'Gdraw2Gtk::Act'; has indices => ( is => 'rw', isa => 'ArrayRef[Int]', required => 1 ); package Gdraw2Gtk::Act::Move; use Moose; use Moose::Util::TypeConstraints; extends 'Gdraw2Gtk::Act::Indexed'; has direction => ( is => 'rw', isa => enum( [ 'up', 'down' ] ), required => 1 ); override redo => sub { my $self = shift; my @indices = @{ $self->indices }; $self->task->move_at( @indices, $self->direction ); }; override undo => sub { my $self = shift; my @indices_u = @{ $self->indices }; my $direction_u; if ( $self->direction eq 'up' ) { $direction_u = 'down'; $indices_u[-1]--; } else { $direction_u = 'up'; $indices_u[-1]++; } $self->task->move_at( @indices_u, $direction_u ); }; package Gdraw2Gtk::Act::Config; use Moose; extends 'Gdraw2Gtk::Act::Indexed'; has 'params_old' => ( is => 'rw', isa => 'HashRef', required => 1 ); has 'params_new' => ( is => 'rw', isa => 'HashRef', required => 1 ); sub _apply { my ( $self, $params ) = @_; my @indices = @{ $self->indices }; my $obj = $self->task->get_object_at(@indices); $obj->applyParams($params); } override redo => sub { my $self = shift; $self->_apply( $self->params_new ); }; override undo => sub { my $self = shift; $self->_apply( $self->params_old ); }; package Gdraw2Gtk::Act::Add; use Moose; use Moose::Util::TypeConstraints; extends 'Gdraw2Gtk::Act::Indexed'; has 'object' => ( is => 'rw', required => 1 ); override redo => sub { my $self = shift; my @indices = @{ $self->indices }; my $obj = $self->object; if ( @indices == 3 ) { $self->task->add_element_at( $obj, @indices ); } elsif ( @indices == 2 ) { $self->task->add_track_at( $obj, @indices ); } elsif ( @indices == 1 ) { $self->task->add_group_at( $obj, @indices ); } else { confess "invalid indices: @indices"; } }; override undo => sub { my $self = shift; my @indices = @{ $self->indices }; if ( @indices == 3 ) { $self->task->remove_element_at(@indices); } elsif ( @indices == 2 ) { $self->task->remove_track_at(@indices); } elsif ( @indices == 1 ) { $self->task->remove_group_at(@indices); } else { confess "invalid indices: @indices"; } }; package Gdraw2Gtk::Act::Remove; use Moose; use Moose::Util::TypeConstraints; extends 'Gdraw2Gtk::Act::Indexed'; has 'object' => ( is => 'rw', required => 1 ); override redo => sub { my $self = shift; my $task = $self->task; my @indices = @{ $self->indices }; if ( @indices == 3 ) { $task->remove_element_at(@indices); } elsif ( @indices == 2 ) { $task->remove_track_at(@indices); } elsif ( @indices == 1 ) { $task->remove_group_at(@indices); } else { confess "invalid indices: @indices"; } }; override undo => sub { my $self = shift; my $obj = $self->object; my $task = $self->task; my @indices = @{ $self->indices }; if ( @indices == 3 ) { $self->task->add_element_at( $obj, @indices ); } elsif ( @indices == 2 ) { $self->task->add_track_at( $obj, @indices ); } elsif ( @indices == 1 ) { $self->task->add_group_at( $obj, @indices ); } else { confess "invalid indices: @indices"; } }; 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/ElementEditor.pm000444001750001750 2715612001671021 20625 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::ElementEditor; use strict; use feature qw/say switch/; use Moose; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use constant { CLASS_BLOCK => 'Gdraw2::Element::CairoBlock', CLASS_TAGSET => 'Gdraw2::Element::CairoTagset', CLASS_MAPPING => 'Gdraw2::Element::CairoMapping', CLASS_RULER => 'Gdraw2::Element::CairoRuler', CLASS_CURVE => 'Gdraw2::Element::CairoDataCurve', }; has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { Gtk2::Builder->new } ); sub BUILD { my $self = shift; my $builder = $self->uiBuilder; my $file_ui = dist_file( 'Gdraw2', 'EleEditor.glade' ); $builder->add_from_file($file_ui); # # connect signals # my $name_entry = $builder->get_object('EleEditor_NameEntry'); my $name_check = $builder->get_object('EleEditor_NameCheck'); my $name_check_change = sub { $name_entry->set_sensitive( $name_check->get_active ? TRUE : FALSE ); }; &$name_check_change(); $name_check->signal_connect( 'toggled', $name_check_change ); } sub run { my ( $self, $params ) = @_; my $builder = $self->uiBuilder; my $editor = $builder->get_object('EleEditor'); my $content_box = $builder->get_object('EleEditor_ContentBox'); given ( $params->{CLASS} ) { when (CLASS_RULER) { $content_box->pack_start( $builder->get_object('RulerComp'), TRUE, TRUE, 0 ); } when (CLASS_MAPPING) { $content_box->pack_start( $builder->get_object('MappingComp'), TRUE, TRUE, 0 ); } when (CLASS_CURVE) { $content_box->pack_start( $builder->get_object('CurveComp'), TRUE, TRUE, 0 ); } } $editor->signal_connect( 'delete-event', sub { $editor->response(1); } ); # get widgets from builder my $name_entry = $builder->get_object('EleEditor_NameEntry'); my $name_check = $builder->get_object('EleEditor_NameCheck'); my $desc_entry = $builder->get_object('EleEditor_DescEntry'); my $pos_entry = $builder->get_object('EleEditor_PosEntry'); my $strand_fwd_rbut = $builder->get_object('EleStrand_FwdRadio'); my $strand_rev_rbut = $builder->get_object('EleStrand_RevRadio'); my $strand_non_rbut = $builder->get_object('EleStrand_NonRadio'); my $stroke_color_but = $builder->get_object('EleEditor_StrokeColorBut'); my $fill_color_but = $builder->get_object('EleEditor_FillColorBut'); my $text_color_but = $builder->get_object('EleEditor_TextColorBut'); my $ele_anchor_left_rbut = $builder->get_object('EleAnchor_LeftRadio'); my $ele_anchor_center_rbut = $builder->get_object('EleAnchor_CenterRadio'); my $ele_anchor_right_rbut = $builder->get_object('EleAnchor_RightRadio'); my $name_anchor_left_rbut = $builder->get_object('NameAnchor_LeftRadio'); my $name_anchor_center_rbut = $builder->get_object('NameAnchor_CenterRadio'); my $name_anchor_right_rbut = $builder->get_object('NameAnchor_RightRadio'); my $layer_top_rbut = $builder->get_object('EleLayer_TopRadio'); my $layer_default_rbut = $builder->get_object('EleLayer_DefaultRadio'); my $layer_bottom_rbut = $builder->get_object('EleLayer_BottomRadio'); # set element properties to widgets $name_entry->set_text( $params->{displayName} ); if ( $params->{showName} ) { $name_check->set_active(TRUE) } else { $name_check->set_active(FALSE) } $desc_entry->set_text( $params->{desc} ); $pos_entry->set_text( join( ', ', @{ $params->{position} } ) ); given ( $params->{strand} ) { when (-1) { $strand_rev_rbut->set_active(TRUE) } when (0) { $strand_non_rbut->set_active(TRUE) } when (1) { $strand_fwd_rbut->set_active(TRUE) } default { confess 'element <' . $params->{displayName} . "> has invalid element strand: " . $params->{strand}; } } $stroke_color_but->set_color( Gtk2::Gdk::Color->new( map { int 65535 * $_ } @{ $params->{strokeColor} }{qw/red green blue/} ) ); $stroke_color_but->set_alpha( int 65535 * $params->{strokeColor}{alpha} ); $fill_color_but->set_color( Gtk2::Gdk::Color->new( map { int 65535 * $_ } @{ $params->{fillColor} }{qw/red green blue/} ) ); $fill_color_but->set_alpha( int 65535 * $params->{fillColor}{alpha} ); $text_color_but->set_color( Gtk2::Gdk::Color->new( map { int 65535 * $_ } @{ $params->{textColor} }{qw/red green blue/} ) ); $fill_color_but->set_alpha( int 65535 * $params->{textColor}{alpha} ); given ( $params->{elementAnchor} ) { when ('left') { $ele_anchor_left_rbut->set_active(TRUE) } when ('center') { $ele_anchor_center_rbut->set_active(TRUE) } when ('right') { $ele_anchor_right_rbut->set_active(TRUE) } } given ( $params->{nameAnchor} ) { when ('left') { $name_anchor_left_rbut->set_active(TRUE) } when ('center') { $name_anchor_center_rbut->set_active(TRUE) } when ('right') { $name_anchor_right_rbut->set_active(TRUE) } } given ( $params->{layer} ) { when ('top') { $layer_top_rbut->set_active(TRUE) } when ('default') { $layer_default_rbut->set_active(TRUE) } when ('bottom') { $layer_bottom_rbut->set_active(TRUE) } } # special element, add special dialog components if ( $params->{CLASS} eq CLASS_RULER ) { $builder->get_object('RulerComp_TickSizeSpin') ->set_value( $params->{tickSize} ); $builder->get_object('RulerComp_GridLengthSpin') ->set_value( $params->{gridLength} ); $builder->get_object('RulerComp_IntTickCheck') ->set_active( $params->{integralTick} ? TRUE : FALSE ); $builder->get_object('RulerComp_AbbrevTickCheck') ->set_active( $params->{abbrevTickText} ? TRUE : FALSE ); } if ( $params->{CLASS} eq CLASS_MAPPING ) { $builder->get_object('MappingComp_ExtGroupSpin') ->set_value( $params->{extGroupIndex} ); $builder->get_object('MappingComp_ExtTrackSpin') ->set_value( $params->{extTrackIndex} ); $builder->get_object('MappingComp_ExtStartSpin') ->set_value( $params->{extStart} ); $builder->get_object('MappingComp_ExtEndSpin') ->set_value( $params->{extEnd} ); } if ( $params->{CLASS} eq CLASS_CURVE ) { $builder->get_object('CurveComp_FillColorBut')->set_color( Gtk2::Gdk::Color->new( map { int 65535 * $_ } @{ $params->{fillColor2} }{qw/red green blue/} ) ); $builder->get_object('CurveComp_FillColorBut')->set_alpha( int 65535 * $params->{fillColor2}{alpha} ); $builder->get_object('CurveComp_DataEntry') ->set_text( join ",", @{ $params->{data} } ); $builder->get_object('CurveComp_HCenterSpin') ->set_value( $params->{middleLine} ); } # # run dialog # my $re = $editor->run; # # apply changes # say "config element: get response $re"; if ( $re == 0 ) { $params->{displayName} = $name_entry->get_text; $params->{showName} = $name_check->get_active ? 1 : 0; $params->{desc} = $desc_entry->get_text; my @pos_nums = split( /[^\-0-9]+/, $pos_entry->get_text ); if ( @pos_nums < 1 ) { warn "invalid position list: (@pos_nums), set to (1,1)"; @pos_nums = ( 1, 1 ); } @{ $params->{position} } = @pos_nums; if ( $strand_rev_rbut->get_active ) { $params->{strand} = -1 } elsif ( $strand_non_rbut->get_active ) { $params->{strand} = 0 } elsif ( $strand_fwd_rbut->get_active ) { $params->{strand} = 1 } my $color_stroke = $stroke_color_but->get_color; $params->{strokeColor}{red} = $color_stroke->red / 65535; $params->{strokeColor}{green} = $color_stroke->green / 65535; $params->{strokeColor}{blue} = $color_stroke->blue / 65535; $params->{strokeColor}{alpha} = $stroke_color_but->get_alpha / 65535; my $color_fill = $fill_color_but->get_color; $params->{fillColor}{red} = $color_fill->red / 65535; $params->{fillColor}{green} = $color_fill->green / 65535; $params->{fillColor}{blue} = $color_fill->blue / 65535; $params->{fillColor}{alpha} = $fill_color_but->get_alpha / 65535; my $color_text = $text_color_but->get_color; $params->{textColor}{red} = $color_text->red / 65535; $params->{textColor}{green} = $color_text->green / 65535; $params->{textColor}{blue} = $color_text->blue / 65535; $params->{textColor}{alpha} = $text_color_but->get_alpha / 65535; if ( $ele_anchor_left_rbut->get_active ) { $params->{elementAnchor} = 'left'; } elsif ( $ele_anchor_center_rbut->get_active ) { $params->{elementAnchor} = 'center'; } elsif ( $ele_anchor_right_rbut->get_active ) { $params->{elementAnchor} = 'right'; } if ( $name_anchor_left_rbut->get_active ) { $params->{nameAnchor} = 'left'; } elsif ( $name_anchor_center_rbut->get_active ) { $params->{nameAnchor} = 'center'; } elsif ( $name_anchor_right_rbut->get_active ) { $params->{nameAnchor} = 'right'; } if ( $layer_top_rbut->get_active ) { $params->{layer} = 'top'; } elsif ( $layer_default_rbut->get_active ) { $params->{layer} = 'default'; } elsif ( $layer_bottom_rbut->get_active ) { $params->{layer} = 'bottom'; } if ( $params->{CLASS} eq CLASS_RULER ) { $params->{tickSize} = $builder->get_object('RulerComp_TickSizeSpin')->get_value; $params->{gridLength} = $builder->get_object('RulerComp_GridLengthSpin')->get_value; $params->{integralTick} = $builder->get_object('RulerComp_IntTickCheck')->get_active ? 1 : 0; $params->{abbrevTickText} = $builder->get_object('RulerComp_AbbrevTickCheck')->get_active ? 1 : 0; } if ( $params->{CLASS} eq CLASS_MAPPING ) { $params->{extGroupIndex} = $builder->get_object('MappingComp_ExtGroupSpin')->get_value; $params->{extTrackIndex} = $builder->get_object('MappingComp_ExtTrackSpin')->get_value; $params->{extStart} = $builder->get_object('MappingComp_ExtStartSpin')->get_value; $params->{extEnd} = $builder->get_object('MappingComp_ExtEndSpin')->get_value; } if ( $params->{CLASS} eq CLASS_CURVE ) { @{ $params->{data} } = split /[^\-0-9]+/, $builder->get_object('CurveComp_DataEntry')->get_text; $params->{middleLine} = $builder->get_object('CurveComp_HCenterSpin')->get_value; my $color_fill_2 = $builder->get_object('CurveComp_FillColorBut')->get_color; $params->{fillColor2}{red} = $color_fill_2->red / 65535; $params->{fillColor2}{green} = $color_fill_2->green / 65535; $params->{fillColor2}{blue} = $color_fill_2->blue / 65535; $params->{fillColor2}{alpha} = $builder->get_object('CurveComp_FillColorBut')->get_alpha / 65535; } } $editor->hide; return $re; } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/EleTypeWizard.pm000444001750001750 345412001671021 20570 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::EleTypeWizard; use strict; use feature qw/say switch/; use Moose; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use constant { CLASS_BLOCK => 'Gdraw2::Element::CairoBlock', CLASS_TAGSET => 'Gdraw2::Element::CairoTagset', CLASS_MAPPING => 'Gdraw2::Element::CairoMapping', CLASS_RULER => 'Gdraw2::Element::CairoRuler', CLASS_CURVE => 'Gdraw2::Element::CairoDataCurve', }; has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { Gtk2::Builder->new } ); sub BUILD { my $self = shift; my $builder = $self->uiBuilder; my $file_ui = dist_file( 'Gdraw2', 'EleTypeWizard.glade' ); $builder->add_from_file($file_ui); my $wizard = $builder->get_object('EleTypeWizard'); $wizard->signal_connect( 'delete-event', sub { $wizard->response(1); } ); } sub run { my $self = shift; my $builder = $self->uiBuilder; my $wizard = $builder->get_object('EleTypeWizard'); my $re = $wizard->run; $wizard->hide; if ( $re == 0 ) { if ($builder->get_object('EleType_BlockRadio')->get_active) { return CLASS_BLOCK; } if ($builder->get_object('EleType_TagsetRadio')->get_active) { return CLASS_TAGSET; } if ($builder->get_object('EleType_PairRadio')->get_active) { return undef; } if ($builder->get_object('EleType_MappingRadio')->get_active) { return CLASS_MAPPING; } if ($builder->get_object('EleType_DataCurveRadio')->get_active) { return CLASS_CURVE; } if ($builder->get_object('EleType_RulerRadio')->get_active) { return CLASS_RULER; } } else { return undef; } } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/Task.pm000555001750001750 7245012001671021 16767 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::Task; use common::sense; use Cairo; use Carp qw/cluck confess/; use File::Basename; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gdraw2::Util qw/calc_gc_content calc_gc_skew calc_tick_size/; use Gdraw2Gtk::Act; use Moose; use YAML::Syck qw/Load Dump LoadFile DumpFile/; use constant { COL_NAME => 0, COL_TYPE => 1, COL_LOCATION => 2, COL_STROKE => 3, COL_FILL => 4, COL_COLOR_SET => 5 }; use constant { FILE_GLADE => 'Gdraw2UI.glade' }; use constant { MAX_UNDO_REDO => 20 }; has app => ( is => 'ro', isa => 'Gdraw2Gtk::App', weak_ref => 1, required => 1 ); has id => ( is => 'rw', isa => 'Str', required => 1 ); has file => ( is => 'rw', isa => 'Str', default => '' ); has page => ( is => 'rw', isa => 'Gdraw2::AbstractTrackPage', required => 1 ); my $unsave_prefix = '*'; has saved => ( is => 'rw', isa => 'Bool', default => 0, trigger => sub { my $self = shift; my $label = $self->label; my $label_text = $label->get_text; if ( $self->saved ) { $label_text =~ s/^\Q$unsave_prefix//; } else { $label_text = $unsave_prefix . $label_text if !( $label_text =~ /^\Q$unsave_prefix/ ); } $label->set_text($label_text); } ); has uiBuilder => ( is => 'rw', isa => 'Gtk2::Builder', default => sub { return Gtk2::Builder->new } ); has label => ( is => 'rw', isa => 'Object', required => 1 ); has undo_list => ( is => 'rw', isa => 'ArrayRef[Gdraw2Gtk::Act]', default => sub { return [] } ); has redo_list => ( is => 'rw', isa => 'ArrayRef[Gdraw2Gtk::Act]', default => sub { return [] } ); sub BUILD { my $self = shift; my $builder = $self->uiBuilder; # load UI resources my $file_ui_mw = dist_file( 'Gdraw2', 'Gdraw2UI.glade' ); $builder->add_objects_from_file( $file_ui_mw, qw/PageComp PageTreeModel AddObjMenu AddGroupAction AddTrackAction AddElementAction DeleteObjAction EditObjAction MoveUpAction MoveDownAction/ ); # bind popup menu my $menu_add = $builder->get_object('AddObjMenu'); $builder->get_object('PageComp_AddBut')->set_menu($menu_add); # setup treeview my $col_name = $builder->get_object('PageTree_NameCol'); my $col_loc = $builder->get_object('PageTree_LocationCol'); my $col_stroke = $builder->get_object('PageTree_StrokeColorCol'); my $col_fill = $builder->get_object('PageTree_FillColorCol'); my $r_name = Gtk2::CellRendererText->new; $col_name->pack_start( $r_name, TRUE ); $col_name->add_attribute( $r_name, 'text', COL_NAME ); my $r_loc = Gtk2::CellRendererText->new; $col_loc->pack_start( $r_loc, TRUE ); $col_loc->add_attribute( $r_loc, 'text', COL_LOCATION ); my $r_stroke = Gtk2::CellRendererText->new; $col_stroke->pack_start( $r_stroke, TRUE ); $col_stroke->add_attribute( $r_stroke, 'cell-background', COL_STROKE ); $col_stroke->add_attribute( $r_stroke, 'cell-background-set', COL_COLOR_SET ); my $r_fill = Gtk2::CellRendererText->new; $col_fill->pack_start( $r_fill, TRUE ); $col_fill->add_attribute( $r_fill, 'cell-background', COL_FILL ); $col_fill->add_attribute( $r_fill, 'cell-background-set', COL_COLOR_SET ); # update treeview $self->rebuild_treeview; } sub get_tree_view { my $self = shift; return $self->uiBuilder->get_object('PageComp_PageTree'); } sub get_preview_area { my $self = shift; return $self->uiBuilder->get_object('PageComp_PreviewArea'); } sub get_tree_model { my $self = shift; return $self->uiBuilder->get_object('PageTreeModel'); } sub get_object_at { my ( $self, @indices ) = @_; if ( @indices == 3 ) { return $self->page->getChildAt( $indices[0] )->getChildAt( $indices[1] ) ->getChildAt( $indices[2] ); } elsif ( @indices == 2 ) { return $self->page->getChildAt( $indices[0] ) ->getChildAt( $indices[1] ); } elsif ( @indices == 1 ) { return $self->page->getChildAt( $indices[0] ); } elsif ( @indices == 0 ) { return $self->page; } } sub move_at { my ( $self, @args ) = @_; my $direction = pop @args; my @i_to = @args; if ( $direction eq 'up' ) { $i_to[-1]--; } elsif ( $direction eq 'down' ) { $i_to[-1]++; } else { confess "invalid direction: '$direction'"; } # get parent my $page = $self->page; my $parent; if ( @args == 3 ) { $parent = $page->getChildAt( $args[0] )->getChildAt( $args[1] ); } elsif ( @args == 2 ) { $parent = $page->getChildAt( $args[0] ); } elsif ( @args == 1 ) { $parent = $page; } else { confess "invalid arguments: @args"; } # validate object to move if ( $direction eq 'up' and $args[-1] == 0 ) { confess "attempt to move up first object"; } if ( $direction eq 'down' and $args[-1] == $parent->numChildren - 1 ) { confess "attempt to move down last object at $args[-1]"; } # modify the Gdraw2 tree my $obj = $parent->removeChildAt( $args[-1] ); $parent->addChildAt( $obj, $i_to[-1] ); # modify the table my $model = $self->uiBuilder->get_object('PageTreeModel'); my $iter_obj = $model->get_iter_from_string( join ':', @args ); my $iter_to = $model->get_iter_from_string( join ':', @i_to ); $model->swap( $iter_obj, $iter_to ); # move cursor my $path = $model->get_path($iter_obj); my $table = $self->uiBuilder->get_object('PageComp_PageTree'); $table->set_cursor($path); } sub save_task { my $self = shift; my $file = shift; # save $file .= '.yaml' if !$file =~ /\.yaml$/; my $page = $self->page; DumpFile( $file, $page->toHash ); # properties $self->file($file); $self->label->set_text( basename($file) ); $self->saved(1); } sub importRichSeq { my ( $self, $config, $IN ) = @_; # generate feature-track mapping my @track_names; my %feature_map ; # feature => [ track_i, ele_type, [tags], [stroke], [fill] ] $config->getTrackTemplates( \@track_names, \%feature_map ); # traverse input my @groups; while (1) { # get seq my $seq_obj; eval { $seq_obj = $IN->next_seq }; if ($@) { $self->app->showError($@); return; } last if !$seq_obj; my $len = $seq_obj->length; # check if we import parital my $start; my $end; if ( $config->importPartial ) { ( $start, $end ) = sort { $a <=> $b } ( $config->partialStart, $config->partialEnd ); $end = $len if $len < $end; } else { $start = 1; $end = $len; } # create group my $group = Gdraw2::CairoTrackGroup->new( displayName => $seq_obj->desc, start => $start, end => $end ); push @groups, $group; # create element tracks foreach my $track_name (@track_names) { my $track = Gdraw2::CairoTrack->new( start => $start, end => $end, displayName => $track_name ); $group->addChild($track); } # traverse through features foreach my $feat ( $seq_obj->get_SeqFeatures ) { my $type = $feat->primary_tag; next if !exists $feature_map{$type}; next if ( $feat->end < $start ) or ( $end < $feat->start ); foreach my $curr ( @{ $feature_map{$type} } ) { my ( $track_i, $ele_type, $tags, $stroke, $fill ) = @$curr; my $track = $group->getChildAt($track_i); # generate element display name my @ele_name_values; foreach my $tag (@$tags) { next if !$feat->has_tag($tag); push @ele_name_values, $feat->get_tag_values($tag); } my $ele_name = join ' ', @ele_name_values; # generate element my $ele; if ( $ele_type eq 'block' ) { $ele = Gdraw2::Element::CairoBlock->new( displayName => $ele_name, position => [ $feat->start, $feat->end ], strand => $feat->strand, strokeColor => Gdraw2::Util::RGBAColor->new(@$stroke), fillColor => Gdraw2::Util::RGBAColor->new(@$fill) ); } elsif ( $ele_type eq 'tagset' ) { $ele = Gdraw2::Element::CairoBlock->new( displayName => $ele_name, position => [ int( ( $feat->start + $feat->end ) / 2 ) ], strokeColor => Gdraw2::Util::RGBAColor->new(@$stroke), fillColor => Gdraw2::Util::RGBAColor->new(@$fill) ); } else { confess "invalid element type: '$ele_type'"; } # append element to track $track->addChild($ele); } } # draw ruler if ( $config->drawRuler ) { my $track_ruler = Gdraw2::CairoTrack->new( start => $start, end => $end, showGuideLine => 0, displayName => 'ruler track' ); $group->addChildAt( $track_ruler, 0 ); my $ruler = Gdraw2::Element::CairoRuler->new( displayName => 'ruler', position => [ $start, $end ], gridLength => $config->rulerTickInterval, ); $track_ruler->addChild($ruler); } # draw GC content if ( $config->drawGC ) { my $track_gc = Gdraw2::CairoTrack->new( displayName => 'GC content track', start => $start, end => $end, showGuideLine => 0 ); $group->addChild($track_gc); my @data; my $gc_start; my $gc_end; for ( $gc_start = $start ; $gc_start < $end ; $gc_start += $config->gcWindowStep ) { $gc_end = $gc_start + $config->gcWindowSize - 1; last if $gc_end > $end; push @data, calc_gc_content( $seq_obj->subseq( $gc_start, $gc_end ) ); } $track_gc->addChild( Gdraw2::Element::CairoDataCurve->new( displayName => 'GC content', position => [ $start, $gc_end ], middleLine => 0.5, data => [@data] ) ); } # draw GC skew if ( $config->drawSkew ) { my $track_skew = Gdraw2::CairoTrack->new( displayName => 'GC skew track', start => 1, end => $len, showGuideLine => 0 ); $group->addChild($track_skew); my @data; my $skew_start; my $skew_end; for ( $skew_start = $start ; $skew_start < $end ; $skew_start += $config->skewWindowStep ) { $skew_end = $skew_start + $config->skewWindowSize - 1; last if $skew_end > $end; push @data, calc_gc_skew( $seq_obj->subseq( $skew_start, $skew_end ) ); } $track_skew->addChild( Gdraw2::Element::CairoDataCurve->new( displayName => 'GC skew', position => [ $start, $skew_end ], middleLine => 0, data => [@data] ) ); } } # add group to page foreach my $group (@groups) { my $path = $self->append_group($group); my $act = Gdraw2Gtk::Act::Add->new( object => $group, task => $self, indices => [ $path->get_indices ] ); $self->add_act($act); } # redraw my $builder_task = $self->uiBuilder; my $area = $builder_task->get_object('PageComp_PreviewArea'); $self->page->draw; $self->on_area_expose( undef, $area ); } sub importBlast { my ( $self, $config, $IN ) = @_; my $do_evalue = $config->doFiltEValue; my $do_score = $config->doFiltBitScore; my $cut_evalue = $config->eValueCutoff; my $cut_score = $config->bitScoreCutoff; my $stack_hsp = $config->stackHSPs; my @groups; while ( my $result = $IN->next_result ) { # # traverse hits # my @tracks; my @elems; while ( my $hit = $result->next_hit ) { my @hit_elems; while ( my $hsp = $hit->next_hsp ) { # create Block from HSP my $score = $hsp->bits; my $evalue = $hsp->evalue; next if $do_score and $score < $cut_score; next if $do_evalue and $evalue > $cut_evalue; my $start = $hsp->start('query'); my $end = $hsp->end('query'); my $strand = $hsp->strand('query') * $hsp->strand('hit'); my $name = $hsp->start('hit') . '-' . $hsp->end('hit'); $name = $hit->name .': '.$name if $stack_hsp; my @color; if ( $score < 40 ) { @color = ( 0, 0, 0, 1 ) } elsif ( $score < 50 ) { @color = ( 0, 0, 1, 1 ) } elsif ( $score < 80 ) { @color = ( 0, 1, 0, 1 ) } elsif ( $score < 200 ) { @color = ( 1, 0, 1, 1 ) } else { @color = ( 1, 0, 0, 1 ) } push @hit_elems, Gdraw2::Element::CairoBlock->new( displayName => $name, showName => 0, position => [ $start, $end ], strand => $strand, strokeColor => Gdraw2::Util::RGBAColor->new(@color), fillColor => Gdraw2::Util::RGBAColor->new(@color) ); } if ( @hit_elems > 0 ) { if ($stack_hsp) { push @elems, @hit_elems; } else { my $track = Gdraw2::CairoTrack->new( displayName => $hit->name, start => 1, end => $result->query_length, elementWidth => 5 ); push @tracks, $track; $track->addChild($_) foreach @hit_elems; } } } # # if non-empty, create the group and ruler # my $group; if ( ( $stack_hsp and @elems > 0 ) or ( !$stack_hsp and @tracks > 0 ) ) { # group $group = Gdraw2::CairoTrackGroup->new( displayName => $result->query_name, desc => $result->query_description, trackDistance => 0, start => 1, end => $result->query_length ); push @groups, $group; # ruler my $track_ruler = Gdraw2::CairoTrack->new( displayName => 'ruler track', start => 1, end => $result->query_length, showGuideLine => 0 ); $group->addChild($track_ruler); $track_ruler->addChild( Gdraw2::Element::CairoRuler->new( displayName => 'ruler', position => [ 1, $result->query_length ], gridLength => calc_tick_size( $result->query_length ) ) ); } # # if non-empty, add contents to group # if ( defined $group ) { if ($stack_hsp) { my $track_content = Gdraw2::CairoTrack->new( displayName => 'HSPs track', start => 1, elementWidth => 5, end => $result->query_length, showGuideLine => 0 ); $group->addChild($track_content); $track_content->addChild($_) foreach @elems; } else { $group->addChild($_) foreach @tracks; } } } # add group to page foreach my $group (@groups) { my $path = $self->append_group($group); my $act = Gdraw2Gtk::Act::Add->new( object => $group, task => $self, indices => [ $path->get_indices ] ); $self->add_act($act); } # redraw my $builder_task = $self->uiBuilder; my $area = $builder_task->get_object('PageComp_PreviewArea'); $self->page->draw; $self->on_area_expose( undef, $area ); } sub export { my ($self,$file,$format) = @_; $file .= ".$format" if $file !~ /\.$format$/; say "export to '$file' in $format format"; my $page = $self->page; # store old context my $cr_old = $page->cairoContext; # create output surface my $surface_out; if ($format eq 'png') { $surface_out = Cairo::ImageSurface->create( 'argb32', $page->width, $page->height ); } elsif ($format eq 'svg') { $surface_out = Cairo::SvgSurface->create( $file, $page->width, $page->height ); } elsif ($format eq 'pdf') { $surface_out = Cairo::PdfSurface->create( $file, $page->width, $page->height ); } elsif ($format eq 'ps') { $surface_out = Cairo::PsSurface->create( $file, $page->width, $page->height ); } # write output my $cr_out = Cairo::Context->create($surface_out); $page->cairoContext($cr_out); $page->draw; $surface_out->write_to_png($file) if $format eq 'png'; # restore old context $page->cairoContext($cr_old); } sub append_group { my $self = shift; my $group = shift; my $page = $self->page; # add group to page $page->addChild($group); # update treeview my $tree_model = $self->get_tree_model; my $iter_group = $tree_model->append(undef); my $path_group = $tree_model->get_path($iter_group); my @grp_i = $path_group->get_indices; $self->update_table_at( $grp_i[0] ); # insert children foreach my $track ( $group->getChildren ) { my $iter_track = $tree_model->append($iter_group); my @i_track = $tree_model->get_path($iter_track)->get_indices; $self->update_table_at(@i_track); foreach my $ele ( $track->getChildren ) { my $iter_ele = $tree_model->append($iter_track); my @i_ele = $tree_model->get_path($iter_ele)->get_indices; $self->update_table_at(@i_ele); } } # select at newly added group my $treeview = $self->get_tree_view; $treeview->expand_to_path($path_group); $treeview->set_cursor($path_group); return $path_group; } sub add_group_at { my $self = shift; my $group = shift; my $grp_i = shift; # add group to page $self->page->addChildAt( $group, $grp_i ); # update treeview my $tree_model = $self->get_tree_model; my $iter_group = $tree_model->insert( undef, $grp_i ); $self->update_table_at($grp_i); # insert children foreach my $track ( $group->getChildren ) { my $iter_track = $tree_model->append($iter_group); my @i_track = $tree_model->get_path($iter_track)->get_indices; $self->update_table_at(@i_track); foreach my $ele ( $track->getChildren ) { my $iter_ele = $tree_model->append($iter_track); my @i_ele = $tree_model->get_path($iter_ele)->get_indices; $self->update_table_at(@i_ele); } } # select at newly added group my $path = $tree_model->get_path($iter_group); my $treeview = $self->get_tree_view; $treeview->expand_to_path($path); $treeview->set_cursor($path); return $path; } sub remove_group { my $self = shift; my $grp = shift; return $self->remove_group_at( $self->page->childIndex($grp) ); } sub remove_group_at { my $self = shift; my $grp_i = shift; # remove group from page my $page = $self->page; my $group = $page->removeChildAt($grp_i); confess "" if !defined $group; # update_ui my $tree_model = $self->get_tree_model; my $iter = $tree_model->get_iter_from_string($grp_i); $tree_model->remove($iter); # return removed return $group; } sub append_track { my $self = shift; my $track = shift; my $grp_index = shift; # get parent my $page = $self->page; my $group = $page->getChildAt($grp_index); # append track to group $group->addChild($track); # get iter pointing to end my $tree_model = $self->get_tree_model; my $iter_group = $tree_model->get_iter_from_string($grp_index); my $iter_track = $tree_model->append($iter_group); # update UI my $path_track = $tree_model->get_path($iter_track); my @i_track = $path_track->get_indices; $self->update_table_at(@i_track); foreach my $ele ( $track->getChildren ) { my $iter_ele = $tree_model->append($iter_track); my @i_ele = $tree_model->get_path($iter_ele)->get_indices; $self->update_table_at(@i_ele); } # select at newly added group my $path = $tree_model->get_path($iter_track); my $treeview = $self->get_tree_view; $treeview->expand_to_path($path); $treeview->set_cursor($path); return $path; } sub add_track_at { my $self = shift; my $track = shift; my $grp_i = shift; my $trk_i = shift; # get parent my $page = $self->page; my $group = $page->getChildAt($grp_i); # add to group $group->addChildAt( $track, $trk_i ); # get iter my $tree_model = $self->get_tree_model; my $iter_group = $tree_model->get_iter_from_string($grp_i); my $iter = $tree_model->insert( $iter_group, $trk_i ); # update treeview $self->update_table_at( $grp_i, $trk_i ); foreach my $ele ( $track->getChildren ) { my $iter_ele = $tree_model->append($iter); my @i_ele = $tree_model->get_path($iter_ele)->get_indices; $self->update_table_at(@i_ele); } # select at newly added group my $path = $tree_model->get_path($iter); my $treeview = $self->get_tree_view; $treeview->expand_to_path($path); $treeview->set_cursor($path); return $path; } sub remove_track_at { my $self = shift; my $grp_i = shift; my $trk_i = shift; # get parent my $page = $self->page; my $grp = $page->getChildAt($grp_i); # remove track from group my $track = $grp->removeChildAt($trk_i); # update UI my $tree_model = $self->get_tree_model; my $iter = $tree_model->get_iter_from_string( join ':', $grp_i, $trk_i ); $tree_model->remove($iter); # return removed return $track; } sub append_element { my $self = shift; my $ele = shift; my $grp_i = shift; my $trk_i = shift; # get parent my $page = $self->page; my $group = $page->getChildAt($grp_i); my $track = $group->getChildAt($trk_i); # add element to track $track->addChild($ele); # get iter pointing to end my $tree_model = $self->get_tree_model; my $iter_track = $tree_model->get_iter_from_string( $grp_i . ':' . $trk_i ); my $iter = $tree_model->append($iter_track); # update UI $self->update_table_at( $grp_i, $trk_i, $track->numChildren - 1 ); # select at newly added group my $path = $tree_model->get_path($iter); my $treeview = $self->get_tree_view; $treeview->expand_to_path($path); $treeview->set_cursor($path); return $path; } sub add_element_at { my ( $self, $ele, $grp_i, $trk_i, $ele_i ) = @_; # get parent my $page = $self->page; my $group = $page->getChildAt($grp_i); my $track = $group->getChildAt($trk_i); # add to parent $track->addChildAt( $ele, $ele_i ); # add to table my $tree_model = $self->get_tree_model; my $iter_track = $tree_model->get_iter_from_string( join ':', $grp_i, $trk_i ); my $iter = $tree_model->insert( $iter_track, $ele_i ); # update UI $self->update_table_at( $grp_i, $trk_i, $ele_i ); # select at newly added group my $path = $tree_model->get_path($iter); my $treeview = $self->get_tree_view; $treeview->expand_to_path($path); $treeview->set_cursor($path); return $path; } sub remove_element_at { my $self = shift; my $grp_i = shift; my $trk_i = shift; my $ele_i = shift; # get parent my $page = $self->page; my $grp = $page->getChildAt($grp_i); my $trk = $grp->getChildAt($trk_i); # remove element my $ele = $trk->removeChildAt($ele_i); # update treeview UI my $tree_model = $self->get_tree_model; my $iter = $tree_model->get_iter_from_string( join ':', $grp_i, $trk_i, $ele_i ); $tree_model->remove($iter); # return deleted return $ele; } sub update_table_at { my ( $self, @i ) = @_; my $tree_model = $self->get_tree_model; my $iter = $tree_model->get_iter_from_string( join ':', @i ); my $page = $self->page; if ( @i == 3 ) { my $ele = $page->getChildAt( $i[0] )->getChildAt( $i[1] )->getChildAt( $i[2] ); $tree_model->set( $iter, COL_NAME, $ele->displayName, COL_LOCATION, $ele->start . '..' . $ele->end, COL_STROKE, $ele->strokeColor->toGdkString8, COL_FILL, $ele->fillColor->toGdkString8, COL_COLOR_SET, TRUE ); } elsif ( @i == 2 ) { my $track = $page->getChildAt( $i[0] )->getChildAt( $i[1] ); $tree_model->set( $iter, COL_NAME, $track->displayName, COL_LOCATION, $track->start . '..' . $track->end, COL_COLOR_SET, FALSE ); } elsif ( @i == 1 ) { my $group = $page->getChildAt( $i[0] ); $tree_model->set( $iter, COL_NAME, $group->displayName, COL_LOCATION, $group->start . '..' . $group->end, COL_COLOR_SET, FALSE ); } else { confess "invalid indices: @i"; } } sub rebuild_treeview { my $self = shift; my $selection_str = shift; # remove everything my $tree_model = $self->get_tree_model; while (1) { my $iter_first = $tree_model->get_iter_first; last if !defined $iter_first; $tree_model->remove($iter_first); } # re-generate everything foreach my $group ( $self->page->getChildren ) { my $group_iter = $tree_model->append(undef); my @group_i = $tree_model->get_path($group_iter)->get_indices; $self->update_table_at(@group_i); foreach my $track ( $group->getChildren ) { my $track_iter = $tree_model->append($group_iter); my @track_i = $tree_model->get_path($track_iter)->get_indices; $self->update_table_at(@track_i); foreach my $ele ( $track->getChildren ) { my $ele_iter = $tree_model->append($track_iter); my @ele_i = $tree_model->get_path($ele_iter)->get_indices; $self->update_table_at(@ele_i); } } } # set cursor if given if ( defined $selection_str and $selection_str ne '' ) { my $path = Gtk2::TreePath->new_from_string($selection_str); my $treeview = $self->get_tree_view; $treeview->expand_to_path($path); $treeview->set_cursor($path); } } sub undo { my $self = shift; my $re = $self->can_undo; return 0 if !$re; my $act = pop @{ $self->undo_list }; $act->undo; push @{ $self->redo_list }, $act; return 1; } sub redo { my $self = shift; return 0 if !$self->can_redo; my $act = pop @{ $self->redo_list }; $act->redo; push @{ $self->undo_list }, $act; return 1; } sub can_undo { my $self = shift; return ( @{ $self->undo_list } > 0 ); } sub can_redo { my $self = shift; return ( @{ $self->redo_list } > 0 ); } sub add_act { my ( $self, $act ) = @_; $self->{redo_list} = []; push @{ $self->undo_list }, $act; } sub on_area_expose { my ( $self, $event, $area ) = @_; my $surface_buffer = $self->page->cairoContext->get_target; my $cr_area = Gtk2::Gdk::Cairo::Context->create( $area->window ); $cr_area->set_source_surface( $surface_buffer, 0, 0 ); $cr_area->paint; } 1; Gdraw2-v0.0.3/lib/Gdraw2Gtk/PageEditor.pm000444001750001750 761512001671021 20066 0ustar00yangxiyangxi000000000000package Gdraw2Gtk::PageEditor; use strict; use feature qw/say switch/; use Moose; use File::ShareDir qw/:ALL/; use Glib qw/TRUE FALSE/; use Gtk2; use constant { CLASS_BLOCK => 'Gdraw2::Element::CairoBlock', CLASS_TAGSET => 'Gdraw2::Element::CairoTagset', CLASS_MAPPING => 'Gdraw2::Element::CairoMapping', CLASS_RULER => 'Gdraw2::Element::CairoRuler', CLASS_CURVE => 'Gdraw2::Element::CairoDataCurve', }; has uiBuilder => ( is => 'ro', isa => 'Gtk2::Builder', default => sub { Gtk2::Builder->new } ); sub BUILD { my $self = shift; my $builder = $self->uiBuilder; my $file_ui = dist_file( 'Gdraw2', 'PageEditor.glade' ); $builder->add_from_file($file_ui); my $linear_rbut = $builder->get_object('PageEditor_LinearRbut'); my $circ_rbut = $builder->get_object('PageEditor_CircularRbut'); my $top_margin_spin = $builder->get_object('PageEditor_TopMarginSpin'); my $init_radius_spin = $builder->get_object('PageEditor_InitRadiusSpin'); my $on_topo_change = sub { my $l_but = shift; if ( $l_but->get_active ) { $top_margin_spin->set_sensitive(TRUE); $init_radius_spin->set_sensitive(FALSE); } else { $top_margin_spin->set_sensitive(FALSE); $init_radius_spin->set_sensitive(TRUE); } }; $linear_rbut->signal_connect( 'toggled', $on_topo_change ); } sub run { my ( $self, $params ) = @_; my $builder = $self->uiBuilder; my $editor = $builder->get_object('PageEditor'); $editor->signal_connect( 'delete-event', sub { $editor->response(1); } ); # get widgets from builder my $width_spin = $builder->get_object('PageEditor_WidthSpin'); my $height_spin = $builder->get_object('PageEditor_HeightSpin'); my $group_dist_spin = $builder->get_object('PageEditor_GroupDistSpin'); my $top_margin_spin = $builder->get_object('PageEditor_TopMarginSpin'); my $init_radius_spin = $builder->get_object('PageEditor_InitRadiusSpin'); my $title_font_entry = $builder->get_object('PageEditor_TitleFontEntry'); my $title_size_spin = $builder->get_object('PageEditor_TitleSizeSpin'); my $text_font_entry = $builder->get_object('PageEditor_TextFontEntry'); my $text_size_spin = $builder->get_object('PageEditor_TextSizeSpin'); my $linear_rbut = $builder->get_object('PageEditor_LinearRbut'); my $circ_rbut = $builder->get_object('PageEditor_CircularRbut'); # set page attributes to dialog UI $width_spin->set_value( $params->{width} ); $height_spin->set_value( $params->{height} ); $group_dist_spin->set_value( $params->{groupDistance} ); $top_margin_spin->set_value( $params->{topMargin} ); $init_radius_spin->set_value( $params->{initRadius} ); $title_font_entry->set_text( $params->{titleFont} ); $title_size_spin->set_value( $params->{titleSize} ); $text_font_entry->set_text( $params->{textFont} ); $text_size_spin->set_value( $params->{textSize} ); # set topology attribute $circ_rbut->set_active( $params->{isCircular} ? TRUE : FALSE ); # run the page dialog my $re = $editor->run; # accept changes if ( $re == 0 ) { $params->{width} = $width_spin->get_value; $params->{height} = $height_spin->get_value; $params->{groupDistance} = $group_dist_spin->get_value; $params->{topMargin} = $top_margin_spin->get_value; $params->{initRadius} = $init_radius_spin->get_value; $params->{titleFont} = $title_font_entry->get_text; $params->{titleSize} = $title_size_spin->get_value; $params->{textFont} = $text_font_entry->get_text; $params->{textSize} = $text_size_spin->get_value; $params->{isCircular} = $linear_rbut->get_active ? 0 : 1; } $editor->hide; return $re; } 1; Gdraw2-v0.0.3/t000755001750001750 012001671021 13240 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/t/circ_mapping.svg000555001750001750 276112001671021 16562 0ustar00yangxiyangxi000000000000 Gdraw2-v0.0.3/t/Arranger.t000555001750001750 201112001671021 15320 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use strict; use feature qw/say/; use threads; use threads::shared; use Gdraw2::Util::Arranger; use Gdraw2::Element::AbstractElement; use Test::More tests => 2; use YAML; say "create element 1"; my $ele1 = Gdraw2::Element::AbstractElement->new( displayName => 'ele 1', position => shared_clone [ 1, 15, 10 ] ); say "create element 2"; my $ele2 = Gdraw2::Element::AbstractElement->new( displayName => 'ele 2', position => shared_clone [ 21, 30 ] ); say "create element 3"; my $ele3 = Gdraw2::Element::AbstractElement->new( displayName => 'ele 3', position => shared_clone [ 10, 20 ] ); say "create element 4"; my $ele4 = Gdraw2::Element::AbstractElement->new( displayName => 'ele 4', position => shared_clone [ 35, 45 ] ); say "create arranger"; my $arranger = Gdraw2::Util::Arranger->new(); $arranger->addChild($ele1); $arranger->addChild($ele2); ok( $arranger->overlaps($ele3), "overlap" ); ok( !$arranger->overlaps($ele4), "not overlap" ); Gdraw2-v0.0.3/t/group_layout.svg000555001750001750 2015612001671021 16676 0ustar00yangxiyangxi000000000000 Gdraw2-v0.0.3/t/CairoTrack.t000555001750001750 74012001671021 15570 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use strict; use threads; use threads::shared; use Gdraw2::CairoTrack; use Gdraw2::Element::AbstractElement; use YAML; my $ele1 = Gdraw2::Element::AbstractElement->new(displayName=>'a'); my $ele2 = Gdraw2::Element::AbstractElement->new(displayName=>'b'); my $ele3 = Gdraw2::Element::AbstractElement->new(displayName=>'c'); my $track = Gdraw2::CairoTrack->new; $track->addChild($ele1); $track->addChild($ele2); $track->addChildAt($ele3,1); print Dump $track;Gdraw2-v0.0.3/t/corona_sars.gb000555001750001750 26260012001671021 16271 0ustar00yangxiyangxi000000000000LOCUS NC_004718 29751 bp ss-RNA linear VRL 04-SEP-2006 DEFINITION SARS coronavirus, complete genome. ACCESSION NC_004718 VERSION NC_004718.3 GI:30271926 PROJECT GenomeProject:15500 KEYWORDS . SOURCE SARS coronavirus ORGANISM SARS coronavirus Viruses; ssRNA positive-strand viruses, no DNA stage; Nidovirales; Coronaviridae; Coronavirus; Coronavirus Group 2; Coronavirus group 2b. REFERENCE 1 (bases 1 to 29751) AUTHORS He,R., Dobie,F., Ballantine,M., Leeson,A., Li,Y., Bastien,N., Cutts,T., Andonov,A., Cao,J., Booth,T.F., Plummer,F.A., Tyler,S., Baker,L. and Li,X. CONSRTM BCCA Genome Sciences Centre, British Columbia Centre for Disease Control and National Microbiology Laboratory Canada TITLE Analysis of multimerization of the SARS coronavirus nucleocapsid protein JOURNAL Biochem. Biophys. Res. Commun. 316 (2), 476-483 (2004) PUBMED 15020242 REFERENCE 2 (bases 1 to 29751) AUTHORS Snijder,E.J., Bredenbeek,P.J., Dobbe,J.C., Thiel,V., Ziebuhr,J., Poon,L.L., Guan,Y., Rozanov,M., Spaan,W.J. and Gorbalenya,A.E. TITLE Unique and conserved features of genome and proteome of SARS-coronavirus, an early split-off from the coronavirus group 2 lineage JOURNAL J. Mol. Biol. 331 (5), 991-1004 (2003) PUBMED 12927536 REFERENCE 3 (bases 1 to 29751) AUTHORS Marra,M.A., Jones,S.J., Astell,C.R., Holt,R.A., Brooks-Wilson,A., Butterfield,Y.S., Khattra,J., Asano,J.K., Barber,S.A., Chan,S.Y., Cloutier,A., Coughlin,S.M., Freeman,D., Girn,N., Griffith,O.L., Leach,S.R., Mayo,M., McDonald,H., Montgomery,S.B., Pandoh,P.K., Petrescu,A.S., Robertson,A.G., Schein,J.E., Siddiqui,A., Smailus,D.E., Stott,J.M., Yang,G.S., Plummer,F., Andonov,A., Artsob,H., Bastien,N., Bernard,K., Booth,T.F., Bowness,D., Czub,M., Drebot,M., Fernando,L., Flick,R., Garbutt,M., Gray,M., Grolla,A., Jones,S., Feldmann,H., Meyers,A., Kabani,A., Li,Y., Normand,S., Stroher,U., Tipples,G.A., Tyler,S., Vogrig,R., Ward,D., Watson,B., Brunham,R.C., Krajden,M., Petric,M., Skowronski,D.M., Upton,C. and Roper,R.L. TITLE The Genome sequence of the SARS-associated coronavirus JOURNAL Science 300 (5624), 1399-1404 (2003) PUBMED 12730501 REFERENCE 4 (bases 1 to 29751) CONSRTM NCBI Genome Project TITLE Direct Submission JOURNAL Submitted (31-AUG-2004) National Center for Biotechnology Information, NIH, Bethesda, MD 20894, USA REFERENCE 5 (bases 1 to 29751) CONSRTM BCCA Genome Sciences Centre, British Columbia Centre for Disease Control and National Microbiology Laboratory Canada TITLE Direct Submission JOURNAL Submitted (30-APR-2003) Genome Sciences Centre, British Columbia Cancer Research Centre, 600 West 10th Avenue, Vancouver, BC V5Z 4E6, Canada REMARK Sequence update by submitter REFERENCE 6 (bases 1 to 29751) CONSRTM BCCA Genome Sciences Centre, British Columbia Centre for Disease Control and National Microbiology Laboratory Canada TITLE Direct Submission JOURNAL Submitted (23-APR-2003) Genome Sciences Centre, British Columbia Cancer Research Centre, 600 West 10th Avenue, Vancouver, BC V5Z 4E6, Canada REMARK Sequence update by submitter REFERENCE 7 (bases 1 to 29751) CONSRTM BCCA Genome Sciences Centre, British Columbia Centre for Disease Control and National Microbiology Laboratory Canada TITLE Direct Submission JOURNAL Submitted (13-APR-2003) Genome Sciences Centre, British Columbia Cancer Research Centre, 600 West 10th Avenue, Vancouver, BC V5Z 4E6, Canada COMMENT REVIEWED REFSEQ: This record has been curated by NCBI staff. The reference sequence was derived from AY274119. On May 1, 2003 this sequence version replaced gi:30124072. The annotation in based mainly on the sequence analysis described by Snijder et al. (2003). Annotation of transcription regulatory sequences was copied from virtually identical (except the very 3' end) AY291315 (Frankfurt 1). Designations of the 3'-adjacent genes do not coincide with those provided by Marra et al. (2003). COMPLETENESS: full length. FEATURES Location/Qualifiers source 1..29751 /organism="SARS coronavirus" /mol_type="genomic RNA" /isolate="Tor2" /isolation_source="patient #2 with severe acute respiratory syndrome (SARS)" /db_xref="taxon:227859" /country="Canada: Toronto" 5'UTR 1..264 /inference="non-experimental evidence, no additional details recorded" misc_feature 67..72 /note="transcription regulatory sequence leader TRS" gene 265..21485 /gene="orf1ab" /locus_tag="sars1" /db_xref="GeneID:1489680" CDS join(265..13398,13398..21485) /gene="orf1ab" /locus_tag="sars1" /ribosomal_slippage /note="It was assumed that the SARS orf1ab polyprotein processing map should be similar to that of murine hepatitis virus; however, of the two MHV papain-like proteinases, only PL2-PRO is well conserved for SARS coronavirus. The mature peptides located downstream from nsp4-pp1a/pp1ab are cleaved from the polyprotein by the nsp5-pp1a/pp1ab proteinase 3CL-PRO. The orf1a/orf1b translational frameshift, the predicted processing map, and both proteinase activities have been supported by in vitro expression and mutagenesis experiments (Thiel et al., 2003); -1 frameshift" /codon_start=1 /product="orf1ab polyprotein (pp1ab)" /protein_id="NP_828849.2" /db_xref="GI:30124074" /db_xref="GeneID:1489680" /translation="MESLVLGVNEKTHVQLSLPVLQVRDVLVRGFGDSVEEALSEARE HLKNGTCGLVELEKGVLPQLEQPYVFIKRSDALSTNHGHKVVELVAEMDGIQYGRSGI TLGVLVPHVGETPIAYRNVLLRKNGNKGAGGHSYGIDLKSYDLGDELGTDPIEDYEQN WNTKHGSGALRELTRELNGGAVTRYVDNNFCGPDGYPLDCIKDFLARAGKSMCTLSEQ LDYIESKRGVYCCRDHEHEIAWFTERSDKSYEHQTPFEIKSAKKFDTFKGECPKFVFP LNSKVKVIQPRVEKKKTEGFMGRIRSVYPVASPQECNNMHLSTLMKCNHCDEVSWQTC DFLKATCEHCGTENLVIEGPTTCGYLPTNAVVKMPCPACQDPEIGPEHSVADYHNHSN IETRLRKGGRTRCFGGCVFAYVGCYNKRAYWVPRASADIGSGHTGITGDNVETLNEDL LEILSRERVNINIVGDFHLNEEVAIILASFSASTSAFIDTIKSLDYKSFKTIVESCGN YKVTKGKPVKGAWNIGQQRSVLTPLCGFPSQAAGVIRSIFARTLDAANHSIPDLQRAA VTILDGISEQSLRLVDAMVYTSDLLTNSVIIMAYVTGGLVQQTSQWLSNLLGTTVEKL RPIFEWIEAKLSAGVEFLKDAWEILKFLITGVFDIVKGQIQVASDNIKDCVKCFIDVV NKALEMCIDQVTIAGAKLRSLNLGEVFIAQSKGLYRQCIRGKEQLQLLMPLKAPKEVT FLEGDSHDTVLTSEEVVLKNGELEALETPVDSFTNGAIVGTPVCVNGLMLLEIKDKEQ YCALSPGLLATNNVFRLKGGAPIKGVTFGEDTVWEVQGYKNVRITFELDERVDKVLNE KCSVYTVESGTEVTEFACVVAEAVVKTLQPVSDLLTNMGIDLDEWSVATFYLFDDAGE ENFSSRMYCSFYPPDEEEEDDAECEEEEIDETCEHEYGTEDDYQGLPLEFGASAETVR VEEEEEEDWLDDTTEQSEIEPEPEPTPEEPVNQFTGYLKLTDNVAIKCVDIVKEAQSA NPMVIVNAANIHLKHGGGVAGALNKATNGAMQKESDDYIKLNGPLTVGGSCLLSGHNL AKKCLHVVGPNLNAGEDIQLLKAAYENFNSQDILLAPLLSAGIFGAKPLQSLQVCVQT VRTQVYIAVNDKALYEQVVMDYLDNLKPRVEAPKQEEPPNTEDSKTEEKSVVQKPVDV KPKIKACIDEVTTTLEETKFLTNKLLLFADINGKLYHDSQNMLRGEDMSFLEKDAPYM VGDVITSGDITCVVIPSKKAGGTTEMLSRALKKVPVDEYITTYPGQGCAGYTLEEAKT ALKKCKSAFYVLPSEAPNAKEEILGTVSWNLREMLAHAEETRKLMPICMDVRAIMATI QRKYKGIKIQEGIVDYGVRFFFYTSKEPVASIITKLNSLNEPLVTMPIGYVTHGFNLE EAARCMRSLKAPAVVSVSSPDAVTTYNGYLTSSSKTSEEHFVETVSLAGSYRDWSYSG QRTELGVEFLKRGDKIVYHTLESPVEFHLDGEVLSLDKLKSLLSLREVKTIKVFTTVD NTNLHTQLVDMSMTYGQQFGPTYLDGADVTKIKPHVNHEGKTFFVLPSDDTLRSEAFE YYHTLDESFLGRYMSALNHTKKWKFPQVGGLTSIKWADNNCYLSSVLLALQQLEVKFN APALQEAYYRARAGDAANFCALILAYSNKTVGELGDVRETMTHLLQHANLESAKRVLN VVCKHCGQKTTTLTGVEAVMYMGTLSYDNLKTGVSIPCVCGRDATQYLVQQESSFVMM SAPPAEYKLQQGTFLCANEYTGNYQCGHYTHITAKETLYRIDGAHLTKMSEYKGPVTD VFYKETSYTTTIKPVSYKLDGVTYTEIEPKLDGYYKKDNAYYTEQPIDLVPTQPLPNA SFDNFKLTCSNTKFADDLNQMTGFTKPASRELSVTFFPDLNGDVVAIDYRHYSASFKK GAKLLHKPIVWHINQATTKTTFKPNTWCLRCLWSTKPVDTSNSFEVLAVEDTQGMDNL ACESQQPTSEEVVENPTIQKEVIECDVKTTEVVGNVILKPSDEGVKVTQELGHEDLMA AYVENTSITIKKPNELSLALGLKTIATHGIAAINSVPWSKILAYVKPFLGQAAITTSN CAKRLAQRVFNNYMPYVFTLLFQLCTFTKSTNSRIRASLPTTIAKNSVKSVAKLCLDA GINYVKSPKFSKLFTIAMWLLLLSICLGSLICVTAAFGVLLSNFGAPSYCNGVRELYL NSSNVTTMDFCEGSFPCSICLSGLDSLDSYPALETIQVTISSYKLDLTILGLAAEWVL AYMLFTKFFYLLGLSAIMQVFFGYFASHFISNSWLMWFIISIVQMAPVSAMVRMYIFF ASFYYIWKSYVHIMDGCTSSTCMMCYKRNRATRVECTTIVNGMKRSFYVYANGGRGFC KTHNWNCLNCDTFCTGSTFISDEVARDLSLQFKRPINPTDQSSYIVDSVAVKNGALHL YFDKAGQKTYERHPLSHFVNLDNLRANNTKGSLPINVIVFDGKSKCDESASKSASVYY SQLMCQPILLLDQALVSDVGDSTEVSVKMFDAYVDTFSATFSVPMEKLKALVATAHSE LAKGVALDGVLSTFVSAARQGVVDTDVDTKDVIECLKLSHHSDLEVTGDSCNNFMLTY NKVENMTPRDLGACIDCNARHINAQVAKSHNVSLIWNVKDYMSLSEQLRKQIRSAAKK NNIPFRLTCATTRQVVNVITTKISLKGGKIVSTCFKLMLKATLLCVLAALVCYIVMPV HTLSIHDGYTNEIIGYKAIQDGVTRDIISTDDCFANKHAGFDAWFSQRGGSYKNDKSC PVVAAIITREIGFIVPGLPGTVLRAINGDFLHFLPRVFSAVGNICYTPSKLIEYSDFA TSACVLAAECTIFKDAMGKPVPYCYDTNLLEGSISYSELRPDTRYVLMDGSIIQFPNT YLEGSVRVVTTFDAEYCRHGTCERSEVGICLSTSGRWVLNNEHYRALSGVFCGVDAMN LIANIFTPLVQPVGALDVSASVVAGGIIAILVTCAAYYFMKFRRVFGEYNHVVAANAL LFLMSFTILCLVPAYSFLPGVYSVFYLYLTFYFTNDVSFLAHLQWFAMFSPIVPFWIT AIYVFCISLKHCHWFFNNYLRKRVMFNGVTFSTFEEAALCTFLLNKEMYLKLRSETLL PLTQYNRYLALYNKYKYFSGALDTTSYREAACCHLAKALNDFSNSGADVLYQPPQTSI TSAVLQSGFRKMAFPSGKVEGCMVQVTCGTTTLNGLWLDDTVYCPRHVICTAEDMLNP NYEDLLIRKSNHSFLVQAGNVQLRVIGHSMQNCLLRLKVDTSNPKTPKYKFVRIQPGQ TFSVLACYNGSPSGVYQCAMRPNHTIKGSFLNGSCGSVGFNIDYDCVSFCYMHHMELP TGVHAGTDLEGKFYGPFVDRQTAQAAGTDTTITLNVLAWLYAAVINGDRWFLNRFTTT LNDFNLVAMKYNYEPLTQDHVDILGPLSAQTGIAVLDMCAALKELLQNGMNGRTILGS TILEDEFTPFDVVRQCSGVTFQGKFKKIVKGTHHWMLLTFLTSLLILVQSTQWSLFFF VYENAFLPFTLGIMAIAACAMLLVKHKHAFLCLFLLPSLATVAYFNMVYMPASWVMRI MTWLELADTSLSGYRLKDCVMYASALVLLILMTARTVYDDAARRVWTLMNVITLVYKV YYGNALDQAISMWALVISVTSNYSGVVTTIMFLARAIVFVCVEYYPLLFITGNTLQCI MLVYCFLGYCCCCYFGLFCLLNRYFRLTLGVYDYLVSTQEFRYMNSQGLLPPKSSIDA FKLNIKLLGIGGKPCIKVATVQSKMSDVKCTSVVLLSVLQQLRVESSSKLWAQCVQLH NDILLAKDTTEAFEKMVSLLSVLLSMQGAVDINRLCEEMLDNRATLQAIASEFSSLPS YAAYATAQEAYEQAVANGDSEVVLKKLKKSLNVAKSEFDRDAAMQRKLEKMADQAMTQ MYKQARSEDKRAKVTSAMQTMLFTMLRKLDNDALNNIINNARDGCVPLNIIPLTTAAK LMVVVPDYGTYKNTCDGNTFTYASALWEIQQVVDADSKIVQLSEINMDNSPNLAWPLI VTALRANSAVKLQNNELSPVALRQMSCAAGTTQTACTDDNALAYYNNSKGGRFVLALL SDHQDLKWARFPKSDGTGTIYTELEPPCRFVTDTPKGPKVKYLYFIKGLNNLNRGMVL GSLAATVRLQAGNATEVPANSTVLSFCAFAVDPAKAYKDYLASGGQPITNCVKMLCTH TGTGQAITVTPEANMDQESFGGASCCLYCRCHIDHPNPKGFCDLKGKYVQIPTTCAND PVGFTLRNTVCTVCGMWKGYGCSCDQLREPLMQSADASTFLNRVCGVSAARLTPCGTG TSTDVVYRAFDIYNEKVAGFAKFLKTNCCRFQEKDEEGNLLDSYFVVKRHTMSNYQHE ETIYNLVKDCPAVAVHDFFKFRVDGDMVPHISRQRLTKYTMADLVYALRHFDEGNCDT LKEILVTYNCCDDDYFNKKDWYDFVENPDILRVYANLGERVRQSLLKTVQFCDAMRDA GIVGVLTLDNQDLNGNWYDFGDFVQVAPGCGVPIVDSYYSLLMPILTLTRALAAESHM DADLAKPLIKWDLLKYDFTEERLCLFDRYFKYWDQTYHPNCINCLDDRCILHCANFNV LFSTVFPPTSFGPLVRKIFVDGVPFVVSTGYHFRELGVVHNQDVNLHSSRLSFKELLV YAADPAMHAASGNLLLDKRTTCFSVAALTNNVAFQTVKPGNFNKDFYDFAVSKGFFKE GSSVELKHFFFAQDGNAAISDYDYYRYNLPTMCDIRQLLFVVEVVDKYFDCYDGGCIN ANQVIVNNLDKSAGFPFNKWGKARLYYDSMSYEDQDALFAYTKRNVIPTITQMNLKYA ISAKNRARTVAGVSICSTMTNRQFHQKLLKSIAATRGATVVIGTSKFYGGWHNMLKTV YSDVETPHLMGWDYPKCDRAMPNMLRIMASLVLARKHNTCCNLSHRFYRLANECAQVL SEMVMCGGSLYVKPGGTSSGDATTAYANSVFNICQAVTANVNALLSTDGNKIADKYVR NLQHRLYECLYRNRDVDHEFVDEFYAYLRKHFSMMILSDDAVVCYNSNYAAQGLVASI KNFKAVLYYQNNVFMSEAKCWTETDLTKGPHEFCSQHTMLVKQGDDYVYLPYPDPSRI LGAGCFVDDIVKTDGTLMIERFVSLAIDAYPLTKHPNQEYADVFHLYLQYIRKLHDEL TGHMLDMYSVMLTNDNTSRYWEPEFYEAMYTPHTVLQAVGACVLCNSQTSLRCGACIR RPFLCCKCCYDHVISTSHKLVLSVNPYVCNAPGCDVTDVTQLYLGGMSYYCKSHKPPI SFPLCANGQVFGLYKNTCVGSDNVTDFNAIATCDWTNAGDYILANTCTERLKLFAAET LKATEETFKLSYGIATVREVLSDRELHLSWEVGKPRPPLNRNYVFTGYRVTKNSKVQI GEYTFEKGDYGDAVVYRGTTTYKLNVGDYFVLTSHTVMPLSAPTLVPQEHYVRITGLY PTLNISDEFSSNVANYQKVGMQKYSTLQGPPGTGKSHFAIGLALYYPSARIVYTACSH AAVDALCEKALKYLPIDKCSRIIPARARVECFDKFKVNSTLEQYVFCTVNALPETTAD IVVFDEISMATNYDLSVVNARLRAKHYVYIGDPAQLPAPRTLLTKGTLEPEYFNSVCR LMKTIGPDMFLGTCRRCPAEIVDTVSALVYDNKLKAHKDKSAQCFKMFYKGVITHDVS SAINRPQIGVVREFLTRNPAWRKAVFISPYNSQNAVASKILGLPTQTVDSSQGSEYDY VIFTQTTETAHSCNVNRFNVAITRAKIGILCIMSDRDLYDKLQFTSLEIPRRNVATLQ AENVTGLFKDCSKIITGLHPTQAPTHLSVDIKFKTEGLCVDIPGIPKDMTYRRLISMM GFKMNYQVNGYPNMFITREEAIRHVRAWIGFDVEGCHATRDAVGTNLPLQLGFSTGVN LVAVPTGYVDTENNTEFTRVNAKPPPGDQFKHLIPLMYKGLPWNVVRIKIVQMLSDTL KGLSDRVVFVLWAHGFELTSMKYFVKIGPERTCCLCDKRATCFSTSSDTYACWNHSVG FDYVYNPFMIDVQQWGFTGNLQSNHDQHCQVHGNAHVASCDAIMTRCLAVHECFVKRV DWSVEYPIIGDELRVNSACRKVQHMVVKSALLADKFPVLHDIGNPKAIKCVPQAEVEW KFYDAQPCSDKAYKIEELFYSYATHHDKFTDGVCLFWNCNVDRYPANAIVCRFDTRVL SNLNLPGCDGGSLYVNKHAFHTPAFDKSAFTNLKQLPFFYYSDSPCESHGKQVVSDID YVPLKSATCITRCNLGGAVCRHHANEYRQYLDAYNMMISAGFSLWIYKQFDTYNLWNT FTRLQSLENVAYNVVNKGHFDGHAGEAPVSIINNAVYTKVDGIDVEIFENKTTLPVNV AFELWAKRNIKPVPEIKILNNLGVDIAANTVIWDYKREAPAHVSTIGVCTMTDIAKKP TESACSSLTVLFDGRVEGQVDLFRNARNGVLITEGSVKGLTPSKGPAQASVNGVTLIG ESVKTQFNYFKKVDGIIQQLPETYFTQSRDLEDFKPRSQMETDFLELAMDEFIQRYKL EGYAFEHIVYGDFSHGQLGGLHLMIGLAKRSQDSPLKLEDFIPMDSTVKNYFITDAQT GSSKCVCSVIDLLLDDFVEIIKSQDLSVISKVVKVTIDYAEISFMLWCKDGHVETFYP KLQASQAWQPGVAMPNLYKMQRMLLEKCDLQNYGENAVIPKGIMMNVAKYTQLCQYLN TLTLAVPYNMRVIHFGAGSDKGVAPGTAVLRQWLPTGTLLVDSDLNDFVSDADSTLIG DCATVHTANKWDLIISDMYDPRTKHVTKENDSKEGFFTYLCGFIKQKLALGGSIAVKI TEHSWNADLYKLMGHFSWWTAFVTNVNASSSEAFLIGANYLGKPKEQIDGYTMHANYI FWRNTNPIQLSSYSLFDMSKFPLKLRGTAVMSLKENQINDMIYSLLEKGRLIIRENNR VVVSSDILVNN" mat_peptide 265..804 /gene="orf1ab" /locus_tag="sars1" /product="leader protein" /experiment="experimental evidence, no additional details recorded" /note="PL2-PRO cleavage product; nsp1-pp1a/pp1ab" /protein_id="NP_828860.2" /db_xref="GI:34555774" mat_peptide 805..2718 /gene="orf1ab" /locus_tag="sars1" /product="counterpart of MHV p65" /experiment="experimental evidence, no additional details recorded" /note="PL2-PRO cleavage product; nsp2-pp1a/pp1ab" /protein_id="NP_828861.2" /db_xref="GI:34555775" mat_peptide 2719..8484 /gene="orf1ab" /locus_tag="sars1" /product="nsp3-pp1a/pp1ab" /note="PL2-PRO cleavage product; former nsp1; conserved domains are: N-terminal acidic (Ac), predicted phosphoesterase (similar to the Appr-1'-p processing enzyme) formerly known as 'X-domain', papain-like proteinase similar to that of MHV PL2-PRO, Y-domain; transmembrane domain 1 (TM1); adenosine diphosphate-ribose 1''-phosphatase (ADPR)" /protein_id="NP_828862.2" /db_xref="GI:34555776" misc_feature 3328..3774 /gene="orf1ab" /locus_tag="sars1" /note="Macro domain, Af1521- and BAL-like family; Region: Macro_Af1521_BAL_like; cd02907" /db_xref="CDD:28847" misc_feature 4885..5841 /gene="orf1ab" /locus_tag="sars1" /note="Papain like viral protease. This family of viral proteases are similar to the papain protease and are required for proteolytic processing of the replicase polyprotein; Region: Viral_protease; pfam08715" /db_xref="CDD:72139" mat_peptide 8485..9984 /gene="orf1ab" /locus_tag="sars1" /product="nsp4-pp1a/pp1ab" /experiment="experimental evidence, no additional details recorded" /note="cleaved from polyprotein by the PL2-PRO at the N-terminus and by 3CL-PRO at the C-terminus; contains transmembrane domain 2 (TM2)" /protein_id="NP_904322.1" /db_xref="GI:34555778" mat_peptide 9985..10902 /gene="orf1ab" /locus_tag="sars1" /product="3C-like proteinase" /experiment="experimental evidence, no additional details recorded" /note="mediates cleavages downstream from nsp4-pp1a/pp1ab. 3D structure has been determined (Yang et al., 2003); main proteinase (Mpro); nsp5-pp1a/pp1ab (3CL-PRO)" /protein_id="NP_828863.1" /db_xref="GI:29837498" misc_feature 10069..10893 /gene="orf1ab" /locus_tag="sars1" /note="Coronavirus endopeptidase C30. Corresponds to Merops family C30. These peptidases are involved in viral polyprotein processing in replication; Region: Peptidase_C30; pfam05409" /db_xref="CDD:68960" mat_peptide 10903..11772 /gene="orf1ab" /locus_tag="sars1" /product="nsp6-pp1a/pp1ab (TM3)" /note="putative transmembrane domain" /protein_id="NP_828864.1" /db_xref="GI:29837499" misc_feature 11773..12021 /gene="orf1ab" /locus_tag="sars1" /note="nsp7 replicase. nsp7 (non structural protein 7) has been implicated in viral RNA replication and is predominantly alpha helical in structure. It forms a hexadecameric supercomplex with nsp7 that adopts a hollow cylinder-like structure; Region: nsp7; pfam08716" /db_xref="CDD:72140" mat_peptide 11773..12021 /gene="orf1ab" /locus_tag="sars1" /product="nsp7-pp1a/pp1ab" /inference="non-experimental evidence, no additional details recorded" /protein_id="NP_828865.1" /db_xref="GI:29837500" misc_feature 12022..12615 /gene="orf1ab" /locus_tag="sars1" /note="nsp8 replicase. Viral nsp8 (non structural protein 8) forms a hexadecameric supercomplex with nsp7 that adopts a hollow cylinder-like structure; Region: nsp8; pfam08717" /db_xref="CDD:72141" mat_peptide 12022..12615 /gene="orf1ab" /locus_tag="sars1" /product="nsp8-pp1a/pp1ab" /inference="non-experimental evidence, no additional details recorded" /protein_id="NP_828866.1" /db_xref="GI:29837501" misc_feature 12616..12954 /gene="orf1ab" /locus_tag="sars1" /note="nsp9 replicase. nsp9 is a single-stranded RNA-binding viral protein likely to be involved in RNA synthesis. Its structure comprises of a single beta barrel; Region: nsp9; pfam08710" /db_xref="CDD:72134" mat_peptide 12616..12954 /gene="orf1ab" /locus_tag="sars1" /product="nsp9-pp1a/pp1ab" /experiment="experimental evidence, no additional details recorded" /note="ssRNA-binding protein" /protein_id="NP_828867.1" /db_xref="GI:29837502" mat_peptide 12955..13371 /gene="orf1ab" /locus_tag="sars1" /product="formerly known as growth-factor-like protein (GFL)" /inference="non-experimental evidence, no additional details recorded" /note="nsp10-pp1a/pp1ab" /protein_id="NP_828868.1" /db_xref="GI:29837503" mat_peptide join(13372..13398,13398..16166) /gene="orf1ab" /locus_tag="sars1" /product="RNA-dependent RNA polymerase" /inference="non-experimental evidence, no additional details recorded" /note="nsp12-pp1ab (RdRp)" /protein_id="NP_828869.1" /db_xref="GI:29837504" misc_feature 13404..14471 /gene="orf1ab" /locus_tag="sars1" /note="Coronavirus RPol N-terminus. This family covers the N-terminal region of the coronavirus RNA-directed RNA Polymerase; Region: Corona_RPol_N; pfam06478" /db_xref="CDD:69971" misc_feature <14859..>15458 /gene="orf1ab" /locus_tag="sars1" /note="RNA dependent RNA polymerase; Region: RdRP_1; pfam00680" /db_xref="CDD:64538" mat_peptide 16167..17969 /gene="orf1ab" /locus_tag="sars1" /product="nsp13-pp1ab (ZD, NTPase/HEL; RNA 5'-triphosphatase)" /experiment="experimental evidence, no additional details recorded" /note="zinc-binding domain (ZD), NTPase/helicase domain. RNA-stimulated ATPase and dsDNA helicase activities have been confirmed (Thiel et al., 2003)" /protein_id="NP_828870.1" /db_xref="GI:29837505" misc_feature <17133..17909 /gene="orf1ab" /locus_tag="sars1" /note="Superfamily I DNA and RNA helicases and helicase subunits [DNA replication, recombination, and repair]; Region: COG1112" /db_xref="CDD:31309" misc_feature 17958..19760 /gene="orf1ab" /locus_tag="sars1" /note="NSP11. This region of coronavirus polyproteins encodes the NSP11 protein; Region: NSP11; pfam06471" /db_xref="CDD:69964" mat_peptide 17970..19550 /gene="orf1ab" /locus_tag="sars1" /product="3'-to-5' exonuclease" /inference="non-experimental evidence, no additional details recorded" /note="nsp14-pp1ab (nuclease ExoN homolog)" /protein_id="NP_828871.1" /db_xref="GI:29837506" mat_peptide 19551..20588 /gene="orf1ab" /locus_tag="sars1" /product="endoRNAse" /experiment="experimental evidence, no additional details recorded" /note="the C-terminal domain is a homolog of endoRNase XendoU and is conserved through the order Nidovirales; nsp15-pp1ab; uridylate-specific endoribonuclease NendoU" /protein_id="NP_828872.1" /db_xref="GI:29837507" mat_peptide 20589..21482 /gene="orf1ab" /locus_tag="sars1" /product="2'-O-ribose methyltransferase (2'-o-MT)" /inference="non-experimental evidence, no additional details recorded" /note="nsp16-pp1ab" /protein_id="NP_828873.2" /db_xref="GI:30133975" misc_feature 20592..21479 /gene="orf1ab" /locus_tag="sars1" /note="Coronavirus NSP13. This family covers the NSP13 region of the coronavirus polyprotein. This protein has the predicted function of an mRNA cap-1 methyltransferase function; Region: NSP13; pfam06460" /db_xref="CDD:69953" CDS 265..13413 /gene="orf1ab" /locus_tag="sars1" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="orf1a polyprotein (pp1a)" /protein_id="NP_828850.1" /db_xref="GI:29836495" /db_xref="GeneID:1489680" /translation="MESLVLGVNEKTHVQLSLPVLQVRDVLVRGFGDSVEEALSEARE HLKNGTCGLVELEKGVLPQLEQPYVFIKRSDALSTNHGHKVVELVAEMDGIQYGRSGI TLGVLVPHVGETPIAYRNVLLRKNGNKGAGGHSYGIDLKSYDLGDELGTDPIEDYEQN WNTKHGSGALRELTRELNGGAVTRYVDNNFCGPDGYPLDCIKDFLARAGKSMCTLSEQ LDYIESKRGVYCCRDHEHEIAWFTERSDKSYEHQTPFEIKSAKKFDTFKGECPKFVFP LNSKVKVIQPRVEKKKTEGFMGRIRSVYPVASPQECNNMHLSTLMKCNHCDEVSWQTC DFLKATCEHCGTENLVIEGPTTCGYLPTNAVVKMPCPACQDPEIGPEHSVADYHNHSN IETRLRKGGRTRCFGGCVFAYVGCYNKRAYWVPRASADIGSGHTGITGDNVETLNEDL LEILSRERVNINIVGDFHLNEEVAIILASFSASTSAFIDTIKSLDYKSFKTIVESCGN YKVTKGKPVKGAWNIGQQRSVLTPLCGFPSQAAGVIRSIFARTLDAANHSIPDLQRAA VTILDGISEQSLRLVDAMVYTSDLLTNSVIIMAYVTGGLVQQTSQWLSNLLGTTVEKL RPIFEWIEAKLSAGVEFLKDAWEILKFLITGVFDIVKGQIQVASDNIKDCVKCFIDVV NKALEMCIDQVTIAGAKLRSLNLGEVFIAQSKGLYRQCIRGKEQLQLLMPLKAPKEVT FLEGDSHDTVLTSEEVVLKNGELEALETPVDSFTNGAIVGTPVCVNGLMLLEIKDKEQ YCALSPGLLATNNVFRLKGGAPIKGVTFGEDTVWEVQGYKNVRITFELDERVDKVLNE KCSVYTVESGTEVTEFACVVAEAVVKTLQPVSDLLTNMGIDLDEWSVATFYLFDDAGE ENFSSRMYCSFYPPDEEEEDDAECEEEEIDETCEHEYGTEDDYQGLPLEFGASAETVR VEEEEEEDWLDDTTEQSEIEPEPEPTPEEPVNQFTGYLKLTDNVAIKCVDIVKEAQSA NPMVIVNAANIHLKHGGGVAGALNKATNGAMQKESDDYIKLNGPLTVGGSCLLSGHNL AKKCLHVVGPNLNAGEDIQLLKAAYENFNSQDILLAPLLSAGIFGAKPLQSLQVCVQT VRTQVYIAVNDKALYEQVVMDYLDNLKPRVEAPKQEEPPNTEDSKTEEKSVVQKPVDV KPKIKACIDEVTTTLEETKFLTNKLLLFADINGKLYHDSQNMLRGEDMSFLEKDAPYM VGDVITSGDITCVVIPSKKAGGTTEMLSRALKKVPVDEYITTYPGQGCAGYTLEEAKT ALKKCKSAFYVLPSEAPNAKEEILGTVSWNLREMLAHAEETRKLMPICMDVRAIMATI QRKYKGIKIQEGIVDYGVRFFFYTSKEPVASIITKLNSLNEPLVTMPIGYVTHGFNLE EAARCMRSLKAPAVVSVSSPDAVTTYNGYLTSSSKTSEEHFVETVSLAGSYRDWSYSG QRTELGVEFLKRGDKIVYHTLESPVEFHLDGEVLSLDKLKSLLSLREVKTIKVFTTVD NTNLHTQLVDMSMTYGQQFGPTYLDGADVTKIKPHVNHEGKTFFVLPSDDTLRSEAFE YYHTLDESFLGRYMSALNHTKKWKFPQVGGLTSIKWADNNCYLSSVLLALQQLEVKFN APALQEAYYRARAGDAANFCALILAYSNKTVGELGDVRETMTHLLQHANLESAKRVLN VVCKHCGQKTTTLTGVEAVMYMGTLSYDNLKTGVSIPCVCGRDATQYLVQQESSFVMM SAPPAEYKLQQGTFLCANEYTGNYQCGHYTHITAKETLYRIDGAHLTKMSEYKGPVTD VFYKETSYTTTIKPVSYKLDGVTYTEIEPKLDGYYKKDNAYYTEQPIDLVPTQPLPNA SFDNFKLTCSNTKFADDLNQMTGFTKPASRELSVTFFPDLNGDVVAIDYRHYSASFKK GAKLLHKPIVWHINQATTKTTFKPNTWCLRCLWSTKPVDTSNSFEVLAVEDTQGMDNL ACESQQPTSEEVVENPTIQKEVIECDVKTTEVVGNVILKPSDEGVKVTQELGHEDLMA AYVENTSITIKKPNELSLALGLKTIATHGIAAINSVPWSKILAYVKPFLGQAAITTSN CAKRLAQRVFNNYMPYVFTLLFQLCTFTKSTNSRIRASLPTTIAKNSVKSVAKLCLDA GINYVKSPKFSKLFTIAMWLLLLSICLGSLICVTAAFGVLLSNFGAPSYCNGVRELYL NSSNVTTMDFCEGSFPCSICLSGLDSLDSYPALETIQVTISSYKLDLTILGLAAEWVL AYMLFTKFFYLLGLSAIMQVFFGYFASHFISNSWLMWFIISIVQMAPVSAMVRMYIFF ASFYYIWKSYVHIMDGCTSSTCMMCYKRNRATRVECTTIVNGMKRSFYVYANGGRGFC KTHNWNCLNCDTFCTGSTFISDEVARDLSLQFKRPINPTDQSSYIVDSVAVKNGALHL YFDKAGQKTYERHPLSHFVNLDNLRANNTKGSLPINVIVFDGKSKCDESASKSASVYY SQLMCQPILLLDQALVSDVGDSTEVSVKMFDAYVDTFSATFSVPMEKLKALVATAHSE LAKGVALDGVLSTFVSAARQGVVDTDVDTKDVIECLKLSHHSDLEVTGDSCNNFMLTY NKVENMTPRDLGACIDCNARHINAQVAKSHNVSLIWNVKDYMSLSEQLRKQIRSAAKK NNIPFRLTCATTRQVVNVITTKISLKGGKIVSTCFKLMLKATLLCVLAALVCYIVMPV HTLSIHDGYTNEIIGYKAIQDGVTRDIISTDDCFANKHAGFDAWFSQRGGSYKNDKSC PVVAAIITREIGFIVPGLPGTVLRAINGDFLHFLPRVFSAVGNICYTPSKLIEYSDFA TSACVLAAECTIFKDAMGKPVPYCYDTNLLEGSISYSELRPDTRYVLMDGSIIQFPNT YLEGSVRVVTTFDAEYCRHGTCERSEVGICLSTSGRWVLNNEHYRALSGVFCGVDAMN LIANIFTPLVQPVGALDVSASVVAGGIIAILVTCAAYYFMKFRRVFGEYNHVVAANAL LFLMSFTILCLVPAYSFLPGVYSVFYLYLTFYFTNDVSFLAHLQWFAMFSPIVPFWIT AIYVFCISLKHCHWFFNNYLRKRVMFNGVTFSTFEEAALCTFLLNKEMYLKLRSETLL PLTQYNRYLALYNKYKYFSGALDTTSYREAACCHLAKALNDFSNSGADVLYQPPQTSI TSAVLQSGFRKMAFPSGKVEGCMVQVTCGTTTLNGLWLDDTVYCPRHVICTAEDMLNP NYEDLLIRKSNHSFLVQAGNVQLRVIGHSMQNCLLRLKVDTSNPKTPKYKFVRIQPGQ TFSVLACYNGSPSGVYQCAMRPNHTIKGSFLNGSCGSVGFNIDYDCVSFCYMHHMELP TGVHAGTDLEGKFYGPFVDRQTAQAAGTDTTITLNVLAWLYAAVINGDRWFLNRFTTT LNDFNLVAMKYNYEPLTQDHVDILGPLSAQTGIAVLDMCAALKELLQNGMNGRTILGS TILEDEFTPFDVVRQCSGVTFQGKFKKIVKGTHHWMLLTFLTSLLILVQSTQWSLFFF VYENAFLPFTLGIMAIAACAMLLVKHKHAFLCLFLLPSLATVAYFNMVYMPASWVMRI MTWLELADTSLSGYRLKDCVMYASALVLLILMTARTVYDDAARRVWTLMNVITLVYKV YYGNALDQAISMWALVISVTSNYSGVVTTIMFLARAIVFVCVEYYPLLFITGNTLQCI MLVYCFLGYCCCCYFGLFCLLNRYFRLTLGVYDYLVSTQEFRYMNSQGLLPPKSSIDA FKLNIKLLGIGGKPCIKVATVQSKMSDVKCTSVVLLSVLQQLRVESSSKLWAQCVQLH NDILLAKDTTEAFEKMVSLLSVLLSMQGAVDINRLCEEMLDNRATLQAIASEFSSLPS YAAYATAQEAYEQAVANGDSEVVLKKLKKSLNVAKSEFDRDAAMQRKLEKMADQAMTQ MYKQARSEDKRAKVTSAMQTMLFTMLRKLDNDALNNIINNARDGCVPLNIIPLTTAAK LMVVVPDYGTYKNTCDGNTFTYASALWEIQQVVDADSKIVQLSEINMDNSPNLAWPLI VTALRANSAVKLQNNELSPVALRQMSCAAGTTQTACTDDNALAYYNNSKGGRFVLALL SDHQDLKWARFPKSDGTGTIYTELEPPCRFVTDTPKGPKVKYLYFIKGLNNLNRGMVL GSLAATVRLQAGNATEVPANSTVLSFCAFAVDPAKAYKDYLASGGQPITNCVKMLCTH TGTGQAITVTPEANMDQESFGGASCCLYCRCHIDHPNPKGFCDLKGKYVQIPTTCAND PVGFTLRNTVCTVCGMWKGYGCSCDQLREPLMQSADASTFLNGFAV" misc_feature 3328..3774 /gene="orf1ab" /locus_tag="sars1" /note="Macro domain, Af1521- and BAL-like family; Region: Macro_Af1521_BAL_like; cd02907" /db_xref="CDD:28847" misc_feature 4885..5841 /gene="orf1ab" /locus_tag="sars1" /note="Papain like viral protease. This family of viral proteases are similar to the papain protease and are required for proteolytic processing of the replicase polyprotein; Region: Viral_protease; pfam08715" /db_xref="CDD:72139" misc_feature 10069..10893 /gene="orf1ab" /locus_tag="sars1" /note="Coronavirus endopeptidase C30. Corresponds to Merops family C30. These peptidases are involved in viral polyprotein processing in replication; Region: Peptidase_C30; pfam05409" /db_xref="CDD:68960" misc_feature 11773..12021 /gene="orf1ab" /locus_tag="sars1" /note="nsp7 replicase. nsp7 (non structural protein 7) has been implicated in viral RNA replication and is predominantly alpha helical in structure. It forms a hexadecameric supercomplex with nsp7 that adopts a hollow cylinder-like structure; Region: nsp7; pfam08716" /db_xref="CDD:72140" misc_feature 12022..12615 /gene="orf1ab" /locus_tag="sars1" /note="nsp8 replicase. Viral nsp8 (non structural protein 8) forms a hexadecameric supercomplex with nsp7 that adopts a hollow cylinder-like structure; Region: nsp8; pfam08717" /db_xref="CDD:72141" misc_feature 12616..12954 /gene="orf1ab" /locus_tag="sars1" /note="nsp9 replicase. nsp9 is a single-stranded RNA-binding viral protein likely to be involved in RNA synthesis. Its structure comprises of a single beta barrel; Region: nsp9; pfam08710" /db_xref="CDD:72134" mat_peptide 13372..13410 /gene="orf1ab" /locus_tag="sars1" /product="nsp11-pp1a" /note="putative C-terminal cleavage product of pp1a" /protein_id="NP_904321.1" /db_xref="GI:34555777" misc_feature 13392..13472 /gene="orf1ab" /locus_tag="sars1" /note="Region: potential ribosome slippery sequence followed by stimulatory RNA pseudoknot" misc_feature 21486..21491 /note="transcription regulatory sequence for mRNA2" gene 21492..25259 /gene="S" /locus_tag="sars2" /note="synonym: E2" /db_xref="GeneID:1489668" CDS 21492..25259 /gene="S" /locus_tag="sars2" /experiment="experimental evidence, no additional details recorded" /note="As established by Krokhin et al. (2003), the glycosylated spike protein (as well as the nucleocapsid protein) can be detected in infected cell culture supernatants with antisera from SARS patients; spike glycoprotein" /codon_start=1 /product="E2 glycoprotein precursor" /protein_id="NP_828851.1" /db_xref="GI:29836496" /db_xref="GeneID:1489668" /translation="MFIFLLFLTLTSGSDLDRCTTFDDVQAPNYTQHTSSMRGVYYPD EIFRSDTLYLTQDLFLPFYSNVTGFHTINHTFGNPVIPFKDGIYFAATEKSNVVRGWV FGSTMNNKSQSVIIINNSTNVVIRACNFELCDNPFFAVSKPMGTQTHTMIFDNAFNCT FEYISDAFSLDVSEKSGNFKHLREFVFKNKDGFLYVYKGYQPIDVVRDLPSGFNTLKP IFKLPLGINITNFRAILTAFSPAQDIWGTSAAAYFVGYLKPTTFMLKYDENGTITDAV DCSQNPLAELKCSVKSFEIDKGIYQTSNFRVVPSGDVVRFPNITNLCPFGEVFNATKF PSVYAWERKKISNCVADYSVLYNSTFFSTFKCYGVSATKLNDLCFSNVYADSFVVKGD DVRQIAPGQTGVIADYNYKLPDDFMGCVLAWNTRNIDATSTGNYNYKYRYLRHGKLRP FERDISNVPFSPDGKPCTPPALNCYWPLNDYGFYTTTGIGYQPYRVVVLSFELLNAPA TVCGPKLSTDLIKNQCVNFNFNGLTGTGVLTPSSKRFQPFQQFGRDVSDFTDSVRDPK TSEILDISPCAFGGVSVITPGTNASSEVAVLYQDVNCTDVSTAIHADQLTPAWRIYST GNNVFQTQAGCLIGAEHVDTSYECDIPIGAGICASYHTVSLLRSTSQKSIVAYTMSLG ADSSIAYSNNTIAIPTNFSISITTEVMPVSMAKTSVDCNMYICGDSTECANLLLQYGS FCTQLNRALSGIAAEQDRNTREVFAQVKQMYKTPTLKYFGGFNFSQILPDPLKPTKRS FIEDLLFNKVTLADAGFMKQYGECLGDINARDLICAQKFNGLTVLPPLLTDDMIAAYT AALVSGTATAGWTFGAGAALQIPFAMQMAYRFNGIGVTQNVLYENQKQIANQFNKAIS QIQESLTTTSTALGKLQDVVNQNAQALNTLVKQLSSNFGAISSVLNDILSRLDKVEAE VQIDRLITGRLQSLQTYVTQQLIRAAEIRASANLAATKMSECVLGQSKRVDFCGKGYH LMSFPQAAPHGVVFLHVTYVPSQERNFTTAPAICHEGKAYFPREGVFVFNGTSWFITQ RNFFSPQIITTDNTFVSGNCDVVIGIINNTVYDPLQPELDSFKEELDKYFKNHTSPDV DLGDISGINASVVNIQKEIDRLNEVAKNLNESLIDLQELGKYEQYIKWPWYVWLGFIA GLIAIVMVTILLCCMTSCCSCLKGACSCGSCCKFDEDDSEPVLKGVKLHYT" misc_feature 21843..21845 /gene="S" /locus_tag="sars2" /experiment="experimental evidence, no additional details recorded" /note="second glycosylation site" misc_feature 21846..21848 /gene="S" /locus_tag="sars2" /experiment="experimental evidence, no additional details recorded" /note="first glycosylation site" misc_feature 22170..22172 /gene="S" /locus_tag="sars2" /experiment="experimental evidence, no additional details recorded" /note="glycosylation site" misc_feature 22296..22298 /gene="S" /locus_tag="sars2" /experiment="experimental evidence, no additional details recorded" /note="glycosylation site" misc_feature 23466..25199 /gene="S" /locus_tag="sars2" /note="Coronavirus S2 glycoprotein. The coronavirus spike glycoprotein forms the characteristic 'corona' after which the group is named. The Spike glycoprotein is translated as a large polypeptide that is subsequently cleaved to S1 pfam01600 and S2; Region: Corona_S2; pfam01601" /db_xref="CDD:65404" misc_feature 23838..23840 /gene="S" /locus_tag="sars2" /experiment="experimental evidence, no additional details recorded" /note="glycosylation site" misc_feature <24126..>24485 /gene="S" /locus_tag="sars2" /note="Uncharacterized protein involved in chromosome partitioning [Cell division and chromosome partitioning]; Region: MukF; COG3006" /db_xref="CDD:32823" misc_feature 25260..25265 /note="transcription regulatory sequence for mRNA3" gene 25268..26092 /locus_tag="sars3a" /db_xref="GeneID:1489669" CDS 25268..26092 /locus_tag="sars3a" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars3a" /protein_id="NP_828852.2" /db_xref="GI:30124073" /db_xref="GeneID:1489669" /translation="MDLFMRFFTLRSITAQPVKIDNASPASTVHATATIPLQASLPFG WLVIGVAFLAVFQSATKIIALNKRWQLALYKGFQFICNLLLLFVTIYSHLLLVAAGME AQFLYLYALIYFLQCINACRIIMRCWLCWKCKSKNPLLYDANYFVCWHTHNYDYCIPY NSVTDTIVVTEGDGISTPKLKEDYQIGGYSEDRHSGVKDYVVVHGYFTEVYYQLESTQ ITTDTGIENATFFIFNKLVKDPPNVQIHTIDGSSGVANPAMDPIYDEPTTTTSVPL" gene 25689..26153 /locus_tag="sars3b" /db_xref="GeneID:1489670" CDS 25689..26153 /locus_tag="sars3b" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars3b" /protein_id="NP_828853.1" /db_xref="GI:29836498" /db_xref="GeneID:1489670" /translation="MMPTTLFAGTHITMTTVYHITVSQIQLSLLKVTAFQHQNSKKTT KLVVILRIGTQVLKTMSLYMAISPKFTTSLSLHKLLQTLVLKMLHSSSLTSLLKTHRM CKYTQSTALQELLIQQWIQFMMSRRRLLACLCKHKKVSTNLCTHSFRKKQVR" misc_feature 26109..26114 /locus_tag="sars3b" /note="transcription regulatory sequence for mRNA4" gene 26117..26347 /gene="E" /locus_tag="sars4" /db_xref="GeneID:1489671" CDS 26117..26347 /gene="E" /locus_tag="sars4" /experiment="experimental evidence, no additional details recorded" /note="E. coli expression reported by Shen et al. (2003); protein sM; small envelope protein" /codon_start=1 /product="protein E" /protein_id="NP_828854.1" /db_xref="GI:29836499" /db_xref="GeneID:1489671" /translation="MYSFVSEETGTLIVNSVLLFLAFVVFLLVTLAILTALRLCAYCC NIVNVSLVKPTVYVYSRVKNLNSSEGVPDLLV" misc_feature 26348..26353 /note="transcription regulatory sequence for mRNA5" gene 26398..27063 /gene="M" /locus_tag="sars5" /db_xref="GeneID:1489672" CDS 26398..27063 /gene="M" /locus_tag="sars5" /note="E. coli expression reported by Zhang et al. (2003)" /codon_start=1 /product="matrix protein" /protein_id="NP_828855.1" /db_xref="GI:29836504" /db_xref="GeneID:1489672" /translation="MADNGTITVEELKQLLEQWNLVIGFLFLAWIMLLQFAYSNRNRF LYIIKLVFLWLLWPVTLACFVLAAVYRINWVTGGIAIAMACIVGLMWLSYFVASFRLF ARTRSMWSFNPETNILLNVPLRGTIVTRPLMESELVIGAVIIRGHLRMAGHSLGRCDI KDLPKEITVATSRTLSYYKLGASQRVGTDSGFAAYNRYRIGNYKLNTDHAGSNDNIAL LVQ" misc_feature 26404..27012 /gene="M" /locus_tag="sars5" /note="Coronavirus M matrix/glycoprotein. This family consists of various coronavirus matrix proteins which are transmembrane glycoproteins. The M protein or E1 glycoprotein is The coronavirus M protein is implicated in virus assembly; Region: Corona_M; pfam01635" /db_xref="CDD:65432" gene 26913..27265 /locus_tag="sars6" /db_xref="GeneID:1489673" misc_feature 26913..26918 /locus_tag="sars6" /note="transcription regulatory sequence for mRNA6" CDS 27074..27265 /locus_tag="sars6" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars6" /protein_id="NP_828856.1" /db_xref="GI:29836500" /db_xref="GeneID:1489673" /translation="MFHLVDFQVTIAEILIIIMRTFRIAIWNLDVIISSIVRQLFKPL TKKNYSELDDEEPMELDYP" misc_feature 27267..27272 /note="transcription regulatory sequence for mRNA7" gene 27273..27641 /locus_tag="sars7a" /db_xref="GeneID:1489674" CDS 27273..27641 /locus_tag="sars7a" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars7a" /protein_id="NP_828857.1" /db_xref="GI:29836501" /db_xref="GeneID:1489674" /translation="MKIILFLTLIVFTSCELYHYQECVRGTTVLLKEPCPSGTYEGNS PFHPLADNKFALTCTSTHFAFACADGTRHTYQLRARSVSPKLFIRQEEVQQELYSPLF LIVAALVFLILCFTIKRKTE" misc_feature 27318..27569 /locus_tag="sars7a" /note="SARS coronavirus X4 like. The structure of the coronavirus X4 protein (also known as 7a and U122) shows similarities to the immunoglobulin like fold and suggests a binding activity to integrin I domains; Region: SARS_X4; pfam08779" /db_xref="CDD:72203" gene 27638..27772 /locus_tag="sars7b" /db_xref="GeneID:1489675" CDS 27638..27772 /locus_tag="sars7b" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars7b" /protein_id="NP_849175.1" /db_xref="GI:30524940" /db_xref="GeneID:1489675" /translation="MNELTLIDFYLCFLAFLLFLVLIMLIIFWFSLEIQDLEEPCTKV" misc_feature 27773..27778 /note="transcription regulatory sequence for mRNA8" gene 27779..27898 /locus_tag="sars8a" /db_xref="GeneID:1489676" CDS 27779..27898 /locus_tag="sars8a" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars8a" /protein_id="NP_849176.1" /db_xref="GI:30524941" /db_xref="GeneID:1489676" /translation="MKLLIVLTCISLCSCICTVVQRCASNKPHVLEDPCKVQH" gene 27864..28118 /locus_tag="sars8b" /db_xref="GeneID:1489677" CDS 27864..28118 /locus_tag="sars8b" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars8b" /protein_id="NP_849177.1" /db_xref="GI:30524942" /db_xref="GeneID:1489677" /translation="MCLKILVRYNTRGNTYSTAWLCALGKVLPFHRWHTMVQTCTPNV TINCQDPAGGALIARCWYLHEGHQTAAFRDVLVVLNKRTN" misc_feature 28106..28111 /locus_tag="sars8b" /note="transcription regulatory sequence for mRNA9" gene 28120..29388 /gene="N" /locus_tag="sars9a" /db_xref="GeneID:1489678" CDS 28120..29388 /gene="N" /locus_tag="sars9a" /experiment="inhibits the activity of cyclin-CDK complex and blocks S phase progression in mammalian cells" /note="As established by Krokhin et al. (2003), the N-terminal methionine is removed, all other methionines are oxidized, and the resulting N-terminal serine is acetylated" /codon_start=1 /product="nucleocapsid protein" /protein_id="NP_828858.1" /db_xref="GI:29836503" /db_xref="GeneID:1489678" /translation="MSDNGPQSNQRSAPRITFGGPTDSTDNNQNGGRNGARPKQRRPQ GLPNNTASWFTALTQHGKEELRFPRGQGVPINTNSGPDDQIGYYRRATRRVRGGDGKM KELSPRWYFYYLGTGPEASLPYGANKEGIVWVATEGALNTPKDHIGTRNPNNNAATVL QLPQGTTLPKGFYAEGSRGGSQASSRSSSRSRGNSRNSTPGSSRGNSPARMASGGGET ALALLLLDRLNQLESKVSGKGQQQQGQTVTKKSAAEASKKPRQKRTATKQYNVTQAFG RRGPEQTQGNFGDQDLIRQGTDYKHWPQIAQFAPSASAFFGMSRIGMEVTPSGTWLTY HGAIKLDDKDPQFKDNVILLNKHIDAYKTFPPTEPKKDKKKKTDEAQPLPQRQKKQPT VTLLPAADMDDFSRQLQNSMSGASADSTQA" misc_feature 28123..28125 /gene="N" /locus_tag="sars9a" /experiment="experimental evidence, no additional details recorded" /note="acetylation site" misc_feature 28183..29202 /gene="N" /locus_tag="sars9a" /note="Coronavirus nucleocapsid protein; Region: Corona_nucleoca; pfam00937" /db_xref="CDD:64785" gene 28130..28426 /locus_tag="sars9b" /db_xref="GeneID:1489679" CDS 28130..28426 /locus_tag="sars9b" /inference="non-experimental evidence, no additional details recorded" /codon_start=1 /product="hypothetical protein sars9b" /protein_id="NP_828859.1" /db_xref="GI:29836502" /db_xref="GeneID:1489679" /translation="MDPNQTNVVPPALHLVDPQIQLTITRMEDAMGQGQNSADPKVYP IILRLGSQLSLSMARRNLDSLEARAFQSTPIVVQMTKLATTEELPDEFVVVTAK" 3'UTR 29389..29751 ORIGIN 1 atattaggtt tttacctacc caggaaaagc caaccaacct cgatctcttg tagatctgtt 61 ctctaaacga actttaaaat ctgtgtagct gtcgctcggc tgcatgccta gtgcacctac 121 gcagtataaa caataataaa ttttactgtc gttgacaaga aacgagtaac tcgtccctct 181 tctgcagact gcttacggtt tcgtccgtgt tgcagtcgat catcagcata cctaggtttc 241 gtccgggtgt gaccgaaagg taagatggag agccttgttc ttggtgtcaa cgagaaaaca 301 cacgtccaac tcagtttgcc tgtccttcag gttagagacg tgctagtgcg tggcttcggg 361 gactctgtgg aagaggccct atcggaggca cgtgaacacc tcaaaaatgg cacttgtggt 421 ctagtagagc tggaaaaagg cgtactgccc cagcttgaac agccctatgt gttcattaaa 481 cgttctgatg ccttaagcac caatcacggc cacaaggtcg ttgagctggt tgcagaaatg 541 gacggcattc agtacggtcg tagcggtata acactgggag tactcgtgcc acatgtgggc 601 gaaaccccaa ttgcataccg caatgttctt cttcgtaaga acggtaataa gggagccggt 661 ggtcatagct atggcatcga tctaaagtct tatgacttag gtgacgagct tggcactgat 721 cccattgaag attatgaaca aaactggaac actaagcatg gcagtggtgc actccgtgaa 781 ctcactcgtg agctcaatgg aggtgcagtc actcgctatg tcgacaacaa tttctgtggc 841 ccagatgggt accctcttga ttgcatcaaa gattttctcg cacgcgcggg caagtcaatg 901 tgcactcttt ccgaacaact tgattacatc gagtcgaaga gaggtgtcta ctgctgccgt 961 gaccatgagc atgaaattgc ctggttcact gagcgctctg ataagagcta cgagcaccag 1021 acacccttcg aaattaagag tgccaagaaa tttgacactt tcaaagggga atgcccaaag 1081 tttgtgtttc ctcttaactc aaaagtcaaa gtcattcaac cacgtgttga aaagaaaaag 1141 actgagggtt tcatggggcg tatacgctct gtgtaccctg ttgcatctcc acaggagtgt 1201 aacaatatgc acttgtctac cttgatgaaa tgtaatcatt gcgatgaagt ttcatggcag 1261 acgtgcgact ttctgaaagc cacttgtgaa cattgtggca ctgaaaattt agttattgaa 1321 ggacctacta catgtgggta cctacctact aatgctgtag tgaaaatgcc atgtcctgcc 1381 tgtcaagacc cagagattgg acctgagcat agtgttgcag attatcacaa ccactcaaac 1441 attgaaactc gactccgcaa gggaggtagg actagatgtt ttggaggctg tgtgtttgcc 1501 tatgttggct gctataataa gcgtgcctac tgggttcctc gtgctagtgc tgatattggc 1561 tcaggccata ctggcattac tggtgacaat gtggagacct tgaatgagga tctccttgag 1621 atactgagtc gtgaacgtgt taacattaac attgttggcg attttcattt gaatgaagag 1681 gttgccatca ttttggcatc tttctctgct tctacaagtg cctttattga cactataaag 1741 agtcttgatt acaagtcttt caaaaccatt gttgagtcct gcggtaacta taaagttacc 1801 aagggaaagc ccgtaaaagg tgcttggaac attggacaac agagatcagt tttaacacca 1861 ctgtgtggtt ttccctcaca ggctgctggt gttatcagat caatttttgc gcgcacactt 1921 gatgcagcaa accactcaat tcctgatttg caaagagcag ctgtcaccat acttgatggt 1981 atttctgaac agtcattacg tcttgtcgac gccatggttt atacttcaga cctgctcacc 2041 aacagtgtca ttattatggc atatgtaact ggtggtcttg tacaacagac ttctcagtgg 2101 ttgtctaatc ttttgggcac tactgttgaa aaactcaggc ctatctttga atggattgag 2161 gcgaaactta gtgcaggagt tgaatttctc aaggatgctt gggagattct caaatttctc 2221 attacaggtg tttttgacat cgtcaagggt caaatacagg ttgcttcaga taacatcaag 2281 gattgtgtaa aatgcttcat tgatgttgtt aacaaggcac tcgaaatgtg cattgatcaa 2341 gtcactatcg ctggcgcaaa gttgcgatca ctcaacttag gtgaagtctt catcgctcaa 2401 agcaagggac tttaccgtca gtgtatacgt ggcaaggagc agctgcaact actcatgcct 2461 cttaaggcac caaaagaagt aacctttctt gaaggtgatt cacatgacac agtacttacc 2521 tctgaggagg ttgttctcaa gaacggtgaa ctcgaagcac tcgagacgcc cgttgatagc 2581 ttcacaaatg gagctatcgt tggcacacca gtctgtgtaa atggcctcat gctcttagag 2641 attaaggaca aagaacaata ctgcgcattg tctcctggtt tactggctac aaacaatgtc 2701 tttcgcttaa aagggggtgc accaattaaa ggtgtaacct ttggagaaga tactgtttgg 2761 gaagttcaag gttacaagaa tgtgagaatc acatttgagc ttgatgaacg tgttgacaaa 2821 gtgcttaatg aaaagtgctc tgtctacact gttgaatccg gtaccgaagt tactgagttt 2881 gcatgtgttg tagcagaggc tgttgtgaag actttacaac cagtttctga tctccttacc 2941 aacatgggta ttgatcttga tgagtggagt gtagctacat tctacttatt tgatgatgct 3001 ggtgaagaaa acttttcatc acgtatgtat tgttcctttt accctccaga tgaggaagaa 3061 gaggacgatg cagagtgtga ggaagaagaa attgatgaaa cctgtgaaca tgagtacggt 3121 acagaggatg attatcaagg tctccctctg gaatttggtg cctcagctga aacagttcga 3181 gttgaggaag aagaagagga agactggctg gatgatacta ctgagcaatc agagattgag 3241 ccagaaccag aacctacacc tgaagaacca gttaatcagt ttactggtta tttaaaactt 3301 actgacaatg ttgccattaa atgtgttgac atcgttaagg aggcacaaag tgctaatcct 3361 atggtgattg taaatgctgc taacatacac ctgaaacatg gtggtggtgt agcaggtgca 3421 ctcaacaagg caaccaatgg tgccatgcaa aaggagagtg atgattacat taagctaaat 3481 ggccctctta cagtaggagg gtcttgtttg ctttctggac ataatcttgc taagaagtgt 3541 ctgcatgttg ttggacctaa cctaaatgca ggtgaggaca tccagcttct taaggcagca 3601 tatgaaaatt tcaattcaca ggacatctta cttgcaccat tgttgtcagc aggcatattt 3661 ggtgctaaac cacttcagtc tttacaagtg tgcgtgcaga cggttcgtac acaggtttat 3721 attgcagtca atgacaaagc tctttatgag caggttgtca tggattatct tgataacctg 3781 aagcctagag tggaagcacc taaacaagag gagccaccaa acacagaaga ttccaaaact 3841 gaggagaaat ctgtcgtaca gaagcctgtc gatgtgaagc caaaaattaa ggcctgcatt 3901 gatgaggtta ccacaacact ggaagaaact aagtttctta ccaataagtt actcttgttt 3961 gctgatatca atggtaagct ttaccatgat tctcagaaca tgcttagagg tgaagatatg 4021 tctttccttg agaaggatgc accttacatg gtaggtgatg ttatcactag tggtgatatc 4081 acttgtgttg taataccctc caaaaaggct ggtggcacta ctgagatgct ctcaagagct 4141 ttgaagaaag tgccagttga tgagtatata accacgtacc ctggacaagg atgtgctggt 4201 tatacacttg aggaagctaa gactgctctt aagaaatgca aatctgcatt ttatgtacta 4261 ccttcagaag cacctaatgc taaggaagag attctaggaa ctgtatcctg gaatttgaga 4321 gaaatgcttg ctcatgctga agagacaaga aaattaatgc ctatatgcat ggatgttaga 4381 gccataatgg caaccatcca acgtaagtat aaaggaatta aaattcaaga gggcatcgtt 4441 gactatggtg tccgattctt cttttatact agtaaagagc ctgtagcttc tattattacg 4501 aagctgaact ctctaaatga gccgcttgtc acaatgccaa ttggttatgt gacacatggt 4561 tttaatcttg aagaggctgc gcgctgtatg cgttctctta aagctcctgc cgtagtgtca 4621 gtatcatcac cagatgctgt tactacatat aatggatacc tcacttcgtc atcaaagaca 4681 tctgaggagc actttgtaga aacagtttct ttggctggct cttacagaga ttggtcctat 4741 tcaggacagc gtacagagtt aggtgttgaa tttcttaagc gtggtgacaa aattgtgtac 4801 cacactctgg agagccccgt cgagtttcat cttgacggtg aggttctttc acttgacaaa 4861 ctaaagagtc tcttatccct gcgggaggtt aagactataa aagtgttcac aactgtggac 4921 aacactaatc tccacacaca gcttgtggat atgtctatga catatggaca gcagtttggt 4981 ccaacatact tggatggtgc tgatgttaca aaaattaaac ctcatgtaaa tcatgagggt 5041 aagactttct ttgtactacc tagtgatgac acactacgta gtgaagcttt cgagtactac 5101 catactcttg atgagagttt tcttggtagg tacatgtctg ctttaaacca cacaaagaaa 5161 tggaaatttc ctcaagttgg tggtttaact tcaattaaat gggctgataa caattgttat 5221 ttgtctagtg ttttattagc acttcaacag cttgaagtca aattcaatgc accagcactt 5281 caagaggctt attatagagc ccgtgctggt gatgctgcta acttttgtgc actcatactc 5341 gcttacagta ataaaactgt tggcgagctt ggtgatgtca gagaaactat gacccatctt 5401 ctacagcatg ctaatttgga atctgcaaag cgagttctta atgtggtgtg taaacattgt 5461 ggtcagaaaa ctactacctt aacgggtgta gaagctgtga tgtatatggg tactctatct 5521 tatgataatc ttaagacagg tgtttccatt ccatgtgtgt gtggtcgtga tgctacacaa 5581 tatctagtac aacaagagtc ttcttttgtt atgatgtctg caccacctgc tgagtataaa 5641 ttacagcaag gtacattctt atgtgcgaat gagtacactg gtaactatca gtgtggtcat 5701 tacactcata taactgctaa ggagaccctc tatcgtattg acggagctca ccttacaaag 5761 atgtcagagt acaaaggacc agtgactgat gttttctaca aggaaacatc ttacactaca 5821 accatcaagc ctgtgtcgta taaactcgat ggagttactt acacagagat tgaaccaaaa 5881 ttggatgggt attataaaaa ggataatgct tactatacag agcagcctat agaccttgta 5941 ccaactcaac cattaccaaa tgcgagtttt gataatttca aactcacatg ttctaacaca 6001 aaatttgctg atgatttaaa tcaaatgaca ggcttcacaa agccagcttc acgagagcta 6061 tctgtcacat tcttcccaga cttgaatggc gatgtagtgg ctattgacta tagacactat 6121 tcagcgagtt tcaagaaagg tgctaaatta ctgcataagc caattgtttg gcacattaac 6181 caggctacaa ccaagacaac gttcaaacca aacacttggt gtttacgttg tctttggagt 6241 acaaagccag tagatacttc aaattcattt gaagttctgg cagtagaaga cacacaagga 6301 atggacaatc ttgcttgtga aagtcaacaa cccacctctg aagaagtagt ggaaaatcct 6361 accatacaga aggaagtcat agagtgtgac gtgaaaacta ccgaagttgt aggcaatgtc 6421 atacttaaac catcagatga aggtgttaaa gtaacacaag agttaggtca tgaggatctt 6481 atggctgctt atgtggaaaa cacaagcatt accattaaga aacctaatga gctttcacta 6541 gccttaggtt taaaaacaat tgccactcat ggtattgctg caattaatag tgttccttgg 6601 agtaaaattt tggcttatgt caaaccattc ttaggacaag cagcaattac aacatcaaat 6661 tgcgctaaga gattagcaca acgtgtgttt aacaattata tgccttatgt gtttacatta 6721 ttgttccaat tgtgtacttt tactaaaagt accaattcta gaattagagc ttcactacct 6781 acaactattg ctaaaaatag tgttaagagt gttgctaaat tatgtttgga tgccggcatt 6841 aattatgtga agtcacccaa attttctaaa ttgttcacaa tcgctatgtg gctattgttg 6901 ttaagtattt gcttaggttc tctaatctgt gtaactgctg cttttggtgt actcttatct 6961 aattttggtg ctccttctta ttgtaatggc gttagagaat tgtatcttaa ttcgtctaac 7021 gttactacta tggatttctg tgaaggttct tttccttgca gcatttgttt aagtggatta 7081 gactcccttg attcttatcc agctcttgaa accattcagg tgacgatttc atcgtacaag 7141 ctagacttga caattttagg tctggccgct gagtgggttt tggcatatat gttgttcaca 7201 aaattctttt atttattagg tctttcagct ataatgcagg tgttctttgg ctattttgct 7261 agtcatttca tcagcaattc ttggctcatg tggtttatca ttagtattgt acaaatggca 7321 cccgtttctg caatggttag gatgtacatc ttctttgctt ctttctacta catatggaag 7381 agctatgttc atatcatgga tggttgcacc tcttcgactt gcatgatgtg ctataagcgc 7441 aatcgtgcca cacgcgttga gtgtacaact attgttaatg gcatgaagag atctttctat 7501 gtctatgcaa atggaggccg tggcttctgc aagactcaca attggaattg tctcaattgt 7561 gacacatttt gcactggtag tacattcatt agtgatgaag ttgctcgtga tttgtcactc 7621 cagtttaaaa gaccaatcaa ccctactgac cagtcatcgt atattgttga tagtgttgct 7681 gtgaaaaatg gcgcgcttca cctctacttt gacaaggctg gtcaaaagac ctatgagaga 7741 catccgctct cccattttgt caatttagac aatttgagag ctaacaacac taaaggttca 7801 ctgcctatta atgtcatagt ttttgatggc aagtccaaat gcgacgagtc tgcttctaag 7861 tctgcttctg tgtactacag tcagctgatg tgccaaccta ttctgttgct tgaccaagct 7921 cttgtatcag acgttggaga tagtactgaa gtttccgtta agatgtttga tgcttatgtc 7981 gacacctttt cagcaacttt tagtgttcct atggaaaaac ttaaggcact tgttgctaca 8041 gctcacagcg agttagcaaa gggtgtagct ttagatggtg tcctttctac attcgtgtca 8101 gctgcccgac aaggtgttgt tgataccgat gttgacacaa aggatgttat tgaatgtctc 8161 aaactttcac atcactctga cttagaagtg acaggtgaca gttgtaacaa tttcatgctc 8221 acctataata aggttgaaaa catgacgccc agagatcttg gcgcatgtat tgactgtaat 8281 gcaaggcata tcaatgccca agtagcaaaa agtcacaatg tttcactcat ctggaatgta 8341 aaagactaca tgtctttatc tgaacagctg cgtaaacaaa ttcgtagtgc tgccaagaag 8401 aacaacatac cttttagact aacttgtgct acaactagac aggttgtcaa tgtcataact 8461 actaaaatct cactcaaggg tggtaagatt gttagtactt gttttaaact tatgcttaag 8521 gccacattat tgtgcgttct tgctgcattg gtttgttata tcgttatgcc agtacataca 8581 ttgtcaatcc atgatggtta cacaaatgaa atcattggtt acaaagccat tcaggatggt 8641 gtcactcgtg acatcatttc tactgatgat tgttttgcaa ataaacatgc tggttttgac 8701 gcatggttta gccagcgtgg tggttcatac aaaaatgaca aaagctgccc tgtagtagct 8761 gctatcatta caagagagat tggtttcata gtgcctggct taccgggtac tgtgctgaga 8821 gcaatcaatg gtgacttctt gcattttcta cctcgtgttt ttagtgctgt tggcaacatt 8881 tgctacacac cttccaaact cattgagtat agtgattttg ctacctctgc ttgcgttctt 8941 gctgctgagt gtacaatttt taaggatgct atgggcaaac ctgtgccata ttgttatgac 9001 actaatttgc tagagggttc tatttcttat agtgagcttc gtccagacac tcgttatgtg 9061 cttatggatg gttccatcat acagtttcct aacacttacc tggagggttc tgttagagta 9121 gtaacaactt ttgatgctga gtactgtaga catggtacat gcgaaaggtc agaagtaggt 9181 atttgcctat ctaccagtgg tagatgggtt cttaataatg agcattacag agctctatca 9241 ggagttttct gtggtgttga tgcgatgaat ctcatagcta acatctttac tcctcttgtg 9301 caacctgtgg gtgctttaga tgtgtctgct tcagtagtgg ctggtggtat tattgccata 9361 ttggtgactt gtgctgccta ctactttatg aaattcagac gtgtttttgg tgagtacaac 9421 catgttgttg ctgctaatgc acttttgttt ttgatgtctt tcactatact ctgtctggta 9481 ccagcttaca gctttctgcc gggagtctac tcagtctttt acttgtactt gacattctat 9541 ttcaccaatg atgtttcatt cttggctcac cttcaatggt ttgccatgtt ttctcctatt 9601 gtgccttttt ggataacagc aatctatgta ttctgtattt ctctgaagca ctgccattgg 9661 ttctttaaca actatcttag gaaaagagtc atgtttaatg gagttacatt tagtaccttc 9721 gaggaggctg ctttgtgtac ctttttgctc aacaaggaaa tgtacctaaa attgcgtagc 9781 gagacactgt tgccacttac acagtataac aggtatcttg ctctatataa caagtacaag 9841 tatttcagtg gagccttaga tactaccagc tatcgtgaag cagcttgctg ccacttagca 9901 aaggctctaa atgactttag caactcaggt gctgatgttc tctaccaacc accacagaca 9961 tcaatcactt ctgctgttct gcagagtggt tttaggaaaa tggcattccc gtcaggcaaa 10021 gttgaagggt gcatggtaca agtaacctgt ggaactacaa ctcttaatgg attgtggttg 10081 gatgacacag tatactgtcc aagacatgtc atttgcacag cagaagacat gcttaatcct 10141 aactatgaag atctgctcat tcgcaaatcc aaccatagct ttcttgttca ggctggcaat 10201 gttcaacttc gtgttattgg ccattctatg caaaattgtc tgcttaggct taaagttgat 10261 acttctaacc ctaagacacc caagtataaa tttgtccgta tccaacctgg tcaaacattt 10321 tcagttctag catgctacaa tggttcacca tctggtgttt atcagtgtgc catgagacct 10381 aatcatacca ttaaaggttc tttccttaat ggatcatgtg gtagtgttgg ttttaacatt 10441 gattatgatt gcgtgtcttt ctgctatatg catcatatgg agcttccaac aggagtacac 10501 gctggtactg acttagaagg taaattctat ggtccatttg ttgacagaca aactgcacag 10561 gctgcaggta cagacacaac cataacatta aatgttttgg catggctgta tgctgctgtt 10621 atcaatggtg ataggtggtt tcttaataga ttcaccacta ctttgaatga ctttaacctt 10681 gtggcaatga agtacaacta tgaacctttg acacaagatc atgttgacat attgggacct 10741 ctttctgctc aaacaggaat tgccgtctta gatatgtgtg ctgctttgaa agagctgctg 10801 cagaatggta tgaatggtcg tactatcctt ggtagcacta ttttagaaga tgagtttaca 10861 ccatttgatg ttgttagaca atgctctggt gttaccttcc aaggtaagtt caagaaaatt 10921 gttaagggca ctcatcattg gatgctttta actttcttga catcactatt gattcttgtt 10981 caaagtacac agtggtcact gtttttcttt gtttacgaga atgctttctt gccatttact 11041 cttggtatta tggcaattgc tgcatgtgct atgctgcttg ttaagcataa gcacgcattc 11101 ttgtgcttgt ttctgttacc ttctcttgca acagttgctt actttaatat ggtctacatg 11161 cctgctagct gggtgatgcg tatcatgaca tggcttgaat tggctgacac tagcttgtct 11221 ggttataggc ttaaggattg tgttatgtat gcttcagctt tagttttgct tattctcatg 11281 acagctcgca ctgtttatga tgatgctgct agacgtgttt ggacactgat gaatgtcatt 11341 acacttgttt acaaagtcta ctatggtaat gctttagatc aagctatttc catgtgggcc 11401 ttagttattt ctgtaacctc taactattct ggtgtcgtta cgactatcat gtttttagct 11461 agagctatag tgtttgtgtg tgttgagtat tacccattgt tatttattac tggcaacacc 11521 ttacagtgta tcatgcttgt ttattgtttc ttaggctatt gttgctgctg ctactttggc 11581 cttttctgtt tactcaaccg ttacttcagg cttactcttg gtgtttatga ctacttggtc 11641 tctacacaag aatttaggta tatgaactcc caggggcttt tgcctcctaa gagtagtatt 11701 gatgctttca agcttaacat taagttgttg ggtattggag gtaaaccatg tatcaaggtt 11761 gctactgtac agtctaaaat gtctgacgta aagtgcacat ctgtggtact gctctcggtt 11821 cttcaacaac ttagagtaga gtcatcttct aaattgtggg cacaatgtgt acaactccac 11881 aatgatattc ttcttgcaaa agacacaact gaagctttcg agaagatggt ttctcttttg 11941 tctgttttgc tatccatgca gggtgctgta gacattaata ggttgtgcga ggaaatgctc 12001 gataaccgtg ctactcttca ggctattgct tcagaattta gttctttacc atcatatgcc 12061 gcttatgcca ctgcccagga ggcctatgag caggctgtag ctaatggtga ttctgaagtc 12121 gttctcaaaa agttaaagaa atctttgaat gtggctaaat ctgagtttga ccgtgatgct 12181 gccatgcaac gcaagttgga aaagatggca gatcaggcta tgacccaaat gtacaaacag 12241 gcaagatctg aggacaagag ggcaaaagta actagtgcta tgcaaacaat gctcttcact 12301 atgcttagga agcttgataa tgatgcactt aacaacatta tcaacaatgc gcgtgatggt 12361 tgtgttccac tcaacatcat accattgact acagcagcca aactcatggt tgttgtccct 12421 gattatggta cctacaagaa cacttgtgat ggtaacacct ttacatatgc atctgcactc 12481 tgggaaatcc agcaagttgt tgatgcggat agcaagattg ttcaacttag tgaaattaac 12541 atggacaatt caccaaattt ggcttggcct cttattgtta cagctctaag agccaactca 12601 gctgttaaac tacagaataa tgaactgagt ccagtagcac tacgacagat gtcctgtgcg 12661 gctggtacca cacaaacagc ttgtactgat gacaatgcac ttgcctacta taacaattcg 12721 aagggaggta ggtttgtgct ggcattacta tcagaccacc aagatctcaa atgggctaga 12781 ttccctaaga gtgatggtac aggtacaatt tacacagaac tggaaccacc ttgtaggttt 12841 gttacagaca caccaaaagg gcctaaagtg aaatacttgt acttcatcaa aggcttaaac 12901 aacctaaata gaggtatggt gctgggcagt ttagctgcta cagtacgtct tcaggctgga 12961 aatgctacag aagtacctgc caattcaact gtgctttcct tctgtgcttt tgcagtagac 13021 cctgctaaag catataagga ttacctagca agtggaggac aaccaatcac caactgtgtg 13081 aagatgttgt gtacacacac tggtacagga caggcaatta ctgtaacacc agaagctaac 13141 atggaccaag agtcctttgg tggtgcttca tgttgtctgt attgtagatg ccacattgac 13201 catccaaatc ctaaaggatt ctgtgacttg aaaggtaagt acgtccaaat acctaccact 13261 tgtgctaatg acccagtggg ttttacactt agaaacacag tctgtaccgt ctgcggaatg 13321 tggaaaggtt atggctgtag ttgtgaccaa ctccgcgaac ccttgatgca gtctgcggat 13381 gcatcaacgt ttttaaacgg gtttgcggtg taagtgcagc ccgtcttaca ccgtgcggca 13441 caggcactag tactgatgtc gtctacaggg cttttgatat ttacaacgaa aaagttgctg 13501 gttttgcaaa gttcctaaaa actaattgct gtcgcttcca ggagaaggat gaggaaggca 13561 atttattaga ctcttacttt gtagttaaga ggcatactat gtctaactac caacatgaag 13621 agactattta taacttggtt aaagattgtc cagcggttgc tgtccatgac tttttcaagt 13681 ttagagtaga tggtgacatg gtaccacata tatcacgtca gcgtctaact aaatacacaa 13741 tggctgattt agtctatgct ctacgtcatt ttgatgaggg taattgtgat acattaaaag 13801 aaatactcgt cacatacaat tgctgtgatg atgattattt caataagaag gattggtatg 13861 acttcgtaga gaatcctgac atcttacgcg tatatgctaa cttaggtgag cgtgtacgcc 13921 aatcattatt aaagactgta caattctgcg atgctatgcg tgatgcaggc attgtaggcg 13981 tactgacatt agataatcag gatcttaatg ggaactggta cgatttcggt gatttcgtac 14041 aagtagcacc aggctgcgga gttcctattg tggattcata ttactcattg ctgatgccca 14101 tcctcacttt gactagggca ttggctgctg agtcccatat ggatgctgat ctcgcaaaac 14161 cacttattaa gtgggatttg ctgaaatatg attttacgga agagagactt tgtctcttcg 14221 accgttattt taaatattgg gaccagacat accatcccaa ttgtattaac tgtttggatg 14281 ataggtgtat ccttcattgt gcaaacttta atgtgttatt ttctactgtg tttccaccta 14341 caagttttgg accactagta agaaaaatat ttgtagatgg tgttcctttt gttgtttcaa 14401 ctggatacca ttttcgtgag ttaggagtcg tacataatca ggatgtaaac ttacatagct 14461 cgcgtctcag tttcaaggaa cttttagtgt atgctgctga tccagctatg catgcagctt 14521 ctggcaattt attgctagat aaacgcacta catgcttttc agtagctgca ctaacaaaca 14581 atgttgcttt tcaaactgtc aaacccggta attttaataa agacttttat gactttgctg 14641 tgtctaaagg tttctttaag gaaggaagtt ctgttgaact aaaacacttc ttctttgctc 14701 aggatggcaa cgctgctatc agtgattatg actattatcg ttataatctg ccaacaatgt 14761 gtgatatcag acaactccta ttcgtagttg aagttgttga taaatacttt gattgttacg 14821 atggtggctg tattaatgcc aaccaagtaa tcgttaacaa tctggataaa tcagctggtt 14881 tcccatttaa taaatggggt aaggctagac tttattatga ctcaatgagt tatgaggatc 14941 aagatgcact tttcgcgtat actaagcgta atgtcatccc tactataact caaatgaatc 15001 ttaagtatgc cattagtgca aagaatagag ctcgcaccgt agctggtgtc tctatctgta 15061 gtactatgac aaatagacag tttcatcaga aattattgaa gtcaatagcc gccactagag 15121 gagctactgt ggtaattgga acaagcaagt tttacggtgg ctggcataat atgttaaaaa 15181 ctgtttacag tgatgtagaa actccacacc ttatgggttg ggattatcca aaatgtgaca 15241 gagccatgcc taacatgctt aggataatgg cctctcttgt tcttgctcgc aaacataaca 15301 cttgctgtaa cttatcacac cgtttctaca ggttagctaa cgagtgtgcg caagtattaa 15361 gtgagatggt catgtgtggc ggctcactat atgttaaacc aggtggaaca tcatccggtg 15421 atgctacaac tgcttatgct aatagtgtct ttaacatttg tcaagctgtt acagccaatg 15481 taaatgcact tctttcaact gatggtaata agatagctga caagtatgtc cgcaatctac 15541 aacacaggct ctatgagtgt ctctatagaa atagggatgt tgatcatgaa ttcgtggatg 15601 agttttacgc ttacctgcgt aaacatttct ccatgatgat tctttctgat gatgccgttg 15661 tgtgctataa cagtaactat gcggctcaag gtttagtagc tagcattaag aactttaagg 15721 cagttcttta ttatcaaaat aatgtgttca tgtctgaggc aaaatgttgg actgagactg 15781 accttactaa aggacctcac gaattttgct cacagcatac aatgctagtt aaacaaggag 15841 atgattacgt gtacctgcct tacccagatc catcaagaat attaggcgca ggctgttttg 15901 tcgatgatat tgtcaaaaca gatggtacac ttatgattga aaggttcgtg tcactggcta 15961 ttgatgctta cccacttaca aaacatccta atcaggagta tgctgatgtc tttcacttgt 16021 atttacaata cattagaaag ttacatgatg agcttactgg ccacatgttg gacatgtatt 16081 ccgtaatgct aactaatgat aacacctcac ggtactggga acctgagttt tatgaggcta 16141 tgtacacacc acatacagtc ttgcaggctg taggtgcttg tgtattgtgc aattcacaga 16201 cttcacttcg ttgcggtgcc tgtattagga gaccattcct atgttgcaag tgctgctatg 16261 accatgtcat ttcaacatca cacaaattag tgttgtctgt taatccctat gtttgcaatg 16321 ccccaggttg tgatgtcact gatgtgacac aactgtatct aggaggtatg agctattatt 16381 gcaagtcaca taagcctccc attagttttc cattatgtgc taatggtcag gtttttggtt 16441 tatacaaaaa cacatgtgta ggcagtgaca atgtcactga cttcaatgcg atagcaacat 16501 gtgattggac taatgctggc gattacatac ttgccaacac ttgtactgag agactcaagc 16561 ttttcgcagc agaaacgctc aaagccactg aggaaacatt taagctgtca tatggtattg 16621 ccactgtacg cgaagtactc tctgacagag aattgcatct ttcatgggag gttggaaaac 16681 ctagaccacc attgaacaga aactatgtct ttactggtta ccgtgtaact aaaaatagta 16741 aagtacagat tggagagtac acctttgaaa aaggtgacta tggtgatgct gttgtgtaca 16801 gaggtactac gacatacaag ttgaatgttg gtgattactt tgtgttgaca tctcacactg 16861 taatgccact tagtgcacct actctagtgc cacaagagca ctatgtgaga attactggct 16921 tgtacccaac actcaacatc tcagatgagt tttctagcaa tgttgcaaat tatcaaaagg 16981 tcggcatgca aaagtactct acactccaag gaccacctgg tactggtaag agtcattttg 17041 ccatcggact tgctctctat tacccatctg ctcgcatagt gtatacggca tgctctcatg 17101 cagctgttga tgccctatgt gaaaaggcat taaaatattt gcccatagat aaatgtagta 17161 gaatcatacc tgcgcgtgcg cgcgtagagt gttttgataa attcaaagtg aattcaacac 17221 tagaacagta tgttttctgc actgtaaatg cattgccaga aacaactgct gacattgtag 17281 tctttgatga aatctctatg gctactaatt atgacttgag tgttgtcaat gctagacttc 17341 gtgcaaaaca ctacgtctat attggcgatc ctgctcaatt accagccccc cgcacattgc 17401 tgactaaagg cacactagaa ccagaatatt ttaattcagt gtgcagactt atgaaaacaa 17461 taggtccaga catgttcctt ggaacttgtc gccgttgtcc tgctgaaatt gttgacactg 17521 tgagtgcttt agtttatgac aataagctaa aagcacacaa ggataagtca gctcaatgct 17581 tcaaaatgtt ctacaaaggt gttattacac atgatgtttc atctgcaatc aacagacctc 17641 aaataggcgt tgtaagagaa tttcttacac gcaatcctgc ttggagaaaa gctgttttta 17701 tctcacctta taattcacag aacgctgtag cttcaaaaat cttaggattg cctacgcaga 17761 ctgttgattc atcacagggt tctgaatatg actatgtcat attcacacaa actactgaaa 17821 cagcacactc ttgtaatgtc aaccgcttca atgtggctat cacaagggca aaaattggca 17881 ttttgtgcat aatgtctgat agagatcttt atgacaaact gcaatttaca agtctagaaa 17941 taccacgtcg caatgtggct acattacaag cagaaaatgt aactggactt tttaaggact 18001 gtagtaagat cattactggt cttcatccta cacaggcacc tacacacctc agcgttgata 18061 taaagttcaa gactgaagga ttatgtgttg acataccagg cataccaaag gacatgacct 18121 accgtagact catctctatg atgggtttca aaatgaatta ccaagtcaat ggttacccta 18181 atatgtttat cacccgcgaa gaagctattc gtcacgttcg tgcgtggatt ggctttgatg 18241 tagagggctg tcatgcaact agagatgctg tgggtactaa cctacctctc cagctaggat 18301 tttctacagg tgttaactta gtagctgtac cgactggtta tgttgacact gaaaataaca 18361 cagaattcac cagagttaat gcaaaacctc caccaggtga ccagtttaaa catcttatac 18421 cactcatgta taaaggcttg ccctggaatg tagtgcgtat taagatagta caaatgctca 18481 gtgatacact gaaaggattg tcagacagag tcgtgttcgt cctttgggcg catggctttg 18541 agcttacatc aatgaagtac tttgtcaaga ttggacctga aagaacgtgt tgtctgtgtg 18601 acaaacgtgc aacttgcttt tctacttcat cagatactta tgcctgctgg aatcattctg 18661 tgggttttga ctatgtctat aacccattta tgattgatgt tcagcagtgg ggctttacgg 18721 gtaaccttca gagtaaccat gaccaacatt gccaggtaca tggaaatgca catgtggcta 18781 gttgtgatgc tatcatgact agatgtttag cagtccatga gtgctttgtt aagcgcgttg 18841 attggtctgt tgaataccct attataggag atgaactgag ggttaattct gcttgcagaa 18901 aagtacaaca catggttgtg aagtctgcat tgcttgctga taagtttcca gttcttcatg 18961 acattggaaa tccaaaggct atcaagtgtg tgcctcaggc tgaagtagaa tggaagttct 19021 acgatgctca gccatgtagt gacaaagctt acaaaataga ggaactcttc tattcttatg 19081 ctacacatca cgataaattc actgatggtg tttgtttgtt ttggaattgt aacgttgatc 19141 gttacccagc caatgcaatt gtgtgtaggt ttgacacaag agtcttgtca aacttgaact 19201 taccaggctg tgatggtggt agtttgtatg tgaataagca tgcattccac actccagctt 19261 tcgataaaag tgcatttact aatttaaagc aattgccttt cttttactat tctgatagtc 19321 cttgtgagtc tcatggcaaa caagtagtgt cggatattga ttatgttcca ctcaaatctg 19381 ctacgtgtat tacacgatgc aatttaggtg gtgctgtttg cagacaccat gcaaatgagt 19441 accgacagta cttggatgca tataatatga tgatttctgc tggatttagc ctatggattt 19501 acaaacaatt tgatacttat aacctgtgga atacatttac caggttacag agtttagaaa 19561 atgtggctta taatgttgtt aataaaggac actttgatgg acacgccggc gaagcacctg 19621 tttccatcat taataatgct gtttacacaa aggtagatgg tattgatgtg gagatctttg 19681 aaaataagac aacacttcct gttaatgttg catttgagct ttgggctaag cgtaacatta 19741 aaccagtgcc agagattaag atactcaata atttgggtgt tgatatcgct gctaatactg 19801 taatctggga ctacaaaaga gaagccccag cacatgtatc tacaataggt gtctgcacaa 19861 tgactgacat tgccaagaaa cctactgaga gtgcttgttc ttcacttact gtcttgtttg 19921 atggtagagt ggaaggacag gtagaccttt ttagaaacgc ccgtaatggt gttttaataa 19981 cagaaggttc agtcaaaggt ctaacacctt caaagggacc agcacaagct agcgtcaatg 20041 gagtcacatt aattggagaa tcagtaaaaa cacagtttaa ctactttaag aaagtagacg 20101 gcattattca acagttgcct gaaacctact ttactcagag cagagactta gaggatttta 20161 agcccagatc acaaatggaa actgactttc tcgagctcgc tatggatgaa ttcatacagc 20221 gatataagct cgagggctat gccttcgaac acatcgttta tggagatttc agtcatggac 20281 aacttggcgg tcttcattta atgataggct tagccaagcg ctcacaagat tcaccactta 20341 aattagagga ttttatccct atggacagca cagtgaaaaa ttacttcata acagatgcgc 20401 aaacaggttc atcaaaatgt gtgtgttctg tgattgatct tttacttgat gactttgtcg 20461 agataataaa gtcacaagat ttgtcagtga tttcaaaagt ggtcaaggtt acaattgact 20521 atgctgaaat ttcattcatg ctttggtgta aggatggaca tgttgaaacc ttctacccaa 20581 aactacaagc aagtcaagcg tggcaaccag gtgttgcgat gcctaacttg tacaagatgc 20641 aaagaatgct tcttgaaaag tgtgaccttc agaattatgg tgaaaatgct gttataccaa 20701 aaggaataat gatgaatgtc gcaaagtata ctcaactgtg tcaatactta aatacactta 20761 ctttagctgt accctacaac atgagagtta ttcactttgg tgctggctct gataaaggag 20821 ttgcaccagg tacagctgtg ctcagacaat ggttgccaac tggcacacta cttgtcgatt 20881 cagatcttaa tgacttcgtc tccgacgcag attctacttt aattggagac tgtgcaacag 20941 tacatacggc taataaatgg gaccttatta ttagcgatat gtatgaccct aggaccaaac 21001 atgtgacaaa agagaatgac tctaaagaag ggtttttcac ttatctgtgt ggatttataa 21061 agcaaaaact agccctgggt ggttctatag ctgtaaagat aacagagcat tcttggaatg 21121 ctgaccttta caagcttatg ggccatttct catggtggac agcttttgtt acaaatgtaa 21181 atgcatcatc atcggaagca tttttaattg gggctaacta tcttggcaag ccgaaggaac 21241 aaattgatgg ctataccatg catgctaact acattttctg gaggaacaca aatcctatcc 21301 agttgtcttc ctattcactc tttgacatga gcaaatttcc tcttaaatta agaggaactg 21361 ctgtaatgtc tcttaaggag aatcaaatca atgatatgat ttattctctt ctggaaaaag 21421 gtaggcttat cattagagaa aacaacagag ttgtggtttc aagtgatatt cttgttaaca 21481 actaaacgaa catgtttatt ttcttattat ttcttactct cactagtggt agtgaccttg 21541 accggtgcac cacttttgat gatgttcaag ctcctaatta cactcaacat acttcatcta 21601 tgaggggggt ttactatcct gatgaaattt ttagatcaga cactctttat ttaactcagg 21661 atttatttct tccattttat tctaatgtta cagggtttca tactattaat catacgtttg 21721 gcaaccctgt catacctttt aaggatggta tttattttgc tgccacagag aaatcaaatg 21781 ttgtccgtgg ttgggttttt ggttctacca tgaacaacaa gtcacagtcg gtgattatta 21841 ttaacaattc tactaatgtt gttatacgag catgtaactt tgaattgtgt gacaaccctt 21901 tctttgctgt ttctaaaccc atgggtacac agacacatac tatgatattc gataatgcat 21961 ttaattgcac tttcgagtac atatctgatg ccttttcgct tgatgtttca gaaaagtcag 22021 gtaattttaa acacttacga gagtttgtgt ttaaaaataa agatgggttt ctctatgttt 22081 ataagggcta tcaacctata gatgtagttc gtgatctacc ttctggtttt aacactttga 22141 aacctatttt taagttgcct cttggtatta acattacaaa ttttagagcc attcttacag 22201 ccttttcacc tgctcaagac atttggggca cgtcagctgc agcctatttt gttggctatt 22261 taaagccaac tacatttatg ctcaagtatg atgaaaatgg tacaatcaca gatgctgttg 22321 attgttctca aaatccactt gctgaactca aatgctctgt taagagcttt gagattgaca 22381 aaggaattta ccagacctct aatttcaggg ttgttccctc aggagatgtt gtgagattcc 22441 ctaatattac aaacttgtgt ccttttggag aggtttttaa tgctactaaa ttcccttctg 22501 tctatgcatg ggagagaaaa aaaatttcta attgtgttgc tgattactct gtgctctaca 22561 actcaacatt tttttcaacc tttaagtgct atggcgtttc tgccactaag ttgaatgatc 22621 tttgcttctc caatgtctat gcagattctt ttgtagtcaa gggagatgat gtaagacaaa 22681 tagcgccagg acaaactggt gttattgctg attataatta taaattgcca gatgatttca 22741 tgggttgtgt ccttgcttgg aatactagga acattgatgc tacttcaact ggtaattata 22801 attataaata taggtatctt agacatggca agcttaggcc ctttgagaga gacatatcta 22861 atgtgccttt ctcccctgat ggcaaacctt gcaccccacc tgctcttaat tgttattggc 22921 cattaaatga ttatggtttt tacaccacta ctggcattgg ctaccaacct tacagagttg 22981 tagtactttc ttttgaactt ttaaatgcac cggccacggt ttgtggacca aaattatcca 23041 ctgaccttat taagaaccag tgtgtcaatt ttaattttaa tggactcact ggtactggtg 23101 tgttaactcc ttcttcaaag agatttcaac catttcaaca atttggccgt gatgtttctg 23161 atttcactga ttccgttcga gatcctaaaa catctgaaat attagacatt tcaccttgcg 23221 cttttggggg tgtaagtgta attacacctg gaacaaatgc ttcatctgaa gttgctgttc 23281 tatatcaaga tgttaactgc actgatgttt ctacagcaat tcatgcagat caactcacac 23341 cagcttggcg catatattct actggaaaca atgtattcca gactcaagca ggctgtctta 23401 taggagctga gcatgtcgac acttcttatg agtgcgacat tcctattgga gctggcattt 23461 gtgctagtta ccatacagtt tctttattac gtagtactag ccaaaaatct attgtggctt 23521 atactatgtc tttaggtgct gatagttcaa ttgcttactc taataacacc attgctatac 23581 ctactaactt ttcaattagc attactacag aagtaatgcc tgtttctatg gctaaaacct 23641 ccgtagattg taatatgtac atctgcggag attctactga atgtgctaat ttgcttctcc 23701 aatatggtag cttttgcaca caactaaatc gtgcactctc aggtattgct gctgaacagg 23761 atcgcaacac acgtgaagtg ttcgctcaag tcaaacaaat gtacaaaacc ccaactttga 23821 aatattttgg tggttttaat ttttcacaaa tattacctga ccctctaaag ccaactaaga 23881 ggtcttttat tgaggacttg ctctttaata aggtgacact cgctgatgct ggcttcatga 23941 agcaatatgg cgaatgccta ggtgatatta atgctagaga tctcatttgt gcgcagaagt 24001 tcaatggact tacagtgttg ccacctctgc tcactgatga tatgattgct gcctacactg 24061 ctgctctagt tagtggtact gccactgctg gatggacatt tggtgctggc gctgctcttc 24121 aaataccttt tgctatgcaa atggcatata ggttcaatgg cattggagtt acccaaaatg 24181 ttctctatga gaaccaaaaa caaatcgcca accaatttaa caaggcgatt agtcaaattc 24241 aagaatcact tacaacaaca tcaactgcat tgggcaagct gcaagacgtt gttaaccaga 24301 atgctcaagc attaaacaca cttgttaaac aacttagctc taattttggt gcaatttcaa 24361 gtgtgctaaa tgatatcctt tcgcgacttg ataaagtcga ggcggaggta caaattgaca 24421 ggttaattac aggcagactt caaagccttc aaacctatgt aacacaacaa ctaatcaggg 24481 ctgctgaaat cagggcttct gctaatcttg ctgctactaa aatgtctgag tgtgttcttg 24541 gacaatcaaa aagagttgac ttttgtggaa agggctacca ccttatgtcc ttcccacaag 24601 cagccccgca tggtgttgtc ttcctacatg tcacgtatgt gccatcccag gagaggaact 24661 tcaccacagc gccagcaatt tgtcatgaag gcaaagcata cttccctcgt gaaggtgttt 24721 ttgtgtttaa tggcacttct tggtttatta cacagaggaa cttcttttct ccacaaataa 24781 ttactacaga caatacattt gtctcaggaa attgtgatgt cgttattggc atcattaaca 24841 acacagttta tgatcctctg caacctgagc ttgactcatt caaagaagag ctggacaagt 24901 acttcaaaaa tcatacatca ccagatgttg atcttggcga catttcaggc attaacgctt 24961 ctgtcgtcaa cattcaaaaa gaaattgacc gcctcaatga ggtcgctaaa aatttaaatg 25021 aatcactcat tgaccttcaa gaattgggaa aatatgagca atatattaaa tggccttggt 25081 atgtttggct cggcttcatt gctggactaa ttgccatcgt catggttaca atcttgcttt 25141 gttgcatgac tagttgttgc agttgcctca agggtgcatg ctcttgtggt tcttgctgca 25201 agtttgatga ggatgactct gagccagttc tcaagggtgt caaattacat tacacataaa 25261 cgaacttatg gatttgttta tgagattttt tactcttaga tcaattactg cacagccagt 25321 aaaaattgac aatgcttctc ctgcaagtac tgttcatgct acagcaacga taccgctaca 25381 agcctcactc cctttcggat ggcttgttat tggcgttgca tttcttgctg tttttcagag 25441 cgctaccaaa ataattgcgc tcaataaaag atggcagcta gccctttata agggcttcca 25501 gttcatttgc aatttactgc tgctatttgt taccatctat tcacatcttt tgcttgtcgc 25561 tgcaggtatg gaggcgcaat ttttgtacct ctatgccttg atatattttc tacaatgcat 25621 caacgcatgt agaattatta tgagatgttg gctttgttgg aagtgcaaat ccaagaaccc 25681 attactttat gatgccaact actttgtttg ctggcacaca cataactatg actactgtat 25741 accatataac agtgtcacag atacaattgt cgttactgaa ggtgacggca tttcaacacc 25801 aaaactcaaa gaagactacc aaattggtgg ttattctgag gataggcact caggtgttaa 25861 agactatgtc gttgtacatg gctatttcac cgaagtttac taccagcttg agtctacaca 25921 aattactaca gacactggta ttgaaaatgc tacattcttc atctttaaca agcttgttaa 25981 agacccaccg aatgtgcaaa tacacacaat cgacggctct tcaggagttg ctaatccagc 26041 aatggatcca atttatgatg agccgacgac gactactagc gtgcctttgt aagcacaaga 26101 aagtgagtac gaacttatgt actcattcgt ttcggaagaa acaggtacgt taatagttaa 26161 tagcgtactt ctttttcttg ctttcgtggt attcttgcta gtcacactag ccatccttac 26221 tgcgcttcga ttgtgtgcgt actgctgcaa tattgttaac gtgagtttag taaaaccaac 26281 ggtttacgtc tactcgcgtg ttaaaaatct gaactcttct gaaggagttc ctgatcttct 26341 ggtctaaacg aactaactat tattattatt ctgtttggaa ctttaacatt gcttatcatg 26401 gcagacaacg gtactattac cgttgaggag cttaaacaac tcctggaaca atggaaccta 26461 gtaataggtt tcctattcct agcctggatt atgttactac aatttgccta ttctaatcgg 26521 aacaggtttt tgtacataat aaagcttgtt ttcctctggc tcttgtggcc agtaacactt 26581 gcttgttttg tgcttgctgc tgtctacaga attaattggg tgactggcgg gattgcgatt 26641 gcaatggctt gtattgtagg cttgatgtgg cttagctact tcgttgcttc cttcaggctg 26701 tttgctcgta cccgctcaat gtggtcattc aacccagaaa caaacattct tctcaatgtg 26761 cctctccggg ggacaattgt gaccagaccg ctcatggaaa gtgaacttgt cattggtgct 26821 gtgatcattc gtggtcactt gcgaatggcc ggacactccc tagggcgctg tgacattaag 26881 gacctgccaa aagagatcac tgtggctaca tcacgaacgc tttcttatta caaattagga 26941 gcgtcgcagc gtgtaggcac tgattcaggt tttgctgcat acaaccgcta ccgtattgga 27001 aactataaat taaatacaga ccacgccggt agcaacgaca atattgcttt gctagtacag 27061 taagtgacaa cagatgtttc atcttgttga cttccaggtt acaatagcag agatattgat 27121 tatcattatg aggactttca ggattgctat ttggaatctt gacgttataa taagttcaat 27181 agtgagacaa ttatttaagc ctctaactaa gaagaattat tcggagttag atgatgaaga 27241 acctatggag ttagattatc cataaaacga acatgaaaat tattctcttc ctgacattga 27301 ttgtatttac atcttgcgag ctatatcact atcaggagtg tgttagaggt acgactgtac 27361 tactaaaaga accttgccca tcaggaacat acgagggcaa ttcaccattt caccctcttg 27421 ctgacaataa atttgcacta acttgcacta gcacacactt tgcttttgct tgtgctgacg 27481 gtactcgaca tacctatcag ctgcgtgcaa gatcagtttc accaaaactt ttcatcagac 27541 aagaggaggt tcaacaagag ctctactcgc cactttttct cattgttgct gctctagtat 27601 ttttaatact ttgcttcacc attaagagaa agacagaatg aatgagctca ctttaattga 27661 cttctatttg tgctttttag cctttctgct attccttgtt ttaataatgc ttattatatt 27721 ttggttttca ctcgaaatcc aggatctaga agaaccttgt accaaagtct aaacgaacat 27781 gaaacttctc attgttttga cttgtatttc tctatgcagt tgcatatgca ctgtagtaca 27841 gcgctgtgca tctaataaac ctcatgtgct tgaagatcct tgtaaggtac aacactaggg 27901 gtaatactta tagcactgct tggctttgtg ctctaggaaa ggttttacct tttcatagat 27961 ggcacactat ggttcaaaca tgcacaccta atgttactat caactgtcaa gatccagctg 28021 gtggtgcgct tatagctagg tgttggtacc ttcatgaagg tcaccaaact gctgcattta 28081 gagacgtact tgttgtttta aataaacgaa caaattaaaa tgtctgataa tggaccccaa 28141 tcaaaccaac gtagtgcccc ccgcattaca tttggtggac ccacagattc aactgacaat 28201 aaccagaatg gaggacgcaa tggggcaagg ccaaaacagc gccgacccca aggtttaccc 28261 aataatactg cgtcttggtt cacagctctc actcagcatg gcaaggagga acttagattc 28321 cctcgaggcc agggcgttcc aatcaacacc aatagtggtc cagatgacca aattggctac 28381 taccgaagag ctacccgacg agttcgtggt ggtgacggca aaatgaaaga gctcagcccc 28441 agatggtact tctattacct aggaactggc ccagaagctt cacttcccta cggcgctaac 28501 aaagaaggca tcgtatgggt tgcaactgag ggagccttga atacacccaa agaccacatt 28561 ggcacccgca atcctaataa caatgctgcc accgtgctac aacttcctca aggaacaaca 28621 ttgccaaaag gcttctacgc agagggaagc agaggcggca gtcaagcctc ttctcgctcc 28681 tcatcacgta gtcgcggtaa ttcaagaaat tcaactcctg gcagcagtag gggaaattct 28741 cctgctcgaa tggctagcgg aggtggtgaa actgccctcg cgctattgct gctagacaga 28801 ttgaaccagc ttgagagcaa agtttctggt aaaggccaac aacaacaagg ccaaactgtc 28861 actaagaaat ctgctgctga ggcatctaaa aagcctcgcc aaaaacgtac tgccacaaaa 28921 cagtacaacg tcactcaagc atttgggaga cgtggtccag aacaaaccca aggaaatttc 28981 ggggaccaag acctaatcag acaaggaact gattacaaac attggccgca aattgcacaa 29041 tttgctccaa gtgcctctgc attctttgga atgtcacgca ttggcatgga agtcacacct 29101 tcgggaacat ggctgactta tcatggagcc attaaattgg atgacaaaga tccacaattc 29161 aaagacaacg tcatactgct gaacaagcac attgacgcat acaaaacatt cccaccaaca 29221 gagcctaaaa aggacaaaaa gaaaaagact gatgaagctc agcctttgcc gcagagacaa 29281 aagaagcagc ccactgtgac tcttcttcct gcggctgaca tggatgattt ctccagacaa 29341 cttcaaaatt ccatgagtgg agcttctgct gattcaactc aggcataaac actcatgatg 29401 accacacaag gcagatgggc tatgtaaacg ttttcgcaat tccgtttacg atacatagtc 29461 tactcttgtg cagaatgaat tctcgtaact aaacagcaca agtaggttta gttaacttta 29521 atctcacata gcaatcttta atcaatgtgt aacattaggg aggacttgaa agagccacca 29581 cattttcatc gaggccacgc ggagtacgat cgagggtaca gtgaataatg ctagggagag 29641 ctgcctatat ggaagagccc taatgtgtaa aattaatttt agtagtgcta tccccatgtg 29701 attttaatag cttcttagga gaatgacaaa aaaaaaaaaa aaaaaaaaaa a // Gdraw2-v0.0.3/t/circ.t000444001750001750 445012001671021 14505 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use common::sense; use Cairo; use Gdraw2::CairoTrackPage; use Gdraw2::CairoTrackGroup; use Gdraw2::CairoTrack; use Gdraw2::Element::CairoTagset; use Gdraw2::Element::CairoBlock; use Gdraw2::Element::CairoRuler; use Gdraw2::Util::RGBAColor; my $surface = Cairo::SvgSurface->create( 'circ.svg', 600, 600 ); my $cr = Cairo::Context->create($surface); my $page = Gdraw2::CairoTrackPage->new( cairoContext => $cr, width => 600, height => 600, textFont => 'Arial', textSize => 8, isCircular => 1 ); my $groupA = Gdraw2::CairoTrackGroup->new( start => 1, end => 1000 ); $page->addChild($groupA); my $track_ruler = Gdraw2::CairoTrack->new( start => 1, end => 750, showGuideLine => 0 ); $groupA->addChild($track_ruler); my $ruler = Gdraw2::Element::CairoRuler->new( position => [ 1, 750 ], gridLength => 100 ); $track_ruler->addChild($ruler); my $trackA1 = Gdraw2::CairoTrack->new( start => 1, end => 750 ); $groupA->addChild($trackA1); for my $pos ( 1, 50, 100, 250, 500, 600, 700, 750 ) { my $tag = Gdraw2::Element::CairoTagset->new( position => [$pos,$pos+5,$pos+10], displayName => "tag_$pos", ); $trackA1->addChild($tag); } for my $pos ( 1 .. 5 ) { my $start = $pos * 100 + 1; my $end = $start + 150 - 1; my $block = Gdraw2::Element::CairoBlock->new( elementAnchor => 'center', strand => $pos % 2 == 0 ? 1 : -1, fillColor => Gdraw2::Util::RGBAColor->new( 0, 1, 1, 0.5 ), position => [ $start, $end - 70, $end - 60, $end ], displayName => "block $start-$end" ); $trackA1->addChild($block); } for my $pos ( 1 .. 5 ) { my $start = $pos * 100 + 1; my $end = $start + 3 - 1; my $block = Gdraw2::Element::CairoBlock->new( elementAnchor => 'center', strand => $pos % 2 == 0 ? 1 : -1, fillColor => Gdraw2::Util::RGBAColor->new( 1, 0, 1, 0.5 ), position => [ $start, $end ], displayName => "short $start-$end" ); $trackA1->addChild($block); } $trackA1->addChild( Gdraw2::Element::CairoBlock->new( position => [ -50, 50 ], strand => 1, fillColor => Gdraw2::Util::RGBAColor->new( 1, 0, 0, 0.5 ), ) ); $trackA1->addChild( Gdraw2::Element::CairoBlock->new( position => [ 700, 800 ], strand => -1, fillColor => Gdraw2::Util::RGBAColor->new( 1, 0, 0, 0.5 ), ) ); $page->draw; Gdraw2-v0.0.3/t/circ_mapping.t000555001750001750 226712001671021 16227 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use common::sense; use Gdraw2::CairoTrack; use Gdraw2::CairoTrackGroup; use Gdraw2::CairoTrackPage; use Gdraw2::Element::CairoMapping; use Gdraw2::Util::RGBAColor; use Math::Trig qw/pi pi2/; my $surface = Cairo::SvgSurface->create( 'circ_mapping.svg', 600, 600 ); my $cr = Cairo::Context->create($surface); my $page = Gdraw2::CairoTrackPage->new( cairoContext => $cr, width => 600, height => 600, groupDistance => 50, textFont => 'Arial', textSize => 8, isCircular => 1 ); my $groupA = Gdraw2::CairoTrackGroup->new( start => 1, end => 1000 ); $page->addChild($groupA); my $trackA = Gdraw2::CairoTrack->new( start => 1, end => 1000 ); $groupA->addChild($trackA); my $groupB = Gdraw2::CairoTrackGroup->new( start => 1, end => 100, circEndIndent => pi * 1.7 ); $page->addChild($groupB); my $trackB = Gdraw2::CairoTrack->new( start => 1, end => 100 ); $groupB->addChild($trackB); my $map = Gdraw2::Element::CairoMapping->new( position => [1,100], extStart => 25, extEnd => 125, extGroupIndex => 0, extTrackIndex => 0, fillColor => Gdraw2::Util::RGBAColor->new(1,0,1,0) ); $trackB->addChild($map); $page->draw; Gdraw2-v0.0.3/t/load.t000555001750001750 62212001671021 14464 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use common::sense; use Glib qw/TRUE FALSE/; use Cairo; use Gdraw2::CairoTrackPage; use YAML qw/Load Dump LoadFile/; my ($store) = LoadFile('full_cairo.yaml'); my $surface = Cairo::PdfSurface->create('load.pdf',$store->{width},$store->{height}); my $cr = Cairo::Context->create($surface); my $page = Gdraw2::CairoTrackPage->loadHash($store,cairoContext=>$cr); $page->drawCairo; Gdraw2-v0.0.3/t/group_layout.t000555001750001750 242712001671021 16323 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use common::sense; use Gdraw2::CairoTrackPage; use Gdraw2::CairoTrackGroup; use Gdraw2::CairoTrack; use Gdraw2::Element::CairoBlock; use Gdraw2::Util::RGBAColor; use Math::Trig qw/pi pi2/; my $surface = Cairo::SvgSurface->create( 'group_layout.svg', 1000, 1000 ); my $cr = Cairo::Context->create($surface); my $page = Gdraw2::CairoTrackPage->new( cairoContext => $cr, groupDistance => 30, width => 1000, height => 1000, textFont => 'Arial', textSize => 8, isCircular => 1 ); for my $i ( 0 .. 5 ) { my $left = $i * 100; my $right = 1000 - $left - 130; my $startIndent = $i / 20 * pi2; my $endIndent = pi2- $startIndent -pi2 / 10; say "#-- create group: $startIndent, $endIndent"; my $group = Gdraw2::CairoTrackGroup->new( leftMargin => $left, rightMargin => $right, circStartIndent => $startIndent, circEndIndent => $endIndent, start => 1, end => 200 ); $page->addChild($group); my $track = Gdraw2::CairoTrack->new( start => 1, end => 200 ); $group->addChild($track); $track->addChild( Gdraw2::Element::CairoBlock->new( position => [ 1, 50, 101, 200 ], fillColor => Gdraw2::Util::RGBAColor->new( 0, 0, 1, 0.5 ) ) ); } $page->draw; Gdraw2-v0.0.3/t/full_cairo.t000444001750001750 653512001671021 15712 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use strict; use Glib qw/TRUE FALSE/; use Cairo; use Gdraw2::Element::CairoBlock; use Gdraw2::Element::CairoMapping; use Gdraw2::Element::CairoDataCurve; use Gdraw2::CairoTrackPage; use Gdraw2::CairoTrackGroup; use Gdraw2::CairoTrack; use Gdraw2::Util::RGBColor; use Gdraw2::Util::RGBAColor; use YAML::Syck qw/Dump Load DumpFile LoadFile/; my $surface = Cairo::PdfSurface->create( 'full_cairo.pdf', 1600, 600 ); my $cr = Cairo::Context->create($surface); my $page = Gdraw2::CairoTrackPage->new( cairoContext => $cr, width => 1600, height => 600 ); my $groupA = Gdraw2::CairoTrackGroup->new( start => 1, end => 1000, leftMargin => 50, rightMargin => 50 ); $page->addChild($groupA); my $groupB = Gdraw2::CairoTrackGroup->new( end => 600, leftMargin => 250, rightMargin => 150 ); $page->addChild($groupB); my $trackA1 = Gdraw2::CairoTrack->new( start => 1, end => 1000 ); my $trackA2 = Gdraw2::CairoTrack->new( start => 501, end => 1000 ); $groupA->addChild($trackA1); $groupA->addChild($trackA2); my $trackB = Gdraw2::CairoTrack->new( start => 1, end => 600 ); $groupB->addChild($trackB); my $eleA1_1 = Gdraw2::Element::CairoBlock->new( displayName => 'element A1-1', nameAnchor => 'right', elementAnchor => 'right', strand => -1, position => [ 1, 200 ] ); my $eleA1_2 = Gdraw2::Element::CairoBlock->new( displayName => 'element A1-2', nameAnchor => 'center', elementAnchor => 'center', position => [ 50, 250 ] ); my $eleA1_3 = Gdraw2::Element::CairoBlock->new( displayName => 'element A1-3', strand => 1, position => [ 300, 400, 450, 600 ] ); my $eleA1_4 = Gdraw2::Element::CairoBlock->new( displayName => 'element A1-4', strand => -1, position => [ 600, 650, 800, 1000 ] ); my $mapA1 = Gdraw2::Element::CairoMapping->new( displayName => 'aaaaa', showName => 0, layer => 'top', fillColor => Gdraw2::Util::RGBAColor->new( 0.5, 0.5, 1, 0.5 ), position => [ 1, 200 ], extGroupIndex => 1, extStart => 1, extEnd => 200 ); $trackA1->addChild($eleA1_1); $trackA1->addChild($eleA1_2); $trackA1->addChild($eleA1_3); $trackA1->addChild($eleA1_4); $trackA1->addChild($mapA1); my $eleA2_1 = Gdraw2::Element::CairoBlock->new( displayName => 'element A2_1', strand => -1, position => [ 600, 650, 680, 950 ] ); my $eleA2_2 = Gdraw2::Element::CairoBlock->new( displayName => 'element A2_2', strand => 1, position => [ 600, 630 ] ); $trackA2->addChild($eleA2_1); $trackA2->addChild($eleA2_2); my $eleB_1 = Gdraw2::Element::CairoBlock->new( displayName => 'element B-1', strand => -1, position => [ 1, 150, 201, 750 ] ); my $eleB_2 = Gdraw2::Element::CairoBlock->new( displayName => 'element B-2', strand => 1, position => [ -50, 150 ] ); my $mapB = Gdraw2::Element::CairoMapping->new( displayName => 'bbbbb', layer => 'top', fillColor => Gdraw2::Util::RGBAColor->new( 1, 0.5, 0.5, 0.5 ), position => [ 401, 600 ], extStart => 701, extEnd => 900 ); my $curve = Gdraw2::Element::CairoDataCurve->new( displayName => 'curve', layer => 'top', position => [401,600], middleLine => 3, data => [1,2,3,4,5] ); $trackB->addChild($eleB_1); $trackB->addChild($eleB_2); $trackB->addChild($mapB); $trackB->addChild($curve); $page->draw; my $hash = $page->toHash; DumpFile( 'full_cairo.yaml', $hash ); Gdraw2-v0.0.3/t/short.pdf000555001750001750 11130612001671021 15274 0ustar00yangxiyangxi000000000000%PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xřn6 ~ @.  tNvEN3 YtWuMڒ8 ?L~|v:yXWS˟^pλ>@dCؖJ䇧úfXǺ{|ypyz~|ڣF!-i5e~i]05E>)L0<(73LOXDTq '`,#2LO`,#1瓢*#lIQuXGZUXGt0E]H\j46 40ܩAQ '* =RU#cș;хTX5BjD7;wH4:;J3gn< !`q]=̥u[] /bŶ@5cnO:]ަ9H8kh`{=7&u=[H)mlM=aCg͜ ,0FLL2 ~6L v 6+* t ef(7ϊ;gPHЌH`$T8kBv63T j ӐI$T8FgTIАI$T8k3}C;,ج U:H$ H$LYPWog( 5: H$ H$L`0LnZzQlF4iD@$^ ln*ua S TdNi((D3 y0dqpCfP5I/f07κ<{0͡rZ\&3x$Gx > /a1 << /CA 0.5 /ca 0.5 >> >> /Font << /f-0-0 5 0 R >> >> endobj 6 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 600 600 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 7 0 obj << /Length 8 0 R /Filter /FlateDecode /Length1 1538 /Length2 33070 /Length3 545 >> stream xxcx%ݶnl;`Ŷٱъmtl۶m۶tZOUY5"'VT258330ͭ lmd镁΀?N8roNV‘mmx'4p5p l Yx,LL u8‘ڹ;9} RUV 0t:(hekg qq[YL@8 qs+s;;[Iώ :)j)0q̜xM@&A & 6@'?b6"e`Qsџn[غx_cg;FUs{g?vv+G  7l t30q_Wn^&?8OG ߁FNC @rNnm&?0Lmm7E lI&zAaa[7'= bax 1*WrP40STM O~Fy['s#[:LL?Oq@GVV$?#%[,/1Y8xks+eTsf dcjF݀ƊNFfUmV6@E[Gzf&ffnditt#`@*)``G,Oft 6N윝&*_wh@=Y6d76s (pv6w0:29w6_6OOJ[g4᏶!?]mbn@# )%ɱ+2 mD6"*NHW5۩ "?1[d,cO 3M@_kn7Lg+F]L> ~/nRbz!U,e3 *-+OvLh\"<^tQͨDGWKVXXdoBa58[zƽX \(QmZ31䵽 3'+%o3  Y>Aj[(eeagfK&ZMm)c%ׅ>_x< ̗ t~& Kajsx_gtEl<,zgw8 y&Z b[b{bNfoe^5˜%_M}⃩#:0 :+m_mȰQb9%!!K"";o>ŪĔ8EJ呗 EjD_pCv\ b@ Ď]PHuBXv`cԩH;FDzM-r]'aBL,)yDK~l0x!l2d"X B6R݉PTv5TAv`lgF~Dteg=%aT4/ul@p%"{p;Dꐵyy;|m:AԬW#]knI D{b"9϶ۦ*8( FLHNZkD A$G3]sx@oX:^S,~GκB;SV9 ^ fyUK>n=j2i /6=yIVD磐~YtdSDKGFG ׼$)޽~-^~ >sb|6 !&q Ku1.#YQ:Q}fBsR HU[! D7y@Huk#"EXxS+Qgrg Z%_C;?"]y Js9eZ>/I?9U=( V{"P|HK/Igh8$wH\6;O j j@3Ll+%կ.h kX1v9-/d2KO~,\ث,YZ}G9|$ T299tSF=~j:M,K33WX22jr<3e.7x%p%~`.!yf0y^?1`%|k20;,39d"\MLLe<Y3](EU +k2w}2 R\%.:oyDM9\^nȱOdY\S2]PNYIӥX;ıu2A6YdPc!JъNثE$jY#H&7(QO9`,A"H4~'qΈذ6 f%w-4-&_Ω= pC~ eO'?"1=~Xxg;W wh6M#TSCXi&AL0Ta9r3G"!+wl.Z>p7 %+`A-C顥ƒB@vzͩl ;(T:lY+!^;\`(`c+\Ib-

cclzAO.=> UlW_J47D øpy+7Uɏ*}h!{4xK3@n^7{^~Pw'BJfms,_C8g*M\wPEZC־߂*ڱ.d@Htpoؓxl:[wy:۾U^#5͵U^Ive^>Zr$rUMehx IS2F`5M{Mņ+d G,74(X\9uNM=3OaQ7 ؚ91%Z#b-߽FuƣMO )d9zP)܂sR}Vjsc,IHpB@.~#B2 "m/5Uؖ:( $#Am:uhW|$w5ZQN;(1qb;Ӕ`_,/Ek|l"c}Q+ Sȉ0?c&}=謄{Zk 5#s;^nu HqZ=D[F#VsS>QBy: '/~XneϺ Q>vkfkD?[yWPHx2AT|"@e4xFMpȊj,`C=0Hߊ.)&CiYsvb0QVE㨟/ eJ00Ěܙ_<`V})D}r&c .:ĺQ/I4 :DF>$g2vUV@2BnƯK#[7 fxN!_g. u JC~kqj{Yom9 H7E-*F@%ȏR <Ur_.oY bT}<&^“%<2Yçv g8>ys&)w SAGˤi8xPv QUfify`@1Pg[>Z^{&Q[ՓgH$;+27i-rLһGb95HuN*X[]CxIآZV/2 .唚2aŗgwpB"[ƍ9 !IFf<>'aOtiSOD%戀&0Wn̐fv jm'ۜ n9xMwH脹ɿTz=$$Tkϓ&ЕэAi #G_M^4v Q^SNCV>G;`CebNe%׈NKbG; , 0Hm7pv:a:3SuaWT> =v@OHn@q *i}{c|B̭YTć KصnՄj%')6A rQlPmX }0hqw󋐍nlFT1ɢr$:MGhB2 |-|4nZC%<Ix-tͩa+L@%{P5XkmUaa4S}>**$Ć]G>qMM!LI6˝Cݑp]DݺOFRڨ،Vt2C\&^BF f':Ֆ3:ߓx;oԲ~ܒ(q/\b:9#ce ,PMbn),م" WW.fȣ*"NBcI=Ƅ@[Z2`rW#Tz%|cF!=p´xg`NVqQv7pCIo\6gC`Nuyz]+C]}8D+ss:^xIpQ7hؾt}h{aӐJ~&jJx]g;3z|KiXH:†\la_X/oTREI_؅[kR$+i@6%B$(QCYPQ~bWY R+qLc!L$hl]*>~n8_jCEM#Lb:PۈР= D6~钍FKLh~$Zī-[+34cL;s\pedk'6pv Ҩvl( Fl㺁hUt nRcFVkD)օ^5>4j375_}XҐ ޝ lTy. M"q361Td [#w9[(0p{F}w'8G݈!; YZ4 {ZD;u p[V7(8UKO4X!ti9oP9v,m?S4|_uRk7jmёO3˝'瀁SXmMeѕfJp .1Rr#L96]\&7h8{ Vz緓XHa)y=C&RӛP݅3Kl<]IwB052apk NDo[?׻ھSO-vl֗q? w$;'fܹKoVvٟJ'vQLʲwߞWUvvpԉ#COV.0}O@QQT9 PobҩxW6z/i.b~dvB!p˧E1-v[l":EHh42vd4U{Q͐<`| ֚UWi}R%Y0djzNm$"kא5a(0AcT(X$+,hԺ/[xtoRX`ZJu퇃(z*rh&nS:+bh# h~yZ٤!m0TFkur p_ճ;wnH,K$#+3{z ^9e⦊/c]a$;8@sAK^:jC ;42{r3cz:ƶ75DOr`WBMZhRFɔH>Г\3l_)D*ֵBٕ>z,TD{qAo,]AKW xy> }w: =Оnw8 ИҶ"(}2T8Gf7B@10==4?n`xYt>uoˋ]2Hyc~j+,.ͷ.e κN`fLӈ s1Ft*He3v} |m/ZAs\ekT3>t=T] ,H5*e"\xAehw~}S^*2lpB^>%_Ϸa=/޽-}Ht X;r;N')gO=8"CX4sG^('s#Dcv3{o2 Q$ʯTqS lA=o?пLTz?gti54v>h^WV腣EV"k5?Awn\Rl`zEϺw7XnrɒBi~ȟU6bH_T*suxn.':EB!!1hOpk2>_ٽ]Tk*u }0M P"Ck=2_&a:!Ou,T}~ 1ŸPϕԙ1l+?}Vi߂̓⣮tÃ~Իllr!"f+Փݸ Nq};h:D᮲3`gLAd~m,!x {vXxRWI _Isƚ֧?{_O)pRzq5-82AYvT*3re袓??כ7‰blķ~7V9&r#U58Pd=0Pd7_8o"qB`|Y`5?cSmŕvW@mGl_,] Q+bwӔ BUv .])Awua%|F0v4F[L~ѡBH¥lG27%"I,W1o+˹==$4ilD~~X=ɝp^Q\%O#b=YM# K/%0Ai`uoMS~:6Lٖ x%\ C4yl=o5M9Kz 4uKw 40n gtY>!|BA^rVkbe+Ku!UDv_ۢkf ,5jX}5dב}42bi=Ay->{s,Ƕ3yďo):ad^Z P}%}w ͘g B_=+_)aպϠ/ۻxX5 tGؼC5k,]Sp7g R>+ۤHҤPorSۃx:8\l{j}7*| X >NyX]InGru`QK`)kx{|%ҩ =fR\nm$N,@ہNZ,&TK>6\*u"4Tχ 3pMOcH!4׷@fL+z:z/7p^e_X`BPɲBܛS07Ϗ{4 hE8F~XGDﶔ*6_ |,2Aqφ6eSCeplJ[Zb6xD%=VanI~ŨG Rl ,A1ބ&  \r}}G_4yyc OWҷZ#CFfͱ,͡49卭E~ 2ij+nQb*~ F)t'E1o&*G})?}ά ժ PCz9̡^x(#&I t'w4 gw?! K I&BmŚ껗`O$Mw ;I0" <4tkc4"+7b^p])V7~`윎d4r>LȸQĀ dPz ׀+T@ʘ 9q !3$Dn'qE3tF8FP2̋8,Gz<^%imfRԼRciꕬ~ɗgtC>/nc:w/׷I8g\VGGR]@Z&9' ƈޑ1Ђ͖Νޠ!!/vuXx "1|iߧo^e绉? _qL0\fxv'W! M =TҕdH '-eÈ)aE_-@,!RP-rd5c&\c "F$y#3z%C8N%Ɍji0 >7UT#Y3t:|: 0ֳSgD6 :hfTOmldL7!0UK|%>Z S7[VLx,!g:åzY|c703{W"k,dJ)0XfcHĂBcr&aq… .dV7~u]{Ͷ2=8dyhUr}} l杝ZDS?gLZ1r5$qhq=9\+;8dC )3vԌ06p)v^EԒAvU_ͮ',RT..n~y۶[03AXr{> ^]엦ӋGzsA<=ixc:x*`|OR#+iЩ,GßEEf֥b&th:Qm(Zγo1*6gFJ4̗/P:9. s(5 %yYLh:2@v A@p] P)_qdòGʏ/Ong65fD[}]Z"nH@!\!C ܢ_mx^pA#u'jE~\wY]ꆍM4)Z7G@B; ;G|Q cH<`.Wӣ iMkr(ĕV)v٪jjUy3ma 8-J!WeЗVT]DނQL9)~YsyQTzj3Du:_7_$9U uaW(Z,EX,PiB3۬䘆.8EfO V|&sζz#!KƸzyYu ?\~.B&0͡KtIA=xpwcF_ /a+׬xvWڪdu=>gNcs y50:`( MxΐBeَ| (VB%4DTL"A$Wvw{)]cahrt a ePfTFߵԯxΰntu}.s*>-h^v{MٻY@T#V2[*ɑ_l}=rhpE;d/CА:W S!xCK1X w2}Z H{nsedӧ'?:Y:Edm:1_9*w&v ٦Zx5gXWI4o۲WUBzc#(~blI8iy˅R78ؤ1VF 1pFOų 0  G1Jϻ$(u\h@{z..X g1S &'xf7O~qGK1Z/Sv@Џ8|V̺g 9zE*n=ɮuʚn(/ W$pBoίM|-*)x-|p >bHG_o`+:vdPL^&5 B/Q]K~6Zȸ,}\6j~Gm46lh1jjEW[ϱRkL`L\^ Aze޳_KYOOw >5cYsYa17u= :pڋFpd$AkZx$8T ޶=u̹ߊ5@0%4-}EBrq{ANGߚ !jY:Jlk&H`+ '/0i#Gj$%P9r*FϦ/-٭-&2~fa #\% W2CVlA}cV ܌ce{_Lqb@ K}F0WGxzPUE=΋uDm:XJ =t3U&X}&@iJm ;~ ]lm,T(uPBD W[̘ VGK|54U^rBA */O8#wCo҂,<N޷u(AO@hLp]q} E7o-9*D0Ѭɤa復7nSм/Fv2c}#X{ B02 L>xd߱vR Z,dP[QG1l氣Z28hna(^ $d߄̜ PblfAB+%R29_iޔK+2Z3\$u`8{¦ܮ,:B_`Sه4#'lZr|/h~x9>OCQ?=^+B`쳗Tn?NnH60@b K!qն^;jN9Zׁ܅BK7&FPKH9vvdA|Hzd?s=M3vGX)7?hѯ+ؗ<}f|)BK i{Bȉy{i^.)fᆴ,+fP@!TJ"Uݐ?AD.?xUUGScvz5.ْ UKncQe輺a^~k)wmű+Da"r *DꝇbS/L;&aiIl, MJFvMZUhfF2':?|Sdew4 2B%yDǴ\|"h _]FƗdul[ /eI\hth ё P\ G&v{?L[w#b妬uP!Tվ7z_{]҇*ROdFQݯ)AtT%xͼBƯ6w{OfSǠ<6C&Sd^BgPe^y"͑g`F֞v+uLgpAq ),HT5SOt8,8L.\m޵5_._]ZVKR OZ8^96bg(ӚdtoAs1 ?6ʆxԟi#:缴軥$wJ4HD..{,:]Di8|}D,8?rDxpb^,;KX3. {z 9_'GWzy ~N)OqH4 FbIbhK<6[35|&Ңv8)U2Y)J6,IB}$^l@Hі!MFH;$#UaeZEE \PLV^Gpc.]u uooyyTQϼc ?N"L^LȐ\ֶIq3ro^+.>_j #7^euVwӗ [`Y7ODS¦c9xi,vvg>'X3^LRu)O+g!seO枲 AHZл -NSG_9#aEhؿv(,eš(^*3M',M H : :c]AG.7vTEQL+U'BwYrO Au;h6YlAr.S'6Lk'2ۙMe A{2N>G{ 4_G&f6ϙKr>Cl 5ЃtE9]JEEgXekFf]X'tƛ||8; nQjOm".z Г0* I(En#6=[62;\CGB* R>z5WɆ!WVX, Tj''en@b*D&U_,4:U"`!{S畾g>Ԟ% e'Sڤ150Җsz?%f+.,cD LyCb*NrXO R(ޙ/nt D.ƟH7tIݐbO6mqe"Μa+G 0L]M񀩐8Jew( Nt<:dգ ptk뭊~#9yl4fL:b",Td<Aց@PZe=cRbZ&8'DmuFA`$0ɠavvuR R[JZ'%CЄ) nXI.1V1Óyl[`S0W`M\ n’%Z3cZ S -U֚8mx`?݌uLaG‡jV~wʯ/zw͙O3Ha]%?#?)dhN|F$ @$V<&@C=SVnF(a=r2T<HFA4\_# ?Yލ fuM&F (;M!{QB6pqVb,G4w6uR:F{πکֺIcxǓC6G3VG947t+™:LĤG!/懢i(26W':<nezVT/jکr$ܒ;ldx;^"!HcrZ؁n͇"]Z~j[jmwJdAQiZSAfD%ئE;CIxp'ǸGkIb[g&uny͘BNKX 5SRnbCv|#`io #ЌCP0wBwڨ_qf Y \+huwV:2]o[׹+ ֡qݖ\C<'̍@`BoYFo}aJKod6q/PȚ:S_*gϟ0!T}j9;.*ޭV}"Fiw0V}u=CjFME%cZwMlwi1d,#ƿt0`LFs<:؎{F7~viZ|[rycdjȍڞLdwGAΙ~øL/O͹xݽPGu".|&ȁ`DPl%΁WZ x}$P>Uy?mp+;EqޞJXb[NZ`A2@[PΛaqc"Dx—2%T|$o. cʅU녈L&5UGXAa6; ) Am8¢}R$⤤h-3nW 66Fxۅ%4l"Y=xxpx'A(˻eUY=P3d4vP(C'0AZ-( R*3S j% ^.[2*j݊.f{;ɵ8l} Q@ύAãyHxxtu٢ bKn^ n65ts'|XY=3/eOĺ2qwu`b%1 U&YY3%Dzv ?!dwiwȧ$nNS3ޣ- h;UTe~˕Ϯe\eLj!r2[;1mW3ѡq&6F4`b~[|=嶡iqMsy_o9˞,Q^l=ß鏓:%PNJCsLyϞ_{ V:MvhDCkaoH:mL@P4g)k[Q´~ZhidAetzM >U J>dR![C0%28yxZԪ=b:^mnP-1E0¢㫜*Yams8SI(֟olEG@EqS-v$y4.Ϟaj7]Cc|_ҕuyT&Et ޔ'kx)uuN-d8"dEd3_'1 qDd]Q)CH=Ffn Sq6\ap;俇XfKy%-N!oOzȡ%ްo>h*YAz42X22NR ba!B`Wd6QrsoC`inP@zL=pEnOb~DHU E.Yw:j-a5SDK 9$5_tBnuM lrLnz1qc^"GvmYXIenHۣ8WTyn7_wϼ >̒%* ǐ]Aiw۟+?bwt8@";uD1כQU ]$;ɁffJ'&VU]\-^K^ dʕO*K*@_ /=WFT3J 7B ai KvEW$R+5x9+.GfG\Beqwޑ̚`5 #*$|p2gm4>nL$,w/h$7V4Q$BN49 ["S߫u0mlԫiDЩM $(yrE`e c*6!/VJr(Ӣx8|&nbB[im 9Nap+tbc.GVKOZpoez@kBG4,ƒlT$-SCF'װǐ֭PUT[<]Cj)Xo}b8JV  IG|k\!XdϲZ|)O@e.[U`o.Rd=gI;u#FpE:[TgI'?,K䑍/tm+(NoK 4?OwGq(g2ckR0J6H1#O/%*QF7'c}z(uMROeggCt L%<.!{F4w53dOŽy83 pxu`X-vg/lnpȇU徭6`V};IGN`mW@U_16\ġ!⼏m ECKf ?=2hoE0O P[js׶oVH=#,TQJpdt5gluH* FV@> & lR _G敓u\m4BQp&]4򉶼;'=O|7%Poў٤PsUiG/%)ܵrˣp$6wOvL׋9Ѭ[~M;sTIe}+r"O}7k,R/#za!٥(q<HXbM6EgD+JiO=Xmޚ+Ԣ.I㏘S{0"ka`hzJasXgj~u  *-4\[^>uUYFݛĘLmO1 6'US?HVFJ^ChVҍa\,H#@j:P q#?n"=qOɎUE!-c.u}A8OCeC@i^K t(U!_-W[X^+(D,h3J8C-XO@Bh0z݅$I Zc *b|Y3rE|;Q@>Ďrzű0xBNG'| ~%¡kyJ9Ko;dv)>ɤ1 F9d1GCzǹj}s tS޸GV)G>iu&,X1 )(9F$*]h0x{t(J9}}HG\oCz7V){dEU Lot"?Kh-2hi]\lDtBa3!r ]ԑGME_\ &3 *KUט(D&tlJSOR3 x | S='}RG$829~1(nJCByHUj;, 귗g7>жGٍ`ʥ'7("50zVKñt X͎II8a~Ԓ ,gDK) Jk@F\cQVvv1L*=4 Noj+PdBC 0@FqԩizJ`Tu3 uR$Lb,H+T$9~dZU-Wp)%׏`t_8-C>[c,Jzfo}mm1,36m=?aߌ=]\b l2mMtXRY<ڜ"So7&_RLC/3&p=5ՠˆ_ٖ8"D5x#%Jq| ީ,E[q+C׽8Lg$> C wZu^O` !Td{i^m҃(RXTW"uܚCj0DAsj5xbQ%/H=C71=*Ch@ VB'<ψ++ ]7Wx׀xjd;p,"\}Nwk4LT`6 wn2133Mcz, | }:ŽiU͗x_>T%% ?fgdLJy1,iBx;BdCUC'\iLh'E/p76jm#.hSs삪8LEs3/wGv-dثg|0=kI+ ʠTu"PLQ@26",q6k!4Ht/S|K5jR+]A∱HU{IS#+Tk`[Ⱥn͜iwIF7+Z8qB&KvȘDaKV@i7oa>xEf @3=|Fk|yrfv)۰lz`Ҷ'˗hяǧ.]3$0r84ҟ=k󤾧FM-Ix1Y$ DLe)`0{Wb\ɞRWxŸDA7RTGmmb9r=.FϫB0BuOU'GvVȔwa7&$A?є[HD5IT$րF{D _(!{֠$D}ƱHfHK]ƏHԖWA`Ű1"d*^qF͵hf¬cmƀQnBwj7|Hlr I=8D(.E\J0L%AJ`(_s`yh)% Uw`mT~ONIƶ oB)ɴ\<\^$P8QP-K=LQv1hy${_"y6WrТ\[@H[_ =3M̝])ȇHZKu"qE&:Cj+)"Jʕf;3 '\m*i=dRsۧ1g5SƄUMhV4fW[qA2iӜv )XvY#!=l09ȩ7%Ec`M༙Kt;^+Y oEj7p**%?"KyO#E.g}g8iuY@43I}` ΒTwkDCyA>;q\J~ݵpGwB<*P?3)u<[{&MnVY2,=ց9g\(F'Ot ?1jM[#ȱq[c]f`в@xU3mPx\k;ƋrHfW 7ީ\6\9j k(A9J'U:י؋[[#YʔpK :R.~VqL;c-BI9Zt`qrI{* ?Up彃ۆo e(\>jf8!$nEdhbf;q;AG Z~9DO0X| ?R-M A#RF'\.1n\-%XT@S<6-L0jgEVi:<(ݝ|(.hQZZ6gT_`73zB7IY+aڢ-Kou%m zV//؂CuuX4$sEډ(6dtkЀ%d΁ @z(z [~&"sy \GtuoLLlu9(W[N)^w>.Gn{G>d]%P֪ So'"x\`:.4UxW{[] +=9q=A2٦p1lQSP> Nd^c&n[ܮFٓM\lte0x ӈ지!o;6gW(MK┿jeq/oL&Bw5ujχ/M:'5;@I]bZ5b%!+p8 UwkK㓵wp>>K'ME* vTQ>WzoCNt/Vyfh-.5\@5q p`keыXi -]ʱTo%h#^1 ~D?F8Ia9d PyB֕ 3tBuYBufEs1>~YUEGs;۰KXrؗĉ6(wu$}B3:gXhF_xo!%*bYqi!`Ɏ|_0%I6$%wf$"$Mh2蠔w*s@p>G'׾bc1q =]3)'&݂f)JP| HPsFS*Qy(Ou5o·u@K;#5PonK)]_zeqE,Ϭ-^>Kbkh 瓒x5?O4e*V'HJHrbbBg>v4WkCݿ &,|1;ٓU%C rtQP#qUL:Z -Lu%)$ADSSArו]̋~> 6ݗ QF&V:PQ6S:a81˛d)}_3q'MHHf.B=}s~KS]qE.ex! ՙ"F,k9GeX~ .&z=؋U/lE}[l6R\|Zԙ@,"G@ 9%šZ|!`kVvK\7  џgqWe!N7gѡu MX+a*@'ۈ؅8X1e uNز^U|n Է=4kk;<0}SK*OT (˅&5Ee,Q\lH([su(zÑêt*d/~Hm}Hق` bQ`۟Lnd>uj]8`.l}ɔqP/6O}lZ^|#;ه:P~h7\[%vĄ0ٖphAPO;s F{C7VKw>1zunh_w-]OH6'eI{HgTEzʼQb V$"6Cd (-0@5DkaEs_eF$odhue{q HkL`=gU~ U) v}gqpJmU ߟ'":nՑ.Gor`b zIʭF_'h{@c4}mRnW!OÞd |-^>zh?/jX`>)}2}{ƅR^eKr~78">y_1>sԏ<֟#ҝS%4L;TKEKg&\tw ʎǟq=wY/fOժ԰4ߚw]Kx_vi-(Ѯ\=o9gͳ&}KL:}wWs"z,kY2K~}+#&&LtL1wv^]I3,mz6)!vwn$'\+f}_mI4Ѥkl\SwfE<7L>頱 +\w;|EA{]'vwxǻ$_W8)O({zEKpd5j=OrRKT +,dAVIkO "=9yN˯]V2tjf&Þ) bʐ|m+s'_o:0w7 wi|ўzwϝ0r0@,g݈X̛_ښi\bf]pTPIΓbeJ^{6W_ҕir*׽?Ɓ E '|đ"g튽n]LJqkaOݾ0Td> stream x]n0 {P[h%4u $F! /NNځKlqki .NJ,*fnX}u8wz\X@郫;2JJOpߌ-H^y3Bq/ BYlI,WZ'dMЌcP%(ņi.[> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NimbusMonoL /FirstChar 0 /LastChar 13 /FontDescriptor 11 0 R /Widths [ 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] /ToUnicode 9 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 6 0 R ] /Count 1 >> endobj 12 0 obj << /Creator (cairo 1.8.10 (http://cairographics.org)) /Producer (cairo 1.8.10 (http://cairographics.org)) >> endobj 13 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 14 0000000000 65535 f 0000036961 00000 n 0000001483 00000 n 0000000015 00000 n 0000001460 00000 n 0000036733 00000 n 0000001624 00000 n 0000001824 00000 n 0000036099 00000 n 0000036123 00000 n 0000036481 00000 n 0000036504 00000 n 0000037026 00000 n 0000037154 00000 n trailer << /Size 14 /Root 13 0 R /Info 12 0 R >> startxref 37207 %%EOF Gdraw2-v0.0.3/t/short.t000444001750001750 273312001671021 14726 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use common::sense; use Cairo; use Gdraw2::Element::CairoBlock; use Gdraw2::Element::CairoMapping; use Gdraw2::Element::CairoRuler; use Gdraw2::Element::CairoTagset; use Gdraw2::CairoTrackPage; use Gdraw2::CairoTrackGroup; use Gdraw2::CairoTrack; use Gdraw2::Util::RGBColor; use Gdraw2::Util::RGBAColor; my $surface = Cairo::PdfSurface->create( 'short.pdf', 600, 600 ); my $cr = Cairo::Context->create($surface); my $page = Gdraw2::CairoTrackPage->new( cairoContext => $cr, width => 600, height => 600 ); my $group1 = Gdraw2::CairoTrackGroup->new( start => -10, end => 10, leftMargin => 50, rightMargin => 50 ); $page->addChild($group1); my $track_ruler = Gdraw2::CairoTrack->new( start => -10, end => 10, showGuideLine => 0 ); $group1->addChild($track_ruler); my $ruler = Gdraw2::Element::CairoRuler->new( position => [ -10, 10 ], gridLength => 1 ); $track_ruler->addChild($ruler); my $track1 = Gdraw2::CairoTrack->new( start => -10, end => 10, ); $group1->addChild($track1); my @loc_tag; for my $i ( -10 .. 10 ) { next if $i == 0; push @loc_tag,$i; $track1->addChild( Gdraw2::Element::CairoBlock->new( position => [ $i,$i ], fillColor => Gdraw2::Util::RGBAColor->new( 0, 1, 1, 0.5 ), elementAnchor => 'center', nameAnchor => 'center', strand => 1, displayName => "at$i" ) ); } $track1->addChild(Gdraw2::Element::CairoTagset->new( position => [@loc_tag] )); $page->draw; Gdraw2-v0.0.3/t/util.t000555001750001750 24212001671021 14520 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use strict; use feature qw/say/; use Test::More; use Gdraw2::Util qw/polar_point/; my ($x,$y) = polar_point(3.14/6,2); say "pie/6,2 => $x,$y"; Gdraw2-v0.0.3/t/circ.svg000555001750001750 17562312001671021 15117 0ustar00yangxiyangxi000000000000 Gdraw2-v0.0.3/t/Element.t000555001750001750 14712001671021 15140 0ustar00yangxiyangxi000000000000#!/usr/bin/perl use strict; use threads; use threads::shared; use Gdraw2::Element::AbstractElement; Gdraw2-v0.0.3/t/full_cairo.yaml000555001750001750 2174012001671021 16427 0ustar00yangxiyangxi000000000000--- CLASS: Gdraw2::CairoTrackPage children: - CLASS: Gdraw2::CairoTrackGroup children: - CLASS: Gdraw2::CairoTrack children: - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element A1-1 elementAnchor: right fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: right position: - 1 - 200 showName: 1 strand: -1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element A1-2 elementAnchor: center fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: center position: - 50 - 250 showName: 1 strand: 0 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element A1-3 elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: left position: - 300 - 400 - 450 - 600 showName: 1 strand: 1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element A1-4 elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: left position: - 600 - 650 - 800 - 1000 showName: 1 strand: -1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoMapping desc: '' displayName: aaaaa elementAnchor: left extEnd: 200 extGroupIndex: 1 extStart: 1 extTrackIndex: 0 fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: '0.5' blue: 1 green: '0.5' red: '0.5' layer: top lineWidth: '0.5' nameAnchor: left position: - 1 - 200 showName: 0 strand: 0 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 displayName: '' elementWidth: 15 end: 1000 showGuideLine: 1 start: 1 - CLASS: Gdraw2::CairoTrack children: - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element A2_1 elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: left position: - 600 - 650 - 680 - 950 showName: 1 strand: -1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element A2_2 elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: left position: - 600 - 630 showName: 1 strand: 1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 displayName: '' elementWidth: 15 end: 1000 showGuideLine: 1 start: 501 circEndIndent: 0 circStartIndent: 0 desc: '' displayName: '' end: 1000 leftMargin: 50 rightMargin: 50 start: 1 trackDistance: 10 - CLASS: Gdraw2::CairoTrackGroup children: - CLASS: Gdraw2::CairoTrack children: - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element B-1 elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: left position: - 1 - 150 - 201 - 750 showName: 1 strand: -1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoBlock desc: '' displayName: element B-2 elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 layer: default lineWidth: '0.5' nameAnchor: left position: - -50 - 150 showName: 1 strand: 1 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoMapping desc: '' displayName: bbbbb elementAnchor: left extEnd: 900 extGroupIndex: 0 extStart: 701 extTrackIndex: 0 fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: '0.5' blue: '0.5' green: '0.5' red: 1 layer: top lineWidth: '0.5' nameAnchor: left position: - 401 - 600 showName: 1 strand: 0 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 - CLASS: Gdraw2::Element::CairoDataCurve data: - 1 - 2 - 3 - 4 - 5 desc: '' displayName: curve elementAnchor: left fillColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: '0.5' green: '0.5' red: 0 fillColor2: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 1 green: 0 red: 1 layer: top lineWidth: '0.5' middleLine: 3 nameAnchor: left position: - 401 - 600 showName: 1 strand: 0 strokeColor: CLASS: Gdraw2::Util::RGBAColor alpha: 1 blue: 0 green: 0 red: 0 displayName: '' elementWidth: 15 end: 600 showGuideLine: 1 start: 1 circEndIndent: 0 circStartIndent: 0 desc: '' displayName: '' end: 600 leftMargin: 250 rightMargin: 150 start: 1 trackDistance: 10 groupDistance: 10 height: 600 initRadius: 80 isCircular: 0 textFont: Courier textSize: 12 titleFont: Courier titleSize: 20 topMargin: 50 width: 1600 Gdraw2-v0.0.3/t/full_cairo.pdf000555001750001750 11070412001671021 16255 0ustar00yangxiyangxi000000000000%PDF-1.5 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xXKo9 Wd*9=X(n !m]Lj07>?7J~W($xdz~>,I)NX L=ܚ|OxWJ%N+y@Ose*G̳4˩(IKMMAeQfT;^ěӝC y< cSgYy, %,LDGWh(M* lU3mPzlJ}M OOSN)hK86S߽Bv{|5?`> PMn_" [GA+}s NjN> ۺthT/XAHcwerw54b2.Vd T[Gh zMLc WtFrko`e~?vdxiG~ܗNځY%R-)Fw+H ᝅqtwگؕb uwVwRr>;8(B~O٬9W?= endstream endobj 4 0 obj 1006 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> /a1 << /CA 0.5 /ca 0.5 >> >> /Font << /f-0-0 5 0 R >> >> endobj 6 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 1600 600 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 7 0 obj << /Length 8 0 R /Filter /FlateDecode /Length1 1616 /Length2 33077 /Length3 545 >> stream xcxd]5줃mc;mtl۶m۶to9UUs5\cZ&#RP41X;13r̬ dme蔀&NO';w3GKBTf6'lwt;~7u:&fn+m6pd6nf&܀P(Qa7:X Z;?ݖfK7[S/U}K@@)L,2}~ā@ϒWlM4utf`0魁 dF6Ve`3{gn w-m\=/j-PR_[[ľ\ljhlL<=if y8;N@O 023tM̬ate;ڛ? `_:0t'\N `7[tBB6:Vv3+Ǡo_BIkc׿jl`p r6fO[ڌl0?EOq @WbNw_J|J KL;^1E3$?k6F\F fk*F@{K3k_7 # ~753:8|o hm2ZYnpdfcx0>om?l=Ug08os pl `b08c3}ڦ 8`e0c*P >409忍O.SgI?g[fC'{OY>mcϥ]pO@Ϗnby^A(Z n1x.E*fRӄo~1`4Kk]d TߠL8 ~t /sN٠DC-_,b 䧛U\lS7iw=|@~\7>4 nPJ:%IR+ZqWatRh~YPf@Efw5YZ~f3B 3'^yfNBȋ[~{_r{i0|5+^0홰\ͱybnB*݅P,?oia7J%M߰\xv7[ 4<$6Qٛz!޽|yCt7Q- Q切qm\\͏ik>Y=ُ%Ŗ~fPex1 od-/ЭEDkSKu53BZ ^%{?np66lA]Sn KV6'NqPZw?Ӯ|'UP;f^>bc)R[^8C=b %jL7:_yA 1U&Q4f퉄hVMgc\Oq#DQQW.VuㅃMo̓ݾU8rpQ^"9c0Mڲ5(tQt ]fk,?NdY9pNiMç??Ē׎b_fvr/:?*b,P R2 9jxx7g}zgY:G޿|dsӏķ}ō!oGWY (`/"+C^ L^_Gk0Eeh#<04:EHa6*qdh)k2:ewLSt-I~8 Pf(˩J]qPKEQ !{ GKy+:'WYGn!3 E,lLy.լ ZGhX% >7w=$Zh1D@뤕IbFu%uaPNr # 2P޶zn K^ý y0-޴O5gv⣂ fu w3+S 0-TET{G栕6,\^PJbm}4zK[nmɎG/4+Wٮ{+%'%?'փ*B`bR[_m,̈́XL~.hU$謳8y#FwYD E.SdyiUHUq_ЉD*@N~HydMs+V2( .RyWX>d6}-5H1ja_1GWlF'u x 83T W_AZLd"`9ǩ`O_onTrנG<Κh DpypYb`| ?%B,9Hr65J%(I3vm|N-ZUcIs]wuSoъ. )gmؤչw sKQZ#0I,lAHՋe*l+2p|ɓ˶ykA}udF-kY) d']V*F$o(ubqwY2)o冃|wlE'V?qŶ,K^>1ylUӰ8ާIdog<=# ;Vݲ?h.;[ө=i3,r쒀גУmF*%T>(4'&ʌ~$mOül=B{Ug7n..w[QE.5|E[.xxͪPbWc]BVB"$df a6.[+2q^S -# FDxdr4ưo\\jU+XXu)06lY̲581P?jV+G@'5 W"mPﬔ+D[rC+f;(k's><`ty|F  $6޿#eVzZQ2~E!ퟦ\h}3Cؒ fUK]6Nwn7^L-*n=o$q %]ߖV{M1ZTJO(s))]ԩ&c"iTj˭d#-}J|tEȺxLi.~DeZ^Q@L #;W "qX'!)Y`R D:{WЏQ[Jľ,; `v*jf!pܻ'd$~=2Ůٮ}h\֖, 2ՄSn _˴ pվcբYB NfE .]|5dP4t]0#z|KȽzoLT ?dR2{q&^V &N|$+\Gu P? Sg֣hTR[/d a |p*l="lT٧GLȼ"#x$}/mL͜'}m(ru g n>$|*\FH/eF*Ы*;^'0)yxVJ\g7zFX;iJR욐q?q#o>L~K#HU YJtsbݹ? ḤX;kZվFsYT5 I+V["tj9[S<۴/n=f͑]G[XqTbm3liٞG=ۍ;{)chMuE᥋FrP33+RRL'mlh[V֛ZH!I9]эF|S ok z^ÜΈv\15Z3`Hqr e9Fg7owjVlli:[PMԴԕr= u2'9H%nߺImTtڝ;?XR^_3,bًÈi(;&s8lD1Os@~.$JI=D,hA@+PVKq5Yaְ^RDрԲW\I6O{5T @ *i! A5ĐyPidaZų  R`s\E-/c?hG?,htHa&xM4ex3E e ۂJH6phZ.{{|B5Tco-Ʃvw ]eƦGu 䫈veA. H5$ K?8!Xf!)r5O1AXi)FG򪊸_u?} ,0w.6]:z;%#vjqҡwA:߄bUAKZ ݺKQ^O EXCtwRT~`;aSyHWUP#3.wKF%iݜC<t]GpMAUK8C^+/1oh-ZK({WrYzZZemH^Sȼ/J"nj35p+厜޻$+h>U.Dmq }adzܪ^7ݢ ) Bt]mLA@l2FKʹ wSƚNpT=e|ZHrcoR+m8 R=&vX!z%d>o4z? ~H;)y!@;I5q37A@DTd]cG.`^bhc\ZajKp̖fI$0!ۃdk7&p`a:/hcz9^ITTK/ #%QouԒ¸;區>/#Vf#*uŏU'!~0 k:YY84_+\R>2w%諶l?I;|h,^ 6ayNB]4~WM3w&-7 '|QW@"`;yLs'Nh. p#!RW_ 1bnZÇ=8Ʉ] z_?1^@[ G)^ɶ XuUG7'nc`!+߯lR9: Nkr %)ʍmXX&GW2~%7MhAWBMLG/]mCf grƮpaă蝌ktHq^BOQ/)6ȠL7_+SWt *bc[60Ԅ6> ZPtL~{CHWL أN-Nye OM,Frjc0AW24j&-ŞM1XQK R[KD @P#;9#Z jjso; pKK4BKn s7)"V'[h",})|D7=.CA TU@3Բl~O-׿񖁦B SY0RKɺf¯3&Cpr=;YIn5[Znx#wWZSO]L͜LH4խz=h6h~}s1GtGHަȫk]XwK;{ uE7X`X`ue`o]aF|I0mOwS^kO|/< :pw5;$4#ȃ͉(~1mEJF#ӷ޻8C!0[uU2}|KU%E…A ؐP`7reѝK^GJbO_K%|؟YtgQv^dYhXW/?ccН׈ֈ:U壅5 آH$ Fy'Wdk z4".ZB`Ş53("^}G1T"Hmcpj>OZkDFHױ#H_q GGJ@1ӷw \hdL”f pޥUdn^9}DD*.لsO $J\ZhڱWF$c~c= J:t2߹`_uY$]FOpT$DU+k\]yB,SnFm9Vvݡe^w{!rBƶq|-[I?6dҼDM!䯾;| Cfx:}bPd{2uzs_7"R|ҍ}bJ,c66)5L]=dt'>$";3eظ*eF;($M^K@* t~` UVO! +vC/E~4 I--%l$Jw+8@&1s^x4C=ûO![Je3iYRt_[xo kMa`b`B_{*uA3[ټU.Aܶ q@/c|^ug1;e+UirGmCl[(Y V-ds'DUr.U!N{untJ?'Vzktݚ^ၼp=l>{7q ڤg0O9 ==9ƟDwT)l>>X/Sa<"8JL*DrcZ3h|_aSjZ]'s%:t6ybeȽ%[\Sl7I Z .;jZx]u~S %IʦCc*o0/)$` ):]4}DSԝyŌՋfO63aN=i /ͰT*iv/Vcw7_RqJt37q{̰C L×=&gk.`{jsTVൿ%9Wb}\p:UaH^N+-ECIooOM qX'K14<~e֓BV{*eYPQVJ+AF2S<&u.. j2f]|{-OY 1$q fsx\[]7DVt!wdL9?'xYbWսbx 40C4jPj~xڍ>:1')`7oRkqW-Q^?>H8/tduj 檿G´3vNs2%ܚ*שc(=LUM)7h\W~lapoQj2* E2j)QoZXVrĈ;ʲǬKȑwC x,Qco7CJp|?f8xi&д]ɱA;;TIL<%L1ʟF){T[nZ kӾדGJMG\9aΫ#go\Re[ّn•c7$)u﹙chD?#ZѳFکȯu }5͢3,QShacƯ3}?vάU8U(&2'9-G× ٦m";Ƞ0^A7_ Ñ̤ ܥVQ\>6)5 gG1ȏУƹEe:Z6؍lK48a$N5tlC%G=ϋ2>͍{0.^.>y4Ư- tmL_g9zބ cIGKg>7|G3t9, .fH- % 'IFJ܁kZ2+z^]F$?+0OKb}~ػK;EtC&_cZ6LJH%L(B/I7̝ 첎;3&2$ǡn\@U{ClZMAMvR"ҜK~ 72c>6cέ0$MlʘA;s`2ڄs] +z8C 2}}fuR9Ky߂rUSwaݑ{qi\\hP5ݡa2 '*i7aej9yJgi~Qn!Ry/ä?>#=uBSJoL^d~vEí )Ƿ 8H\ pr=I[::~qKɵfT{&\*/ d'о_qzvα_WD|CBSǐ}0U𳭸BUm F 6fYi}[3Oɤ.5ȗ\WkD"D{D}IgȂ#Ε6e,og Y9 >g0QK4 >D*@ NhO!bE|Ŵ=l$ UԽ0J0%ʕLiZmu^m2 xɌ:S®:붰zmu0<+džVVR{|k:Ebo'MKF;0{mġ68L;pk6+9]=KUf#śd,Sl1$]qo0U8aMҽ+IhKw4rOO,'UNbu,ؙMIikr>_)s:gA *1kW334 srVlj؜NzYWŦ+$m\X&&fvq:S3?=8NP|s6^M{ ?ZS~-;ݓ5zK͕^T\\wٮ3Qs.{+qC߉4[ݏYYzƹ|:tp*Au0J֣w!2&{ZJ$ԇ7@*ɟ6sg0%%iT`2OzO" PW.[q`ŲCʋ+Kjcƥ21b@]yY\$تH\G!X&E&'ؤ_ixwF%q#lAzXs^YꄎiL< j&{QFu{9郜 5"zY0AX-E+NFqhשmԃDtsS q-vܳdNσVr]1'}xAŴt#QZ8Ն;rQk:)&ؒCK(.l`ؔY牆,G&H?v h6(N~i+Ҽ'=~c`_О.[y:=}#@sN B:0.ۄCSs*zVg'ؐ}%Gю+Ӳdc=>ỷ(= To]~Hd{H T9-a"HЛWE0Z-1٪&̦HS]!"r&3}c⽯.dQسQdWgoh+ZE_]~Ur~ uDdB1NDPeu [aOwVbʉ`mW^n,~uaWv2S쭩#B55ʡc*^oDh|M݀xǎ&e1Y?)48 5Pe56P̹ ?ěWhv(*W%M& Fq K3~{[8"+tÅBn ڈ9e tuPOwBaO~Tlz;;\+s۟- K&BdpBs [@&\z7ƎVoE" 1JėPWeF[YIЇB%~.Y>{v]BPD5IR|F Edgt!]ˡ*ҧ+dDt'%ME7,V`D u*f ;,Ηi#j0QR /V{>ZFK)ImEs(coAgU#^ E澝Gxj0_V)l3SNN\ $x *RV[!H>؀!`|"^P).kp %f3fU%U-_A)9ZkM.{qu˜3&yVXxH=ո :-S T2wW:D1h5҅ҏ:Ķ{#B4 @z6|R2Ԍz&$ld1[ZvCW_˶6kvP}p49"Tt"><%QZF5,s)duFqh+BA$cQ~Zܑξ:q4V8X Ը-?p}}feWҨE&8E?? )J`68.l M{0F| ^Nyˊ :U2f:+_ӅN3r(/=3 M}2f%hKD>[s!tBFO"@Qz3pꕾd`U2J1DtզÞ6fCv\ތu8/ w^149nxCзV}2{NQ,ow>IXג-L G_4& `mQB2U Ȟ+q\!֖lP24VvFEK)H8YE0>gptfТ, 32n)rh]=i58RF(m"V1G-}-ZšAE#l1le#;KPTJŃ݅h'sK6#~ EfUǽU,xBwh2iEP;Pݛ #_;*AW[>d([1S'U@a j+"k0FFI7Qbʊ9/ ]-xL.UtdS%/P&C Q6$5t<3wqhJ>m»hyNhNP@G?"I79}tlB]u^Uw#3i״j!QW5]sZ0pd$+yxْD8Tgu/A=K8kohbz 0_xgu8|o̿JkK4b"1{~Bԗ[/=KO3ЖT7Ϩ)ΟXOifŢֈwJ?ŠCJpia?GA M/Ċ/{}sJO\`\fZ6 Vm^oK[Ki{J96'qip(nԯ$60xE^rBA */O8#wCo҂,<N޷u(AO@hLp]q} E7o-9*D0Ѭɤa復7nSм/Fv2c}#X{ B02 L>xd߱vR Z,dP[QG1l氣Z28hna(^ $d߄̜ PblfAB+%R29_iޔK+2Z3\$u`8{¦ܮ,:B_`Sه4#'lZr|/h~x9>OCQ?=^+B`쳗Tn?NnH60@b K!qն^;jN9Zׁ܅BK7&FPKH9vvdA|Hzd?s=M3vGX)7?hѯ+ؗ<}f|)BK i{Bȉy{i^.)fᆴ,+fP@!TJ"Uݐ?AD.?xUUGScvz5.ْ UKncQe輺a^~k)wmű+Da"r *DꝇbS/L;&aiIl, MJFvMZUhfF2':?|Sdew4 2B%yDǴ\|"h _]FƗdul[ /eI\hth ё P\ G&v{?L[w#b妬uP!Tվ7z_{]҇*ROdFQݯ)AtT%xͼBƯ6w{OfSǠ<6C&Sd^BgPe^y"͑g`F֞v+uLgpAq ),HT5SOt8,8L.\m޵5_._]ZVKR OZ8^96bg(ӚdtoAs1 ?6ʆxԟi#:缴軥$wJ4HD..{,:]Di8|}D,8?rDxpb^,;KX3. {z 9_'GWzy ~N)OqH4 FbIbhK<6[35|&Ңv8)U2Y)J6,IB}$^l@Hі!MFH;$#UaeZEE \PLV^Gpc.]u uooyyTQϼc ?N"L^LȐ\ֶIq3ro^+.>_j #7^euVwӗ [`Y7ODS¦c9xi,vvg>'X3^LRu)O+g!seO枲 AHZл -NSG_9#aEhؿv(,eš(^*3M',M H : :c]AG.7vTEQL+U'BwYrO Au;h6YlAr.S'6Lk'2ۙMe A{2N>G{ 4_G&f6ϙKr>Cl 5ЃtE9]JEEgXekFf]X'tƛ||8; nQjOm".z Г0* I(En#6=[62;\CGB* R>z5WɆ!WVX, Tj''en@b*D&U_,4:U"`!{S畾g>Ԟ% e'Sڤ150Җsz?%f+.,cD LyCb*NrXO R(ޙ/nt D.ƟH7tIݐbO6mqe"Μa+G 0L]M񀩐8Jew( Nt<:dգ ptk뭊~#9yl4fL:b",Td<Aց@PZe=cRbZ&8'DmuFA`$0ɠavvuR R[JZ'%CЄ) nXI.1V1Óyl[`S0W`M\ n’%Z3cZ S -U֚8mx`?݌uLaG‡jV~wʯ/zw͙O3Ha]%?#?)dhN|F$ @$V<&@C=SVnF(a=r2T<HFA4\_# ?Yލ fuM&F (;M!{QB6pqVb,G4w6uR:F{πکֺIcxǓC6G3VG947t+™:LĤG!/懢i(26W':<nezVT/jکr$ܒ;ldx;^"!HcrZ؁n͇"]Z~j[jmwJdAQiZSAfD%ئE;CIxp'ǸGkIb[g&uny͘BNKX 5SRnbCv|#`io #ЌCP0wBwڨ_qf Y \+huwV:2]o[׹+ ֡qݖ\C<'̍@`BoYFo}aJKod6q/PȚ:S_*gϟ0!T}j9;.*ޭV}"Fiw0V}u=CjFME%cZwMlwi1d,#ƿt0`LFs<:؎{F7~viZ|[rycdjȍڞLdwGAΙ~øL/O͹xݽPGu".|&ȁ`DPl%΁WZ x}$P>Uy?mp+;EqޞJXb[NZ`A2@[PΛaqc"Dx—2%T|$o. cʅU녈L&5UGXAa6; ) Am8¢}R$⤤h-3nW 66Fxۅ%4l"Y=xxpx'A(˻eUY=P3d4vP(C'0AZ-( R*3S j% ^.[2*j݊.f{;ɵ8l} Q@ύAãyHxxtu٢ bKn^ n65ts'|XY=3/eOĺ2qwu`b%1 U&YY3%Dzv ?!dwiwȧ$nNS3ޣ- h;UTe~˕Ϯe\eLj!r2[;1mW3ѡq&6F4`b~[|=嶡iqMsy_o9˞,Q^l=ß鏓:%PNJCsLyϞ_{ V:MvhDCkaoH:mL@P4g)k[Q´~ZhidAetzM >U J>dR![C0%28yxZԪ=b:^mnP-1E0¢㫜*Yams8SI(֟olEG@EqS-v$y4.Ϟaj7]Cc|_ҕuyT&Et ޔ'kx)uuN-d8"dEd3_'1 qDd]Q)CH=Ffn Sq6\ap;俇XfKy%-N!oOzȡ%ްo>h*YAz42X22NR ba!B`Wd6QrsoC`inP@zL=pEnOb~DHU E.Yw:j-a5SDK 9$5_tBnuM lrLnz1qc^"GvmYXIenHۣ8WTyn7_wϼ >̒%* ǐ]Aiw۟+?bwt8@";uD1כQU ]$;ɁffJ'&VU]\-^K^ dʕO*K*@_ /=WFT3J 7B ai KvEW$R+5x9+.GfG\Beqwޑ̚`5 #*$|p2gm4>nL$,w/h$7V4Q$BN49 ["S߫u0mlԫiDЩM $(yrE`e c*6!/VJr(Ӣx8|&nbB[im 9Nap+tbc.GVKOZpoez@kBG4,ƒlT$-SCF'װǐ֭PUT[<]Cj)Xo}b8JV  IG|k\!XdϲZ|)O@e.[U`o.Rd=gI;u#FpE:[TgI'?,K䑍/tm+(NoK 4?OwGq(g2ckR0J6H1#O/%*QF7'c}z(uMROeggCt L%<.!{F4w53dOŽy83 pxu`X-vg/lnpȇU徭6`V};IGN`mW@U_16\ġ!⼏m ECKf ?=2hoE0O P[js׶oVH=#,TQJpdt5gluH* FV@> & lR _G敓u\m4BQp&]4򉶼;'=O|7%Poў٤PsUiG/%)ܵrˣp$6wOvL׋9Ѭ[~M;sTIe}+r"O}7k,R/#za!٥(q<HXbM6EgD+JiO=Xmޚ+Ԣ.I㏘S{0"ka`hzJasXgj~u  *-4\[^>uUYFݛĘLmO1 6'US?HVFJ^ChVҍa\,H#@j:P q#?n"=qOɎUE!-c.u}A8OCeC@i^K t(U!_-W[X^+(D,h3J8C-XO@Bh0z݅$I Zc *b|Y3rE|;Q@>Ďrzű0xBNG'| ~%¡kyJ9Ko;dv)>ɤ1 F9d1GCzǹj}s tS޸GV)G>iu&,X1 )(9F$*]h0x{t(J9}}HG\oCz7V){dEU Lot"?Kh-2hi]\lDtBa3!r ]ԑGME_\ &3 *KUט(D&tlJSOR3 x | S='}RG$829~1(nJCByHUj;, 귗g7>жGٍ`ʥ'7("50zVKñt X͎II8a~Ԓ ,gDK) Jk@F\cQVvv1L*=4 Noj+PdBC 0@FqԩizJ`Tu3 uR$Lb,H+T$9~dZU-Wp)%׏`t_8-C>[c,Jzfo}mm1,36m=?aߌ=]\b l2mMtXRY<ڜ"So7&_RLC/3&p=5ՠˆ_ٖ8"D5x#%Jq| ީ,E[q+C׽8Lg$> C wZu^O` !Td{i^m҃(RXTW"uܚCj0DAsj5xbQ%/H=C71=*Ch@ VB'<ψ++ ]7Wx׀xjd;p,"\}Nwk4LT`6 wn2133Mcz, | }:ŽiU͗x_>T%% ?fgdLJy1,iBx;BdCUC'\iLh'E/p76jm#.hSs삪8LEs3/wGv-dثg|0=kI+ ʠTu"PLQ@26",q6k!4Ht/S|K5jR+]A∱HU{IS#+Tk`[Ⱥn͜iwIF7+Z8qB&KvȘDaKV@i7oa>xEf @3=|Fk|yrfv)۰lz`Ҷ'˗hяǧ.]3$0r84ҟ=k󤾧FM-Ix1Y$ DLe)`0{Wb\ɞRWxŸDA7RTGmmb9r=.FϫB0BuOU'GvVȔwa7&$A?є[HD5IT$րF{D _(!{֠$D}ƱHfHK]ƏHԖWA`Ű1"d*^qF͵hf¬cmƀQnBwj7|Hlr I=8D(.E\J0L%AJ`(_s`yh)% Uw`mT~ONIƶ oB)ɴ\<\^$P8QP-K=LQv1hy${_"y6WrТ\[@H[_ =3M̝])ȇHZKu"qE&:Cj+)"Jʕf;3 '\m*i=dRsۧ1g5SƄUMhV4fW[qA2iӜv )XvY#!=l09ȩ7%Ec`M༙Kt;^+Y oEj7p**%?"KyO#E.g}g8iuY@43I}` ΒTwkDCyA>;q\J~ݵpGwB<*P?3)u<[{&MnVY2,=ց9g\(F'Ot ?1jM[#ȱq[c]f`в@xU3mPx\k;ƋrHfW 7ީ\6\9j k(A9J'U:י؋[[#YʔpK :R.~VqL;c-BI9Zt`qrI{* ?Up彃ۆo e(\>jf8!$nEdhbf;q;AG Z~9DO0X| ?R-M A#RF'\.1n\-%XT@S<6-L0jgEVi:<(ݝ|(.hQZZ6gT_`73zB7IY+aڢ-Kou%m zV//؂CuuX4$sEډ(6dtkЀ%d΁ @z(z [~&"sy \GtuoLLlu9(W[N)^w>.Gn{G>d]%P֪ So'"x\`:.4UxW{[] +=9q=A2٦p1lQSP> Nd^c&n[ܮFٓM\lte0x ӈ지!o;6gW(MK┿jeq/oL&Bw5ujχ/M:'5;@I]bZ5b%!+p8 UwkK㓵wp>>K'ME* vTQ>WzoCNt/Vyfh-.5\@5q p`keыXi -]ʱTo%h#^1 ~D?F8Ia9d PyB֕ 3tBuYBufEs1>~YUEGs;۰KXrؗĉ6(wu$}B3:gXhF_xo!%*bYqi!`Ɏ|_0%I6$%wf$"$Mh2蠔w*s@p>G'׾bc1q =]3)'&݂f)JP| HPsFS*Qy(Ou5o·u@K;#5PonK)]_zeqE,Ϭ-^>Kbkh 瓒x5?O4e*V'HJHrbbBg>v4WkCݿ &,|1;ٓU%C rtQP#qUL:Z -Lu%)$ADSSArו]̋~> 6ݗ QF&V:PQ6S:a81˛d)}_3q'MHHf.B=}s~KS]qE.ex! ՙ"F,k9GeX~ .&z=؋U/lE}[l6R\|Zԙ@,"G@ 9%šZ|!`kVvK\7  џgqWe!N7gѡu MX+a*@'ۈ؅8X1e uNز^U|n Է=4kk;<0}SK*OT (˅&5Ee,Q\lH([su(zÑêt*d/~Hm}Hق` bQ`۟LngE`oYԒz$Lc&`k42}A)VЙE& 0+~n'SLȨn=C+h]P`ɱnܨ5//;WO_FK?[{u6_⮂- WD3DaZA#MI]zpH#tQtOtblnw|:꺅gДbj>b6 [fjkWρykJ-)sc6,r6AaEN8ssjG^It+xKV!m񓈑KG$i a "|Ŷm}e`&p,q P gaׂI`.00*j8RUHCR$xɝ57>d㜝)GXObX<Vs-d,K/ű,dqǹQTsEp5,.$-~?91$|lHk>Sy^*ҍ>xg,skLKx0'3fP#?t>+ԧ 8 rjVRE-OY~.^yWcS!c[ޥޯ(n?Y܇ȡG,E=x0$ GokxoXO Px~E  &g%5M@Lgr,s>aWU# 2X&W§A~T||fs=/Z+_/i)u/$^s4NbQ?Ș$밟[g&ps4_Snoҏ 7 3_jWek=Yi}AU+X~#PX˰Tdg9gM!W7+,ӔR0křvg̺WkQ`M =18lcpα;' c~9w Kϯ{)W2.`8at_9[pƶ:}t# 7ݲ}9]z=ycX#_Ǜp*mvu֊+ T6؞8ԙ; -S+pGLH|4{@˕-_|J|~MG97<(MnU~s{Ng'o+f(8zQZij{_?b[b9TKG'?ܢ/s`9}Rfze9egӫ- :/l3[vyn56SkIPY" :^{/"mǓOi-=wƽiG̩O\n1t>r?_QwuyG_1a×\ߘAHp9k'K6 CjbMa=kYy6u/^:{YZ/Yyjba-Gͭ0x~EtWf/L<~MO(:OĥAikJOc[-"vήs'~%iL 7jk2}oևi|{ZiJǛ6)!f:Y5ݸ~2W3rֺЀlA?|652pN`]3Y (\ sRJsRKRk3Ӹ˚ endstream endobj 8 0 obj 34184 endobj 9 0 obj << /Length 10 0 R /Filter /FlateDecode >> stream x]n0 E|#B֤[mjS|Kz28^c(m2_MeI(&q)w†x/jO|d. yw'^KAxGya>XbXԫEX##p{-A{笯1y-<@]ͧ^ endstream endobj 10 0 obj 308 endobj 11 0 obj << /Type /FontDescriptor /FontName /TCPINR+NimbusMonoL /Flags 4 /FontBBox [ -46 -274 650 821 ] /ItalicAngle 0 /Ascent 821 /Descent -274 /CapHeight 821 /StemV 80 /StemH 80 /FontFile 7 0 R >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /TCPINR+NimbusMonoL /FirstChar 0 /LastChar 19 /FontDescriptor 11 0 R /Widths [ 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] /ToUnicode 9 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 6 0 R ] /Count 1 >> endobj 12 0 obj << /Creator (cairo 1.10.2 (http://cairographics.org)) /Producer (cairo 1.10.2 (http://cairographics.org)) >> endobj 13 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 14 0000000000 65535 f 0000036703 00000 n 0000001121 00000 n 0000000015 00000 n 0000001098 00000 n 0000036444 00000 n 0000001262 00000 n 0000001463 00000 n 0000035775 00000 n 0000035799 00000 n 0000036185 00000 n 0000036208 00000 n 0000036768 00000 n 0000036896 00000 n trailer << /Size 14 /Root 13 0 R /Info 12 0 R >> startxref 36949 %%EOF Gdraw2-v0.0.3/t/load.pdf000555001750001750 10754312001671021 15064 0ustar00yangxiyangxi000000000000%PDF-1.4 % 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xUn1 +P,  Ʒ"cCC~4ؙS-ꉢ?,Xg|7{OoW'8l 1Z*|wW MHC õٯDYa3)`P׈){)Θ>_fT̹즬vSV1vCѦؕJLI/ ݣ^Q^MBGfPJ]/%yu1T,zV, bۇ9؜;baRPa&00cM)n/Ԟb"BQxs$㻑Y7ScKK/1`JV\"{uT8cYtԳcjL'+.v.J%'g{H&|«Ԛ,ۅgq$zRMp9d-B D[E۩ک2VdvIEƪ]8W|U`d8M'/9 xr`%\T8^Qߜ ޲K(̱DdB3?) endstream endobj 4 0 obj 655 endobj 2 0 obj << /ExtGState << /a0 << /CA 0.5 /ca 0.5 >> /a1 << /CA 1 /ca 1 >> >> /Font << /f-0-0 5 0 R >> >> endobj 6 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 1600 600 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 7 0 obj << /Length 8 0 R /Filter /FlateDecode /Length1 1574 /Length2 32883 /Length3 545 >> stream xcx%[6N:Xmvlctb۶m۶m;t{?<\5M F}uy;O';($F,6xG 7T;VD|2e w^j,t6< sy!OAU`/p@f:YfTc%+B,Xf,7~װy-i^.6 ę߉[ h˕Hշ ^W | 5̭vՎ2H3AJ֥Gm}&ɶ鱌[B/<Kba?G09 ӯ:{W o6UjrŁj n~SKk- M=1'tqDtz2/a̒>lEzunl눶~dXʨPkfϒ%o7bUbtK" "w5"J/! f;T{~1ABIb.(UZZ:!,zNwP0G1dy$\FcY& t.0!&޼kty"%?k6m6̋cyx2LD(** ;j|pi M3Bux "r:볞F0*Va6 f=8G"}uZ߼ e jVrwr`ث5$W C"kdr1\YgRmJ[AMĄu Aq#gj&$'t}-5Vc Sי9ׄN8,(^YdJQ3!Y9Q~~$*f$ZĤ3O;$`~'J܅@b5&[`~•Ak45ɖdNp'{?wp.UR,qپ\>*NA?&JlrPᙫr,CS9uQ2t<\r??0E|<_zak6VZcgk ʱj0B,OЃAN}y>oE=Q.2x­TFьr'0K&'tՋ_=n9C>pO] Ճ1 $s$B! Xb!KYIr`6tszljKQDIf 6 [ɺU>`(rHb\8_R1iJj/ɢGa>61[ھ~nR)QbWϱoAsetV={E 9t7CN:$8m"Z-\+)a O2{z9ub]è$ wYtw"# 3;Nêa`+ h!7Wۥ-y33MmcI&Dxd tRצgyիXwXZi_0&s1,r;9P?kתFA 4!WGrJiITSZ,S 39;Un#e4<(;Є*mLDa 3e`!V,*1o@%^wZjh5[ӀK{ T @9(6J@O>oEF @6#EydQ9ha&D#4!yal7L?~aL$AqtrTxCư&JC½z6È0r0T>J sbϮjs PUզz҃ȤeH}]["n'O#[)smTlFD+l:! UW i/!DjOSTwgIp7fjY?nIX.^1ґ2m{Q&e17 Q sD+J3n QQx'QcBY Ƀz--c0ȫ@Z[*1# tSaZm30'r (r!7wJ~F3!0<}hr{.>99/o](g4l_k>iH%?5V%U3}GY^CA4Y,Om vaCk.by60/Uq@qsyVɤ/B`-5J4unqR d]_(,E} ?1,D@tcrGF1sZ&t4Y?DIs? 7/} fAyJ~3ZLc4&cSZy|4XOW8`QM>Rlw](A40рE-A&V;]4=1ΪR?&T|[cJ8B9Հ[Ec؟e.rx$\]/21[r m`7(s NbwR6|եΏ28n8z^,Ro㜲%qЀD`t Dwy\,%%Aq$bXy{Igx쟠샒Ob O@`k0hQ=I_΅kxZN7,Vʽy ~z[@bBe;*=ۨ +G>4i'Jjxtv(\l鏐#*fd_ F&t+9{ '@ɠbW#dy3,)^i\RA"3 Pf&1{(mD\hPSvC~?tF^%|4?A-yt U|1um9 G.2K @ew8;}nMDiI;i}|6S#6V`sq@4 N*[S 1#|+'jom"Ӄ#X UåP(JK.PzMN{Ln9p+I к \e,K)&|?{U Ŗ 4h=l~[y!?tau0bh:|#"|L ŷWLآ$wbcx$o,g( C䒕 CJ ^׃/5B\fhUfƯ>gpi6Y*<w&8{E*2R̭Э UZ=e;nDIHKՐٝ,-JVVAsCl=y I-ٺ[}qb8-\ϛ De %',7l(_l;նr)obl/:)s絛P56{ȧΓsBp ٩MA3%oU&Ԝ m..4=+]_v,z۰!crW6o}o .$n!m0hd py5's{u-v ]m)'jk;6r˸FXeY3`wܥ܃ڋ7+;Oc s%\nL[NsNcyl6ݐ; U5Κu O ޵wSΑ~s@#M{ k܂2b?]ك039:k?-n•+ ^ Ew&e;TFoO{+k*E;8D܉G!'N+Ek's ߇(*w71CmvA% @iaYM*a2y IrDMIEfv鞟D*.I{19M'SRz ciUB' s:/Q篒 Zg:+W"Xi*q6龴y-4?{2;\V_R@RbSNy-6qU"lFe Xu{;hXI*(fHU^0>F}gik*> I,s`2s~i=6HmkȚ0aVU1O*^xTwX4]JBhj]N-L:7)n,0 O xlAp=947ҩZFXRHQ1PTY4Pp{O*#ri!klA b70`:I7JRTŮJ]$}~ N[<1D`dxZTWM:qR<I]8i#:]u@JPbAD|^czoκFfBq4iHsB~O6X!8{;jMXSggOn3/냝//7 &wvҁ6Thi0ZS,P Bx=۲w%}uqHR{{2gFs'v03liD93_z1Q>iF2UڌiEIjԌPQWq1FJCiDvk*ހq-'f'5JkV[ip?`$@B+t(Q#X(piTeﻦ~fꐇSO"5Pkyq\:iԠEjkK +x$ɿ".vS\F~N1af$ܹD?[ !['~$ACPVRm@*z%bb]:K(gh>AlS9r]5*^nbw$|2ysKL.a a2Jr;sz/yl8Lk!FVUlk /۰Fؖ>$z,O_^9[}3'ڌB RL!G,޹#/Lݓ"~yI17(BW}D^b8詆|AȠ̷}_&R| +cbk71Յ79?[QMy5@JԤ̀GcέG sͬ+:Sp!츳7rtfU_%^jͱ.Xr1ČY@PcTĈ{Xyc:L {J++tъ"_+ ;|.b6^\g];UhY͛b,| P 7smdO!4e?O* V1Jl/N9:J<7 H"!Ðc4'`5}%!nv\5; `tr٢ _$ Ⱦ ߝdCN" +o㬒ҶMc0 IzJ6 |?6[T#B7 kq%5uc6.%Њ?;1s)bd#W}nݩ^#!IT5˓ so ճmM4󕃦AÊP[2Qy˹eso0@rq8Z[}*H[ v9]_QTL_NϞNJ6 ׯ.?uj5oj}{s>@@L١̯]pO?x sC0ܐ:f\>zO(J|I{EUwƊ֟>a+F4oAQ[oAc]Hj6~@\ n'RǸ|I4k pWYjg&@ 26x<= ;,<+ ċÅ$q9cMFN=˯ 8K)8W}]: srGE%UҕQĈHpjuɃ[^WZr@[5b$ElGqN~TČyX"oׂ87Eo]SnC761e#<[cEjbH? D fhy6!\F`Ş3y7,&Y{9@9\*Du2`shz!_Z kTVXϩ3v@iWWZP)˯o\Axt\ҌhMt~A9cTT:>Ŕk_$ZBƀxƩgf(SAS-JtԮ PȢ$My]V_ h T4TѿU G<[="Z,3&]VNU~OGrbIB{?d2҂d=m{K#Nz0Fd/y]_6Ӵ}3L||ː-ub7v4C S# h;sXxn&~]P!@$π#mu݇$|}+LޘNҞwŇV46E"??N8(ǧsjTƞ,ڦE%40}7I&܉?\~hqOk&lKlƅR|.!}<7ǁ&tvtzS̥{=DjXilԻ [Q 7m3:~I\> ! }/LQ95e1eojr%κ?x*e/m5H5,ݾu̚ Hc>}nԠC^uR9TMcA] Y_ǷLаrEUl/ѪJWD v';/7☋ag)wi4,[Hzh`9o(gZ;-ZYyQJY\G#+)[+Vxx? _eI$qҦXK dѼgWZ{0[2"A_" l藚oz*ӆ!L遌)﬚ PR⦶_ wf!6YJC= FaWw-֎ 4}Sz]'~8y3tG~^JI!qBhCf"Y4`R{sMA쁊f+AV%'m`V@DS,{[QeeЍ@n O8ځgCUebd6uz%^-1uE<ƞaq0 $ Ub#lwA)yKw6ӁIAoB]vFI^I.>#/|kak hL<ܧ+[| j3rXP"mb?O(s1 hHCbf#wFܓ7o#ɾ> g`jA!= Ym iqh/rօ`x٩z3zO p|k662Ӈz%[SZg@Cқ-+&{p琳@^Rvx,{vky™=T}+5c,3_xsS[wLbAx!190ո]BmD2}GɛvofO^e *\HIt6N-ue&_TOt9Xqu{x\څzu;tjF XGHl"xj ;f׊{c 珋qP *J7?Mm[Xŭ]z]SzZ ,sͽvmi k .K[ţV}~qhǞc4 B.-n7` wEm.NP nQ6a[r v l] ql{/uc^Ѳ]Y yvj =c$9Xܲo(Lf1 A@$A 0_Kw5D9Ibn;fl|5ELJ햍p+ 2wKw+c."ozNBC(&IȜjpùR{7)Fӷ\?V2xcExP-כѽgw!WPt)Q()ϒxrJͯg^p%4N;s)ĈL =Xhn^({y_E9~R bP9EK驶 ( 2B(P;ǽ(Ĝ`MxHjIJ%K@JJ#c/%£}8P#DuDpRhY$!5dȣ)G  ?:~SPw "f]$luS 'k[rA%J/+ `ii-uh=㎥|KHZC<S`ղD "N*驿򱑻d>P7/AҸy/$ڠm0}f*y]4I14V6Mn_Y% $ ; mǭx*dyh?.ﶏZ`RdljL5:LZ8pϡS8I ɛ;ݱIC GQs\ɛi}O:B0+o",yi!mV`rLG"w~+?rbg[L吥 c|Uh@vDȞb*e8ب;6lq<"Xnчp&1_hqk!'8`Ҏڕ9\e*zX9 O2[Eo CƆ#.lRBNkt%Zwk' l#!x gt)/f-;$F~wsV!r@gHP%u`:$ n1#Mw~n{氕kV<+mUa:[ip1J}@9<mwH0&+k"s`*}& h;򻽔04[~:P02(3*ZCWXv9mJDSIf/  ]`MKk`T],rh+- k. OmI\#EXg"U"F7TDqj> ǻOr^܉("Cˆt'UD5Ո /q>K 4etbtnbf!hHAJЫ)-I=_J9]ŇP2nӓ~"qCvQs јů~;;CWlS-3F+ݤjc7m٫z*!1V\?u1$ns4+qE f]ϳ ]"tJd:eMX7Xݗ+8P7&I_K>tG1K7MPq0j;2{(VVY/Irښ%?]-d\>MltK5?H6CQ 64U5l"+ЭoiXjڵ]&XEn0h&np./@W 2Y/%cl|RC; †l1 [z0˜:ОL؅Yj8Ed#82 ϵH{y\i̋dfpo:^oŚ}Pٖ !8콂 'WoMאU5_,VGtS%n5[ $uCsۓđ#W5J ?a Y қu(o=-S)`|P ylMBKNHE2>-V8:URoaks+|x;H"i"0  Dgӗ֎NJu@?r@M+c![{\Q+T F۾h+݋FE`{nƱ2/@Mt1 CW@sxcs#\#Ye[spk|A"K :x^6D^K%Zjq>_oo4%NܶIϝYe?MzNj.6[*:(!SfgfLt#%*it!4+_?a1R`#`KƭrБbܽofW|[?8)D}v7Ηي;v:ߔ_i5_0]a]ax Ԙל&+ dΕZ5M(J{%훿Bo>@x@%$ՆQleO})1֏>^rBA */O8#wCo҂,<N޷u(AO@hLp]q} E7o-9*D0Ѭɤa復7nSм/Fv2c}#X{ B02 L>xd߱vR Z,dP[QG1l氣Z28hna(^ $d߄̜ PblfAB+%R29_iޔK+2Z3\$u`8{¦ܮ,:B_`Sه4#'lZr|/h~x9>OCQ?=^+B`쳗Tn?NnH60@b K!qն^;jN9Zׁ܅BK7&FPKH9vvdA|Hzd?s=M3vGX)7?hѯ+ؗ<}f|)BK i{Bȉy{i^.)fᆴ,+fP@!TJ"Uݐ?AD.?xUUGScvz5.ْ UKncQe輺a^~k)wmű+Da"r *DꝇbS/L;&aiIl, MJFvMZUhfF2':?|Sdew4 2B%yDǴ\|"h _]FƗdul[ /eI\hth ё P\ G&v{?L[w#b妬uP!Tվ7z_{]҇*ROdFQݯ)AtT%xͼBƯ6w{OfSǠ<6C&Sd^BgPe^y"͑g`F֞v+uLgpAq ),HT5SOt8,8L.\m޵5_._]ZVKR OZ8^96bg(ӚdtoAs1 ?6ʆxԟi#:缴軥$wJ4HD..{,:]Di8|}D,8?rDxpb^,;KX3. {z 9_'GWzy ~N)OqH4 FbIbhK<6[35|&Ңv8)U2Y)J6,IB}$^l@Hі!MFH;$#UaeZEE \PLV^Gpc.]u uooyyTQϼc ?N"L^LȐ\ֶIq3ro^+.>_j #7^euVwӗ [`Y7ODS¦c9xi,vvg>'X3^LRu)O+g!seO枲 AHZл -NSG_9#aEhؿv(,eš(^*3M',M H : :c]AG.7vTEQL+U'BwYrO Au;h6YlAr.S'6Lk'2ۙMe A{2N>G{ 4_G&f6ϙKr>Cl 5ЃtE9]JEEgXekFf]X'tƛ||8; nQjOm".z Г0* I(En#6=[62;\CGB* R>z5WɆ!WVX, Tj''en@b*D&U_,4:U"`!{S畾g>Ԟ% e'Sڤ150Җsz?%f+.,cD LyCb*NrXO R(ޙ/nt D.ƟH7tIݐbO6mqe"Μa+G 0L]M񀩐8Jew( Nt<:dգ ptk뭊~#9yl4fL:b",Td<Aց@PZe=cRbZ&8'DmuFA`$0ɠavvuR R[JZ'%CЄ) nXI.1V1Óyl[`S0W`M\ n’%Z3cZ S -U֚8mx`?݌uLaG‡jV~wʯ/zw͙O3Ha]%?#?)dhN|F$ @$V<&@C=SVnF(a=r2T<HFA4\_# ?Yލ fuM&F (;M!{QB6pqVb,G4w6uR:F{πکֺIcxǓC6G3VG947t+™:LĤG!/懢i(26W':<nezVT/jکr$ܒ;ldx;^"!HcrZ؁n͇"]Z~j[jmwJdAQiZSAfD%ئE;CIxp'ǸGkIb[g&uny͘BNKX 5SRnbCv|#`io #ЌCP0wBwڨ_qf Y \+huwV:2]o[׹+ ֡qݖ\C<'̍@`BoYFo}aJKod6q/PȚ:S_*gϟ0!T}j9;.*ޭV}"Fiw0V}u=CjFME%cZwMlwi1d,#ƿt0`LFs<:؎{F7~viZ|[rycdjȍڞLdwGAΙ~øL/O͹xݽPGu".|&ȁ`DPl%΁WZ x}$P>Uy?mp+;EqޞJXb[NZ`A2@[PΛaqc"Dx—2%T|$o. cʅU녈L&5UGXAa6; ) Am8¢}R$⤤h-3nW 66Fxۅ%4l"Y=xxpx'A(˻eUY=P3d4vP(C'0AZ-( R*3S j% ^.[2*j݊.f{;ɵ8l} Q@ύAãyHxxtu٢ bKn^ n65ts'|XY=3/eOĺ2qwu`b%1 U&YY3%Dzv ?!dwiwȧ$nNS3ޣ- h;UTe~˕Ϯe\eLj!r2[;1mW3ѡq&6F4`b~[|=嶡iqMsy_o9˞,Q^l=ß鏓:%PNJCsLyϞ_{ V:MvhDCkaoH:mL@P4g)k[Q´~ZhidAetzM >U J>dR![C0%28yxZԪ=b:^mnP-1E0¢㫜*Yams8SI(֟olEG@EqS-v$y4.Ϟaj7]Cc|_ҕuyT&Et ޔ'kx)uuN-d8"dEd3_'1 qDd]Q)CH=Ffn Sq6\ap;俇XfKy%-N!oOzȡ%ްo>h*YAz42X22NR ba!B`Wd6QrsoC`inP@zL=pEnOb~DHU E.Yw:j-a5SDK 9$5_tBnuM lrLnz1qc^"GvmYXIenHۣ8WTyn7_wϼ >̒%* ǐ]Aiw۟+?bwt8@";uD1כQU ]$;ɁffJ'&VU]\-^K^ dʕO*K*@_ /=WFT3J 7B ai KvEW$R+5x9+.GfG\Beqwޑ̚`5 #*$|p2gm4>nL$,w/h$7V4Q$BN49 ["S߫u0mlԫiDЩM $(yrE`e c*6!/VJr(Ӣx8|&nbB[im 9Nap+tbc.GVKOZpoez@kBG4,ƒlT$-SCF'װǐ֭PUT[<]Cj)Xo}b8JV  IG|k\!XdϲZ|)O@e.[U`o.Rd=gI;u#FpE:[TgI'?,K䑍/tm+(NoK 4?OwGq(g2ckR0J6H1#O/%*QF7'c}z(uMROeggCt L%<.!{F4w53dOŽy83 pxu`X-vg/lnpȇU徭6`V};IGN`mW@U_16\ġ!⼏m ECKf ?=2hoE0O P[js׶oVH=#,TQJpdt5gluH* FV@> & lR _G敓u\m4BQp&]4򉶼;'=O|7%Poў٤PsUiG/%)ܵrˣp$6wOvL׋9Ѭ[~M;sTIe}+r"O}7k,R/#za!٥(q<HXbM6EgD+JiO=Xmޚ+Ԣ.I㏘S{0"ka`hzJasXgj~u  *-4\[^>uUYFݛĘLmO1 6'US?HVFJ^ChVҍa\,H#@j:P q#?n"=qOɎUE!-c.u}A8OCeC@i^K t(U!_-W[X^+(D,h3J8C-XO@Bh0z݅$I Zc *b|Y3rE|;Q@>Ďrzű0xBNG'| ~%¡kyJ9Ko;dv)>ɤ1 F9d1GCzǹj}s tS޸GV)G>iu&,X1 )(9F$*]h0x{t(J9}}HG\oCz7V){dEU Lot"?Kh-2hi]\lDtBa3!r ]ԑGME_\ &3 *KUט(D&tlJSOR3 x | S='}RG$829~1(nJCByHUj;, 귗g7>жGٍ`ʥ'7("50zVKñt X͎II8a~Ԓ ,gDK) Jk@F\cQVvv1L*=4 Noj+PdBC 0@FqԩizJ`Tu3 uR$Lb,H+T$9~dZU-Wp)%׏`t_8-C>[c,Jzfo}mm1,36m=?aߌ=]\b l2mMtXRY<ڜ"So7&_RLC/3&p=5ՠˆ_ٖ8"D5x#%Jq| ީ,E[q+C׽8Lg$> C wZu^O` !Td{i^m҃(RXTW"uܚCj0DAsj5xbQ%/H=C71=*Ch@ VB'<ψ++ ]7Wx׀xjd;p,"\}Nwk4LT`6 wn2133Mcz, | }:ŽiU͗x_>T%% ?fgdLJy1,iBx;BdCUC'\iLh'E/p76jm#.hSs삪8LEs3/wGv-dثg|0=kI+ ʠTu"PLQ@26",q6k!4Ht/S|K5jR+]A∱HU{IS#+Tk`[Ⱥn͜iwIF7+Z8qB&KvȘDaKV@i7oa>xEf @3=|Fk|yrfv)۰lz`Ҷ'˗hяǧ.]3$0r84ҟ=k󤾧FM-Ix1Y$ DLe)`0{Wb\ɞRWxŸDA7RTGmmb9r=.FϫB0BuOU'GvVȔwa7&$A?є[HD5IT$րF{D _(!{֠$D}ƱHfHK]ƏHԖWA`Ű1"d*^qF͵hf¬cmƀQnBwj7|Hlr I=8D(.E\J0L%AJ`(_s`yh)% Uw`mT~ONIƶ oB)ɴ\<\^$P8QP-K=LQv1hy${_"y6WrТ\[@H[_ =3M̝])ȇHZKu"qE&:Cj+)"Jʕf;3 '\m*i=dRsۧ1g5SƄUMhV4fW[qA2iӜv )XvY#!=l09ȩ7%Ec`M༙Kt;^+Y oEj7p**%?"KyO#E.g}g8iuY@43I}` ΒTwkDCyA>;q\J~ݵpGwB<*P?3)u<[{&MnVY2,=ց9g\(F'Ot ?1jM[#ȱq[c]f`в@xU3mPx\k;ƋrHfW 7ީ\6\9j k(A9J'U:י؋[[#YʔpK :R.~VqL;c-BI9Zt`qrI{* ?Up彃ۆo e(\>jf8!$nEdhbf;q;AG Z~9DO0X| ?R-M A#RF'\.1n\-%XT@S<6-L0jgEVi:<(ݝ|(.hQZZ6gT_`73zB7IY+aڢ-Kou%m zV//؂CuuX4$sEډ(6dtkЀ%d΁ @z(z [~&"sy \GtuoLLlu9(W[N)^w>.Gn{G>d]%P֪ So'"x\`:.4UxW{[] +=9q=A2٦p1lQSP> Nd^c&n[ܮFٓM\lte0x ӈ지!o;6gW(MK┿jeq/oL&Bw5ujχ/M:'5;@I]bZ5b%!+p8 UwkK㓵wp>>K'ME* vTQ>WzoCNt/Vyfh-.5\@5q p`keыXi -]ʱTo%h#^1 ~D?F8Ia9d PyB֕ 3tBuYBufEs1>~YUEGs;۰KXrؗĉ6(wu$}B3:gXhF_xo!%*bYqi!`Ɏ|_0%I6$%wf$"$Mh2蠔w*s@p>G'׾bc1q =]3)'&݂f)JP| HPsFS*Qy(Ou5o·u@K;#5PonK)]_zeqE,Ϭ-^>Kbkh 瓒x5?O4e*V'HJHrbbBg>v4WkCݿ &,|1;ٓU%C rtQP#qUL:Z -Lu%)$ADSSArו]̋~> 6ݗ QF&V:PQ6S:a81˛d)}_3q'MHHf.B=}s~KS]qE.ex! ՙ"F,k9GeX~ .&z=؋U/lE}[l6R\|Zԙ@,"G@ 9%šZ|!`kVvK\7  џgqWe!N7gѡu MX+a*@'ۈ؅8X1e uNز^U|n Է=4kk;<0}SK*OT (˅&5Ee,Q\lH([su(zÑêt*d/~Hm}Hق` bQ`۟Lnd==L󎬱 tFp~ ֐/DlQZt{eogwHH;B( #O-y_\R_.9el`Z6S73vIƭ.W1oN1B{=,XL=V; ?!fܡ8  л~Gh<]_Uo{+uwtKgZbJ]&@_,#bɥ)>lZOs[qg^mBȋDt仧\4[΀uD{DWSTWeej*-aoLiq,겗o)DKKxVR5)ٮ m?> ( h+A'Hg|g(Lʭ4}%0p{%5(3d j00 W5wf Rߩ&ǽJL[CtezySTۊ* tjy"EopǶWZ8P<[(tc>lKߑ#+߿`_?L]ؚZ+YRaV{]l;mj>*yzʥ_ޖyrs>v/%_wӡXgrO(t^QmtWYu>{6^eJ[ڞ:g1mbw❥ڮz%jGzsX,EK*o˫R)#q\~aX{7v Z34w9/$Eׅg-kaȿGЯibJGyR6qb(pA߫?H>]Կ9cY?F)]|޺9a&Sh)*u$v%?+:G>ِ^~j@'^)} 5UYs87~_(oƕqj_ZEzx'г_'ٙ7sB޹J'Y\Oc*Z{eOJ3qs>h~r-ݜ'6g/ex~[l!NL\D~ϲ9W2gDikԀaa@rNjbQI~nbQ6WuQjqI~Qjmf@= endstream endobj 8 0 obj 33969 endobj 9 0 obj << /Length 10 0 R /Filter /FlateDecode >> stream x]n E|byRnCM!0}M.@|vu{Tq&Λ|aijn8'yXS,\R\# ޢNC.!>]mN«*6oz.lS|s]gKPgv2ZbY*aen kmaC+{H#&~`2? Q! ouai[E%%?ykY4 xJz/1o160r8>t endstream endobj 10 0 obj 295 endobj 11 0 obj << /Type /FontDescriptor /FontName /NimbusMonoL /Flags 4 /FontBBox [ -46 -274 650 821 ] /ItalicAngle 0 /Ascent 821 /Descent -274 /CapHeight 500 /StemV 80 /StemH 80 /FontFile 7 0 R >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NimbusMonoL /FirstChar 0 /LastChar 16 /FontDescriptor 11 0 R /Widths [ 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] /ToUnicode 9 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 6 0 R ] /Count 1 >> endobj 12 0 obj << /Creator (cairo 1.8.10 (http://cairographics.org)) /Producer (cairo 1.8.10 (http://cairographics.org)) >> endobj 13 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 14 0000000000 65535 f 0000036094 00000 n 0000000768 00000 n 0000000015 00000 n 0000000746 00000 n 0000035854 00000 n 0000000909 00000 n 0000001110 00000 n 0000035206 00000 n 0000035230 00000 n 0000035602 00000 n 0000035625 00000 n 0000036159 00000 n 0000036287 00000 n trailer << /Size 14 /Root 13 0 R /Info 12 0 R >> startxref 36340 %%EOF Gdraw2-v0.0.3/data000755001750001750 012001671021 13706 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/data/FeatureImporter.glade000444001750001750 16630312001671021 20227 0ustar00yangxiyangxi000000000000 False 5 True center True dialog True False question yes-no Are you sure to remove selected? True False 2 True False end False True end 0 1 1000000 1000 1 10 1 1000000 200 1 10 1 1000000 1000 1 10 1 1000000 200 1 10 -100000000 100000000 1 10 1 100000000 1000 1 10 -100000000 100000000 1 10 800 False 5 Import feature from sequence file True center normal False True False 5 True False 0 True False 3 5 4 5 True False 5 True False 5 Add track False True True True False False 0 Add feature False True True True False False 1 gtk-edit False True True True True False False 2 gtk-go-up False True True True True False False 3 gtk-go-down False True True True True False False 4 gtk-delete False True True True True False False 5 False False 0 True True automatic automatic True True FeatureImporter_TrackModel False 0 True Track name True True True Feature True True True Draw as True True True Feature name from Stroke color Fill color True True 1 True False Feature and track True True True 0 True False end gtk-ok False True True True True False False 0 gtk-cancel False True True True True False False 1 False True end 0 True False 5 True False 0 True False 5 5 5 5 True False 5 True False Tick interval: False False 0 True True True False False True True FeatureImporter_RulerAdj True True 1 Ruler False True True False True True True True 0 True False 0 True False 5 5 5 5 True False 5 True True False False True True FeatureImporter_StartAdj True True 0 True False to False False 1 True True False False True True FeatureImporter_EndAdj True True 2 Only import features within range: False True True False True True True 1 True True 2 True False 5 True False 0 True False 5 5 5 5 True False 5 True False Window size: True True 0 True True True False False True True FeatImporter_GCContentSizeAdj True True 1 True False Step: True True 2 True True True False False True True FeatImporter_GCContentStepAdj True True 3 GC content False True True False True True True True 0 True False 0 True False 5 5 5 5 True False 5 True False Window size: True True 0 True True True False False True True FeatImporter_GCSkewSizeAdj True True 1 True False Step: True True 2 True True True False False True True FeatImporter_GCSkewStepAdj True True 3 GC skew False True True False True True True True 1 False True 3 FeatImporter_OkBut FeatImporter_CancelBut False 5 Edit a feature import True center True normal False True False 2 True False end Ok False True True True False False 0 Cancel False True True True False False 1 False True end 0 True False 4 2 5 5 True False 1 Import features as: 1 2 GTK_FILL True False 0 True False 5 5 5 5 True False 5 True False 1 Stroke: True True 0 False True True True True #000000000000 True False 1 True False 1 Fill: True True 2 False True True True True #00007f7f7f7f True False 3 True False Element color True 2 3 4 True False Blocks False True True False True True True False 0 Tags False True True False True True ImportTrackEditor_BlockTypeRadio True False 1 1 2 1 2 True False 1 Feature name from: (comma-sep list) right 2 3 GTK_FILL GTK_FILL True True False False True True 1 2 2 3 True False 1 Feature: right GTK_FILL True True True False False True True 1 2 False True 1 ImportTrackEditor_OkBut ImportTrackEditor_CancelBut False 5 Track name True dialog False True False 5 True False end gtk-ok False True True True True False False 0 gtk-cancel False True True True True False False 1 False True end 0 True False 5 True False 1 Track name: right True True 0 True True True False False True True True True 1 False False 1 button1 button2 Gdraw2-v0.0.3/data/block.png000444001750001750 47112001671021 15625 0ustar00yangxiyangxi000000000000PNG  IHDR@ -sBITO pHYsttfxIDATX Dg6~x@$®\TI8+0y^>[d0kT$}y"Kgdwr)z!aYN1(M)N2Dd9@pHp}ݷY\ 3 -{IV`EY :nFS`M?$6CR EM M?~茶џog"^ |sj+IENDB`Gdraw2-v0.0.3/data/TrackEditor.glade000444001750001750 3044412001671021 17301 0ustar00yangxiyangxi000000000000 65535 1 10 -1000000000 1000000000 1 1 10 False 5 Track Properties True center True normal False True False 10 True False end Ok False True True True False False 0 Cancel False True True True False False 1 False True end 0 True False 2 2 5 10 True False Name: True True Display name of this track False False True True 1 2 True False Start: 1 2 True False 5 True True Track location False False True True TrackEditor_StartAdj True True 0 True False End: False False 1 True True Track location False False True True TrackEditor_EndAdj True True 2 1 2 1 2 False True 1 True False 5 True False Element Size: False False 0 True True Element width for this track False False True True TrackEditor_EleWidthAdj True True 1 False False 2 Show track guide line False True True False a grey thich bar occupies full length of the track 1 True True False False 3 TrackEditor_OkBut TrackEditor_CancelBut -1000000000 1000000000 1 1 10 Gdraw2-v0.0.3/data/tagset.png000444001750001750 30112001671021 16012 0ustar00yangxiyangxi000000000000PNG  IHDR@ - pHYsttfxtIME9U`IDATX1 CѸ;0ޒ(bَyxKƲk[SSNQAc[g]3ݚraBm 100 1 10 100 1 10 False 5 TrackGroup Properties True center True normal False True False 5 True False end Ok False True True True False False 0 Cancel False True True True False False 1 False True end 0 True False 6 4 5 10 True False 0 Name: GTK_FILL True True False False True True 1 4 True False 0 True False 5 5 5 5 True False 5 True False 1 Start: False True 0 True True False False True True GroupEditor_CircStartIndentAdj True True 1 True False 1 End: False True 2 True True False False True True GroupEditor_CircEndIndentAdj True True 3 True False Circular ending indentation True 4 5 6 True False 0 True False 5 5 5 5 True False 5 True False 1 Left: False True 0 True True False False True True GroupEditor_LeftMarginAdj True True 1 True False 1 Right: False True 2 True True False False True True GroupEditor_RightMarginAdj True True 3 True False Horizontal margin True 4 4 5 True False 1 Start: 3 4 GTK_FILL True True False False True True GroupEditor_StartAdj 1 2 3 4 True False 1 End: 2 3 3 4 GTK_FILL True True False False True True GroupEditor_EndAdj 3 4 3 4 True False 1 Desc: 1 2 GTK_FILL True True False False True True 1 4 1 2 True False 5 True False 0 Track Distance: False False 0 True True False False True True GroupEditor_TrackDistAdj True True 1 4 2 3 False True 1 GroupEditor_OkBut GroupEditor_CancelBut -1000000000 1000000000 1 10 1000 1 10 1000 1 10 -1000000000 1000000000 1 10 100 1 10 Gdraw2-v0.0.3/data/curve.png000444001750001750 46012001671021 15655 0ustar00yangxiyangxi000000000000PNG  IHDR@ -sBITO pHYsttfxIDATX Eu>-KNe<ڔrk1QC9@Yy%\%LeYk[7k%_p]ɍQdKXrF˗d٢{dO3mJV:jf(*Yf @ \t\ϸt/ (I 0q'`[ch+i!~ xe9'.6zC,^IENDB`Gdraw2-v0.0.3/data/Gdraw2UI.glade000444001750001750 14250412001671021 16473 0ustar00yangxiyangxi000000000000 Add element Element gtk-add Add group Group gtk-add Add track Track gtk-add Close Close Close current file gtk-close Config page Configure page gtk-page-setup Copy Copy Copy selected object gtk-copy True Cut Cut Cut selected object gtk-cut True Delete object Delete Remove selected object gtk-delete Edit selected object Edit Configure selected object gtk-edit Export picture Export Create an image Force refresh Force refresh gtk-refresh Import blast result Import sequence features Import Import features from file like Genbank, EMBL, GFF Exit gtk-quit gtk-go-down gtk-go-up New New Create a new drawing gtk-new Open Open file gtk-open Redo Redo gtk-redo edit-redo Save as Save as gtk-save-as Save Save Save file gtk-save Undo Undo gtk-undo edit-undo True False AddGroupAction True False True True AddTrackAction True False True True AddElementAction True False True True False Gdraw2 center 800 600 True False True False False True False _File True True False NewFileAction True False True True OpenFileAction True False True True SaveFileAction True False True True SaveAsAction True False True True CloseFileAction True False True True True False False True False Import True True False ImportSeqAction True False True True ImportBlastAction True False True True ExportFileAction True False True True True False MainExitAction True False True True False True False _Edit True True False UndoAction True False RedoAction True False True False CutAction True False True True CopyAction True False True True PasteAction True False True True True False Add False True False False True False AddGroupAction True False True True AddTrackAction True False True True AddElementAction True False True True DeleteObjAction True False True True EditObjAction True False True True False True False ForceRefreshAction True False True True False True False _Help True True False gtk-about False True False True True False True 0 True False NewFileAction True False New True False True OpenFileAction True False Open True False True SaveFileAction True False Save True False True CloseFileAction True False toolbutton1 True False True True False False True UndoAction True False Undo True False True RedoAction True False Redo True False True True False False True CutAction True False Cut True False True CopyAction True False Copy True False True PasteAction True False Paste True False True True False False True ConfigPageAction True False Page Preference True False True False True False False ForceRefreshAction True False toolbutton1 True False True False True 1 True True True True True 2 False 5 center normal False True False 2 True False end gtk-yes False True True True True False False 0 gtk-no False True True True True False False 1 gtk-cancel False True True True True False False 2 False True end 0 True False False True 1 button1 button2 button3 True False True False True False icons MoveUpAction True False _Up True gtk-go-up False True MoveDownAction True False _Down True gtk-go-down False True False True False True gtk-add False True DeleteObjAction True False Delete True gtk-delete False True EditObjAction True False Edit True gtk-edit False True False True 0 True True 150 True 100 True True 50 True True PageTreeModel False 0 True Name True True Location True True Stroke color True Fill color False True 100 True True True False queue True True False True True True True 1 True False dbg False True True True False False 0 dbg_clip False True True True False False 1 False False 2 True True 0 Paste Paste Paste object gtk-paste True Gdraw2-v0.0.3/data/mapping.png000444001750001750 40112001671021 16157 0ustar00yangxiyangxi000000000000PNG  IHDR@ - pHYsttfxtIME5.IDATX Dq6Qdn`g.6Ƿyy9"ՖN{/=Ơhl`-"6&"6 m0w ͍u ( ZYhP  10000000000 100 1 10 False 5 dialog True False 2 True False end gtk-ok False True True True True False False 0 gtk-cancel False True True True True False False 1 False True end 0 True False 0 True False 5 5 5 5 True False 2 2 5 5 By e-value False True True False True GTK_FILL By bit score False True True False True 1 2 GTK_FILL True True False False True True BlastImporter_BitScoreAdj 1 2 1 2 True True 1e-10 False False True True 1 2 True False Filtrations True True True 1 True False 0 True False 5 5 5 5 True False One track for each hit False True True False True True True True 0 Stack HSPs False True True False True True BlastImporter_TrackLayout True True 1 True False Content layout True True True 2 button1 button2 Gdraw2-v0.0.3/data/EleEditor.glade000444001750001750 14352112001671021 16763 0ustar00yangxiyangxi000000000000 -10000000 10000000 0.050000000000000003 0.10000000000000001 True False 0 True False 5 5 5 5 True False 2 4 5 5 True False Fill color 2: False True True True The color for data lower than horizontal center True #ffff0000ffff 1 2 True False Horizontal center: 2 3 True True False False True True CurveComp_HCenterAdj 2 3 4 True False 1 Data: 1 2 True True comma-separated False False True True 1 4 1 2 True False DataCurve specific True False 5 True center True normal False True False 2 True False end gtk-ok False True True True True False False 0 gtk-cancel False True True True True False False 1 False True end 0 True False 5 True False 4 2 5 5 True False Description: 1 2 True True False False True True 1 2 1 2 True False Strand: 3 4 True True False False True True 1 2 Name: False True True False 1 True True True False + False True True False True True True True 0 - False True True False True EleStrand_FwdRadio True True 1 None False True True False True EleStrand_FwdRadio True True 2 1 2 3 4 True False 0 True False 5 5 5 5 True True comma-separated False False True True True False comma-separated Location True 2 2 3 True True 0 True False 5 True False Stroke: True True 0 False True True True True Pick Stroke Color #000000000000 True True 1 True False Fill: True True 2 False True True True True Pick Fill Color #00007f7f7f7f True True 3 True False Text: True True 4 False True True True True #000000000000 True True 5 True True 1 True False 0 True False 5 5 5 True False Left False True True False True True True True 0 Center False True True False True True EleAnchor_LeftRadio True True 1 Right False True True False True True EleAnchor_LeftRadio True True 2 True False Element Anchor True True True 2 True False 0 True False 5 5 5 True False Left False True True False True True True True 0 Center False True True False True True NameAnchor_LeftRadio True True 1 Right False True True False True True NameAnchor_LeftRadio True True 2 True False Name Anchor True True True 3 True False 0 True False 5 5 5 True False Top False True True False True True True True 0 Default False True True False True True EleLayer_TopRadio True True 1 Bottom False True True False True True EleLayer_TopRadio True True 2 True False Layer True True True 4 False True 1 EleEditor_OkBut EleEditor_CancelBut -1000000000 1000000000 1 10 True False 0 True False 5 5 5 5 True False 2 4 5 5 True False 1 End: 2 3 1 2 True True False False True True MappingComp_ExtEndAdj 3 4 1 2 True False 1 Ext. group index: True True False False True True MappingComp_ExtGroupAdj 1 2 True True False False True True MappingComp_ExtTrackAdj 1 2 1 2 True False 1 Ext. track index: 1 2 True False 1 Start: 2 3 True True False False True True MappingComp_ExtStartAdj 3 4 True False Location on external track True 65535 1 10 -1000000000 1000000000 1 10 100 1 10 True False 4 2 5 5 True False 1 Tick size: True False 1 Grid length: 1 2 Tick at integral location False True True False True 2 2 3 True True False False True True RulerComp_TickSizeAdj 1 2 True True False False True True RulerComp_GridLengthAdj 1 2 1 2 Abbreviate tick text False True True False True 2 3 4 100000 1 10 100 1 10 Gdraw2-v0.0.3/data/FileDialogs.glade000444001750001750 620412001671021 17225 0ustar00yangxiyangxi000000000000 False 5 Save task True center True dialog False save True True False 2 True False end gtk-cancel False True True True True False False 0 gtk-save False True True True True False False 1 False True end 0 button1 button2 Gdraw2-v0.0.3/data/EleTypeWizard.glade000444001750001750 2720112001671021 17613 0ustar00yangxiyangxi000000000000 False 5 False True center normal False True False 2 True False end gtk-cancel False True True True True False False 0 gtk-media-next False True True True True False False 1 False True end 0 True False 6 2 5 5 Ruler False True True False True EleType_BlockRadio 1 2 5 6 Block False True True False True True 1 2 Tagset False True True False True True EleType_BlockRadio 1 2 1 2 Pair False True True False True EleType_BlockRadio 1 2 2 3 Location mapping False True True False True True EleType_BlockRadio 1 2 3 4 Data curve False True True False True True EleType_BlockRadio 1 2 4 5 True False block.png True False tagset.png 1 2 True False gtk-missing-image 2 3 True False mapping.png 3 4 True False curve.png 4 5 True False ruler.png 5 6 False True 1 button5 button4 Gdraw2-v0.0.3/data/PageEditor.glade000444001750001750 7521612001671021 17117 0ustar00yangxiyangxi000000000000 False 5 Page properties True center True normal False True False 2 True False end Ok False True True True False False 0 Cancel False True True True False False 1 False True end 0 True False 0 True False 5 5 5 True False 5 True False 5 True False 1 Width: False True 0 True True False False True True PageEditor_WidthAdj 1 True True True 1 True False 1 Height: False True 2 True True False False True True PageEditor_HeightAdj True True True 3 True True 0 True False 5 True False Group distance: False True 0 True True False False True True PageEditor_GroupDistAdj True False True 1 True True 1 True False Page properties True False True 1 True False 0 True False 5 5 5 True False True False 0 none True False 12 True False 5 True False Top margin: True True 0 True True False False True True PageEditor_TopMarginAdj True True True 1 Linear False True True False True True True True 0 True False 0 none True False 12 True False 5 True False Init radius: True True 0 True True False False True True PageEditor_InitRadiusAdj True True True 1 Circular False True True False True True PageEditor_LinearRbut True True 1 True False Topology True False True 2 True False 0 True False 5 5 5 True False 2 4 5 5 True False Title font: True True False False True True 1 2 True False Size: 2 3 True True False False True True PageEditor_TitleSizeAdj True 3 4 True False Text font: 1 2 True True False False True True 1 2 1 2 True False Size: 2 3 1 2 True True False False True True PageEditor_TextSizeAdj True 3 4 1 2 True False Font settings True False True 3 PageEditor_OkBut PageEditor_CancelBut 65535 1 10 65535 1 10 65535 1 10 65535 1 10 65535 1 10 65535 1 10 65535 1 10 Gdraw2-v0.0.3/.settings000755001750001750 012001671021 14713 5ustar00yangxiyangxi000000000000Gdraw2-v0.0.3/.settings/org.eclipse.ltk.core.refactoring.prefs000555001750001750 20612001671021 24326 0ustar00yangxiyangxi000000000000#Tue Jun 22 09:09:59 CST 2010 eclipse.preferences.version=1 org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false