src/gui/widgets/object_list/object_text.cpp

Go to the documentation of this file.
00001 /*  $Id: object_text.cpp 20473 2009-12-02 15:20:11Z ucko $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors: Yury Voronov
00027  *
00028  * File Description:
00029  *
00030  */
00031 
00032 #include <ncbi_pch.hpp>
00033 
00034 #include <gui/widgets/object_list/object_text.hpp>
00035 
00036 #include <gui/widgets/text_widget/plain_text_item.hpp>
00037 #include <gui/widgets/text_widget/composite_text_item.hpp>
00038 #include <gui/widgets/text_widget/selection_helper.hpp>
00039 #include <gui/widgets/wx/simple_clipboard.hpp>
00040 
00041 #include <gui/objutils/label.hpp>
00042 
00043 #include <objects/seqalign/Seq_align.hpp>
00044 #include <objects/seqfeat/Seq_feat.hpp>
00045 #include <objects/seqloc/Seq_loc.hpp>
00046 #include <objects/general/Object_id.hpp>
00047 #include <objects/general/User_object.hpp>
00048 #include <objects/general/User_field.hpp>
00049 
00050 #include <connect/ncbi_conn_stream.hpp>
00051 
00052 #include <objects/seqalign/Seq_align_set.hpp>
00053 #include <objects/seqalign/Dense_seg.hpp>
00054 #include <objects/seqalign/Std_seg.hpp>
00055 
00056 #include <serial/iterator.hpp>
00057 #include <objmgr/util/sequence.hpp>
00058 #include <objmgr/util/feature.hpp>
00059 #include <objtools/format/flat_file_config.hpp>
00060 #include <objtools/format/flat_file_generator.hpp>
00061 
00062 #include <wx/sstream.h>
00063 #include <wx/txtstrm.h>
00064 
00065 
00066 BEGIN_NCBI_SCOPE
00067 USING_SCOPE(objects);
00068 
00069 class CSelectableMainGroup : public CCompositeTextItem
00070 {
00071     DECLARE_EVENT_TABLE()
00072 public:
00073 
00074     virtual void FillContextMenu( wxMenu& menu ) const;
00075 
00076     void OnMenuCommand( wxCommandEvent& event );
00077     void OnMenuCommandUpdateUI( wxUpdateUIEvent& event );
00078 };
00079 
00080 BEGIN_EVENT_TABLE( CSelectableMainGroup, CCompositeTextItem )
00081     EVT_MENU( wxID_COPY, CSelectableMainGroup::OnMenuCommand )
00082     EVT_UPDATE_UI( wxID_COPY, CSelectableMainGroup::OnMenuCommandUpdateUI )
00083 END_EVENT_TABLE()
00084 
00085 
00086 class CSelectableObjectItem : public CCompositeTextItem
00087 {
00088     DECLARE_EVENT_TABLE()
00089 
00090 public:
00091     CSelectableObjectItem( const CObject* object ) : m_Object( object ) {
00092     }
00093 
00094     virtual const CConstRef<CObject> GetAssosiatedObject() const { return m_Object; }
00095     virtual int GetTextOffset( CTextPanelContext* context ) const;
00096 
00097     virtual void FillContextMenu( wxMenu& menu ) const;
00098 
00099 protected:
00100     void OnCopy( wxCommandEvent& event );
00101     void OnCopyUpdateUI( wxUpdateUIEvent& event );
00102 
00103 private:
00104     CConstRef<CObject> m_Object;
00105 };
00106 
00107 BEGIN_EVENT_TABLE( CSelectableObjectItem, CCompositeTextItem )
00108     EVT_MENU( wxID_COPY, CSelectableObjectItem::OnCopy )
00109     EVT_UPDATE_UI( wxID_COPY, CSelectableObjectItem::OnCopyUpdateUI )
00110 
00111 END_EVENT_TABLE()
00112 
00113 void CSelectableMainGroup::FillContextMenu( wxMenu& menu ) const
00114 {
00115     menu.Append( wxID_COPY, _T("&Copy") );
00116 }
00117 
00118 void CSelectableMainGroup::OnMenuCommand( wxCommandEvent& event )
00119 {
00120     if( event.GetId() == wxID_COPY ){
00121         CTextItemPanel* panel = static_cast<CTextItemPanel*>( event.GetEventObject() );
00122         CTextPanelContext* context = panel->GetContext();
00123         if( panel->IsTextSelected() ){
00124             CTextBlock block = panel->GetTextSelection().Normalized();
00125 
00126             wxStringOutputStream stream;
00127             wxTextOutputStream os( stream );
00128             GetText( os, block, context );
00129 
00130             CSimpleClipboard::Instance().Set( stream.GetString() );
00131         }
00132     }
00133 }
00134 
00135 void CSelectableMainGroup::OnMenuCommandUpdateUI( wxUpdateUIEvent& event )
00136 {
00137     if( event.GetId() == wxID_COPY ){
00138         CTextItemPanel* panel = (CTextItemPanel*)event.GetEventObject();
00139         event.Enable( panel->IsTextSelected() );
00140     }
00141 }
00142 
00143 
00144 int CSelectableObjectItem::GetTextOffset( CTextPanelContext* context ) const
00145 {
00146     return
00147         CCompositeTextItem::GetTextOffset( context )
00148         + context->GetLeftMargin()
00149     ;
00150 }
00151 
00152 void CSelectableObjectItem::FillContextMenu( wxMenu& menu ) const
00153 {
00154     menu.Append( wxID_COPY, _T("&Copy") );
00155 }
00156 
00157 void CSelectableObjectItem::OnCopy( wxCommandEvent& event )
00158 {
00159     CTextItemPanel* panel = static_cast<CTextItemPanel*>( event.GetEventObject() );
00160     CTextPanelContext* context = panel->GetContext();
00161     if( panel->IsTextSelected() ){
00162         CTextBlock block = panel->GetTextSelection().Normalized();
00163 
00164         wxStringOutputStream stream;
00165         wxTextOutputStream os( stream );
00166         GetText( os, block, context );
00167 
00168         CSimpleClipboard::Instance().Set( stream.GetString() );
00169     }
00170 }
00171 
00172 void CSelectableObjectItem::OnCopyUpdateUI( wxUpdateUIEvent& event )
00173 {
00174     CTextItemPanel* panel = (CTextItemPanel*)event.GetEventObject();
00175     event.Enable( panel->IsTextSelected() );
00176 }
00177 
00178 ///////////////////////////////////////////////////////////////////////////////
00179 /// CObjectTextWidget
00180 CObjectTextWidget::CObjectTextWidget()
00181     : CTextItemPanel()
00182     , m_Brief( false )
00183     , m_Scope( NULL )
00184 {
00185 }
00186 
00187 CObjectTextWidget::CObjectTextWidget(
00188     wxWindow* parent,
00189     wxWindowID id,
00190     const wxPoint& pos,
00191     const wxSize& size
00192 )
00193     : CTextItemPanel( parent, id, pos, size )
00194     , m_Brief( false )
00195     , m_Scope( NULL )
00196 {
00197     SetBackgroundColour( wxColor(_T("white")) );
00198 
00199     //x_UpdatePanelFont();
00200     int pointSize = 8;
00201     wxFontFamily fontFamily = wxFONTFAMILY_MODERN;
00202     SetFont(wxFont(pointSize, fontFamily, wxNORMAL, wxNORMAL));
00203 }
00204 
00205 void CObjectTextWidget::Init( TConstScopedObjects& objects, bool brief )
00206 {
00207     m_Objects = objects;
00208     m_Brief = brief;
00209 
00210     if( objects.size() > 0 ){
00211        m_Scope = objects[0].scope;
00212     }
00213 
00214     vector<ITextItem*> items;
00215 
00216     x_GenerateTextItemsFromObjects( items );
00217 
00218     SetData( new CSelectableMainGroup(), new CTextPanelContext(2) );
00219     AddItems( items );
00220 }
00221 
00222 void CObjectTextWidget::GetSelection( TConstScopedObjects& objects )
00223 {
00224     vector< CConstRef<CObject> > objs;
00225 
00226     GetContext()->GetSelectedObjects( objs );
00227 
00228     for( int i = 0; i < (int)objs.size(); ++i ){
00229         const CObject* obj = objs[i];
00230         objects.push_back( SConstScopedObject(*obj, *m_Scope) );
00231     }
00232 }
00233 
00234 
00235 //static const char* kObjectPrefix = "\n-----\n\n";
00236 
00237 void CObjectTextWidget::x_GenerateTextItemsFromObjects( vector<ITextItem*>& items )
00238 {
00239     int obj_num = m_Objects.size();
00240 
00241     for( int i = 0; i < obj_num; i++ ){
00242         if( i > 0 ){
00243             CPlainTextItem* item = new CPlainTextItem();
00244             item->AddLine( " " );
00245             items.push_back( item );
00246         }
00247 
00248         SConstScopedObject& obj = m_Objects[i];
00249 
00250         x_GetItems_Object( *obj.object, obj.scope, items );
00251     }
00252 }
00253 
00254 static void s_GetItems_PairwiseAlign(
00255     const CSeq_align& align, CScope* scope, vector<ITextItem*>& items
00256 ){
00257     string text;
00258 
00259     switch( align.GetSegs().Which() ){
00260     case CSeq_align::TSegs::e_Denseg:
00261         break;
00262 
00263     case CSeq_align::TSegs::e_Std:
00264         break;
00265 
00266     case CSeq_align::TSegs::e_Disc:
00267         {{
00268             /// each segment represents an exon, so we can format a text dump
00269             /// with this information
00270             ITERATE( CSeq_align::TSegs::TDisc::Tdata, iter, align.GetSegs().GetDisc().Get() ){
00271             }
00272         }}
00273         break;
00274 
00275     default:
00276         CLabel::GetLabel( align, &text, CLabel::eDescription, scope );
00277         break;
00278     }
00279 
00280     CPlainTextItem* item = new CPlainTextItem();
00281     item->AddLine( text );
00282     items.push_back( item );
00283 }
00284 
00285 
00286 static void s_GetItems_GenericAlign(
00287     const CSeq_align& align, CScope* scope, vector<ITextItem*>& items
00288 ){
00289     string text;
00290     CLabel::GetLabel( align, &text, CLabel::eDescription, scope );
00291 
00292     CPlainTextItem* item = new CPlainTextItem();
00293     item->AddLine( text );
00294     items.push_back( item );
00295 }
00296 
00297 
00298 static void s_GetItems_Align(
00299     const CSeq_align& align, CScope* scope, vector<ITextItem*>& items
00300 ){
00301     string preamble;
00302     string ids;
00303 
00304     set<CSeq_id_Handle> id_set;
00305     CTypeConstIterator<CSeq_id> id_iter( align );
00306     for( ; id_iter; ++id_iter ){
00307         CSeq_id_Handle idh = CSeq_id_Handle::GetHandle( *id_iter );
00308         if( id_set.insert(idh).second ){
00309             if( !ids.empty() ){
00310                 ids += " x ";
00311             }
00312 
00313             if( scope ){
00314                 idh = sequence::GetId( idh, *scope, sequence::eGetId_Best );
00315             }
00316             idh.GetSeqId()->GetLabel( &ids );
00317         }
00318     }
00319 
00320     string text;
00321 
00322     text = "Alignment: " + ids;
00323     CPlainTextItem* item = new CPlainTextItem();
00324     item->AddLine( text );
00325     items.push_back( item );
00326 
00327     if( id_set.size() == 2 ){
00328         s_GetItems_PairwiseAlign( align, scope, items );
00329     } else {
00330         s_GetItems_GenericAlign(align, scope, items );
00331     }
00332 }
00333 
00334 
00335 static void s_AccListToItem(const CUser_field::TData::TStrs& item_data,
00336                             const string& title,
00337                             CPlainTextItem* item)
00338 {
00339     string s(title);
00340     if ( !s.empty() ) {
00341         s += ": ";
00342     }
00343 
00344     list<string> refseq;
00345     list<string> non_refseq;
00346     ITERATE (CUser_field::TData::TStrs, it, item_data) {
00347         CSeq_id::EAccessionInfo info = CSeq_id::IdentifyAccession(*it);
00348         if ((info & CSeq_id::eAcc_type_mask) == CSeq_id::e_Other) {
00349             refseq.push_back(*it);
00350         } else {
00351             non_refseq.push_back(*it);
00352         }
00353     }
00354 
00355     string accs;
00356     if (refseq.size()) {
00357         accs += NStr::Join(refseq, ", ");
00358     }
00359 
00360     if (non_refseq.size()) {
00361         if ( !accs.empty() ) {
00362             accs += ", ";
00363         }
00364         accs += NStr::Join(non_refseq, ", ");
00365     }
00366 
00367     if ( !accs.empty() ) {
00368         s += accs;
00369     } else {
00370         s += "<unknown>";
00371     }
00372 
00373     list<string> lines;
00374     NStr::Wrap(s, 78, lines);
00375     if ( !lines.empty() ) {
00376         ITERATE (list<string>, iter, lines) {
00377             if (iter != lines.begin()) {
00378                 item->AddLine("    " + *iter);
00379             } else {
00380                 item->AddLine(*iter);
00381             }
00382         }
00383     }
00384 }
00385 
00386 static void s_GetItems_Feat_Evidence(
00387     const CSeq_feat& feat, CScope* scope, vector<ITextItem*>& items)
00388 {
00389     if ( !feat.IsSetExt()  &&  !feat.IsSetExts()) {
00390         return;
00391     }
00392 
00393     list< CConstRef<CUser_object> > objs;
00394     if (feat.IsSetExt()) {
00395         CConstRef<CUser_object> o(&feat.GetExt());
00396         if (o->IsSetType()  &&  o->GetType().IsStr()  && o->GetType().GetStr() == "CombinedFeatureUserObjects") {
00397             ITERATE (CUser_object::TData, it, o->GetData()) {
00398                 const CUser_field& field = **it;
00399                 CConstRef<CUser_object> sub_o(&field.GetData().GetObject());
00400                 objs.push_back(sub_o);
00401             }
00402         } else {
00403             objs.push_back(o);
00404         }
00405     }
00406     if (feat.IsSetExts()) {
00407         copy(feat.GetExts().begin(), feat.GetExts().end(), back_inserter(objs));
00408     }
00409 
00410     CPlainTextItem* item = new CPlainTextItem();
00411 
00412     ITERATE (list< CConstRef<CUser_object> >, obj_it, objs) {
00413         const CUser_object& obj = **obj_it;
00414         if ( !obj.IsSetType()  ||
00415              !obj.GetType().IsStr()  ||
00416              obj.GetType().GetStr() != "ModelEvidence") {
00417             continue;
00418         }
00419 
00420         string s;
00421         CConstRef<CUser_field> f;
00422 
00423         item->AddLine("");
00424 
00425         ///
00426         /// generation method
00427         string method;
00428         s = "Model Generation Method: ";
00429         f = obj.GetFieldRef("Method");
00430         if (f) {
00431             method = f->GetData().GetStr();
00432             s += method;
00433         } else {
00434             s += "<unknown>";
00435         }
00436         item->AddLine(s);
00437 
00438         ///
00439         /// list of support
00440         if (method == "Chainer"  ||  method == "Gnomon") {
00441 
00442             ///
00443             /// scan for multiple 'Core' entries
00444             f = obj.GetFieldRef("Support");
00445             if (f) {
00446                 string core;
00447                 ITERATE (CUser_field::TData::TFields, it, f->GetData().GetFields()) {
00448                     const CUser_field& this_f = **it;
00449                     if (this_f.GetLabel().GetStr() == "Core") {
00450                         if ( !core.empty() ) {
00451                             core += ", ";
00452                         }
00453                         core += this_f.GetData().GetStr();
00454                     }
00455                 }
00456                 if ( !core.empty() ) {
00457                     s = "Model Based On: ";
00458                     s += core;
00459                     item->AddLine(s);
00460                 }
00461             }
00462 
00463             ///
00464             /// supporting proteins
00465             f = obj.GetFieldRef("Support.Proteins");
00466             if (f) {
00467                 s_AccListToItem(f->GetData().GetStrs(),
00468                                 "Source Proteins", item);
00469             }
00470 
00471             ///
00472             /// supporting proteins
00473             f = obj.GetFieldRef("Support.mRNAs");
00474             if (f) {
00475                 s_AccListToItem(f->GetData().GetStrs(),
00476                                 "Source mRNAs", item);
00477             }
00478         }
00479     }
00480 
00481     items.push_back( item );
00482 }
00483 
00484 
00485 
00486 static void s_GetItems_Feat(
00487     const CSeq_feat& feat, CScope* scope, vector<ITextItem*>& items
00488 ){
00489     string text;
00490     CPlainTextItem* item;
00491 
00492     try {
00493         /// start with the description text
00494         CLabel::GetLabel( feat, &text, CLabel::eDescription, scope );
00495         item = new CPlainTextItem();
00496         item->AddLine( text );
00497         items.push_back( item );
00498 
00499         /// add information about the feature's location
00500         TSeqRange range = feat.GetLocation().GetTotalRange();
00501         text = "Total Range:  ";
00502         switch( sequence::GetStrand(feat.GetLocation(), scope) ){
00503         case eNa_strand_plus:
00504             text += "(+) ";
00505             break;
00506         case eNa_strand_minus:
00507             text += "(-) ";
00508             break;
00509 
00510         default:
00511             break;
00512         }
00513 
00514         text += NStr::IntToString(range.GetFrom() + 1, NStr::fWithCommas);
00515         text += " - ";
00516         text += NStr::IntToString(range.GetTo() + 1, NStr::fWithCommas);
00517 
00518         item = new CPlainTextItem();
00519         item->AddLine( text );
00520         items.push_back( item );
00521 
00522         text = "Total Length:  ";
00523         text += NStr::IntToString(range.GetLength(), NStr::fWithCommas);
00524 
00525         item = new CPlainTextItem();
00526         item->AddLine( text );
00527         items.push_back( item );
00528 
00529         text = "Processed Length:  ";
00530         text += NStr::IntToString(sequence::GetLength(feat.GetLocation(), scope),
00531                                   NStr::fWithCommas);
00532 
00533         item = new CPlainTextItem();
00534         item->AddLine( text );
00535         items.push_back( item );
00536 
00537         if (feat.IsSetProduct()  &&  scope) {
00538             try {
00539                 string prod_len_str;
00540                 CBioseq_Handle h = scope->GetBioseqHandle(feat.GetProduct());
00541                 if (h) {
00542                     text = "Product Length: ";
00543                     text += NStr::IntToString(h.GetBioseqLength(),
00544                                               NStr::fWithCommas);
00545 
00546                     item = new CPlainTextItem();
00547                     item->AddLine( text );
00548                     items.push_back( item );
00549                 }
00550             }
00551             catch (CException&) {
00552             }
00553         }
00554 
00555         item = new CPlainTextItem();
00556         item->AddLine( " " );
00557         items.push_back( item );
00558 
00559         /// next, include the flat file text for this feature
00560         CFlatFileConfig cfg;
00561         cfg.SetNeverTranslateCDS();
00562 
00563         if( scope ){
00564             string s = CFlatFileGenerator::GetSeqFeatText(feat, *scope, cfg);
00565             string::size_type pos = s.find_first_not_of(" \n\r\t");
00566             if( pos != string::npos ){
00567                 s.erase(0, pos);
00568             }
00569 
00570             item = new CPlainTextItem();
00571 
00572             string::size_type lpos = -1;
00573             do {
00574                 pos = lpos +1;
00575                 lpos = s.find_first_of("\n\r", pos );
00576 
00577                 if( lpos == string::npos ){
00578                     text = s.substr( pos );
00579                 } else {
00580                     text = s.substr( pos, lpos - pos );
00581                 }
00582                 item->AddLine( text );
00583 
00584             } while( lpos != string::npos );
00585 
00586             items.push_back( item );
00587         }
00588 
00589         /// lastly, add items relating to model evidence
00590         s_GetItems_Feat_Evidence(feat, scope, items);
00591     }
00592     catch (CException&) {
00593     }
00594 }
00595 
00596 static void s_GetItems_Loc(
00597     const CSeq_loc& loc, CScope* scope, vector<ITextItem*>& items
00598 ){
00599     string text;
00600     CLabel::GetLabel( loc, &text, CLabel::eDescription, scope );
00601 
00602     CPlainTextItem* item = new CPlainTextItem();
00603     item->AddLine( text );
00604     items.push_back( item );
00605 }
00606 
00607 void CObjectTextWidget::x_GetItems_Object(
00608     const CObject& object, CScope* scope, vector<ITextItem*>& items
00609 ){
00610     if( m_Brief ){
00611         string text;
00612         CLabel::GetLabel(
00613             object, &text, CLabel::eDescriptionBrief, scope
00614             );
00615 
00616         CPlainTextItem* item = new CPlainTextItem();
00617         item->AddLine( text );
00618         items.push_back( item );
00619     } else {
00620         const CSerialObject* cso = dynamic_cast<const CSerialObject*>(&object);
00621 
00622         if( cso ){
00623 
00624             CSelectableObjectItem* comp_item = new CSelectableObjectItem( cso );
00625             vector<ITextItem*> comp_items;
00626 
00627             if( cso->GetThisTypeInfo() == CSeq_align::GetTypeInfo() ){
00628                 s_GetItems_Align((const CSeq_align&)*cso, scope, comp_items);
00629 
00630             } else if (cso->GetThisTypeInfo() == CSeq_feat::GetTypeInfo()) {
00631                 s_GetItems_Feat((const CSeq_feat&)*cso, scope, comp_items);
00632 
00633             } else if (cso->GetThisTypeInfo() == CSeq_loc::GetTypeInfo()) {
00634                 s_GetItems_Loc((const CSeq_loc&)*cso, scope, comp_items);
00635             } else {
00636                 string text;
00637                 CLabel::GetLabel( object, &text, CLabel::eDescription, scope );
00638 
00639                 CPlainTextItem* item = new CPlainTextItem();
00640                 item->AddLine( text );
00641                 comp_items.push_back( item );
00642             }
00643 
00644             NON_CONST_ITERATE( vector<ITextItem*>, item_iter, comp_items ){
00645                 comp_item->AddItem( *item_iter );
00646             }
00647 
00648             items.push_back( comp_item );
00649         }
00650     }
00651 }
00652 
00653 END_NCBI_SCOPE
00654 
00655 

Generated on Wed Dec 9 04:38:25 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:18:04 2009 by modify_doxy.py rev. 173732