alnmulti_model.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:19k
- /*
- * ===========================================================================
- * PRODUCTION $Log: alnmulti_model.cpp,v $
- * PRODUCTION Revision 1000.1 2004/06/01 21:07:07 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: alnmulti_model.cpp,v 1000.1 2004/06/01 21:07:07 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Andrey Yazhuk
- *
- * File Description:
- *
- */
- #include <ncbi_pch.hpp>
- #include <gui/widgets/aln_multiple/alnmulti_model.hpp>
- #include <gui/widgets/aln_multiple/alnmulti_ds.hpp>
- BEGIN_NCBI_SCOPE
- USING_SCOPE(objects);
- ////////////////////////////////////////////////////////////////////////////////
- /// class CAlnMultiModel
- CAlnMultiModel::CAlnMultiModel()
- : m_pStyleCatalog(NULL),
- m_pDataSource(NULL),
- m_pMasterRow(NULL),
- m_bAutoSort(false)
- {
- double max_sym_w = 2 * m_Style.m_SeqFont.GetMetric(CGlBitmapFont::eMetric_MaxCharWidth);
- // setup Port
- m_Port.SetAdjustmentPolicy(CGlPane::fAdjustAll, CGlPane::fShiftToLimits);
- m_Port.SetMinScaleX(1 / max_sym_w);
- m_Port.SetOriginType(CGlPane::eOriginLeft, CGlPane::eOriginTop);
-
- SetPortLimits();
- }
- CAlnMultiModel::~CAlnMultiModel()
- {
- ClearRows();
- }
- ////////////////////////////////////////////////////////////////////////////////
- // IAlnMultiPaneParent implementation
- void CAlnMultiModel::SetStyleCatalog(const CRowStyleCatalog* catalog)
- {
- m_pStyleCatalog = catalog;
- }
- const CWidgetDisplayStyle* CAlnMultiModel::GetDisplayStyle() const
- {
- return &m_Style;
- }
- int CAlnMultiModel::GetRowState(TNumrow row) const
- {
- return x_GetRecordByRow(row).m_State;
- }
- bool CAlnMultiModel::SRowRecord::PRecLineLess(const SRowRecord* rec1,
- const SRowRecord* rec2)
- {
- return rec1->m_Line < rec2->m_Line;
- }
- /// changes visibility state for given vector of rows to "b_visible"
- void CAlnMultiModel::SetVisible(const vector<TNumrow>& rows, bool b_visible,
- bool b_invert_others)
- {
- size_t n_rows = rows.size();
- if(n_rows || b_invert_others) {
- vector<TNumrow> v_items;
- TNumrow master_row = m_pDataSource->GetAnchor();
-
- if(b_invert_others) { // all rows in alignment are affected
- // by default set state for all rows to "! b_visible"
- vector<bool> new_visible(m_RowToRec.size(), ! b_visible);
-
- ITERATE(vector<TNumrow>, it, rows) {
- new_visible[*it] = b_visible;
- }
- vector<SRowRecord*> vis_recs;
- vis_recs.reserve(b_visible ? rows.size()
- : new_visible.size() - rows.size());
- for( TNumrow row = 0; row < (TNumrow) new_visible.size(); row++ ) { // for all rows
- if(row != master_row && new_visible[row]) {
- SRowRecord& rec = x_GetRecordByRow(row);
- vis_recs.push_back(&rec);
- }
- }
- // sort records by line number
- sort(vis_recs.begin(), vis_recs.end(), SRowRecord::PRecLineLess);
-
- // copy row numbers to v_items
- v_items.reserve(vis_recs.size());
- ITERATE(vector<SRowRecord*>, it, vis_recs) {
- IAlignRow* p_row = (*it)->m_pRow;
- v_items.push_back(p_row->GetRowNum());
- }
- TNumrowModelImpl::SetItems(v_items, false, true);
- }
- else { // only "rows" will be affected
- v_items.reserve(n_rows);
- vector<TLine> v_indices;
- v_indices.reserve(n_rows);
- ITERATE(vector<TNumrow>, it, rows) {
- TNumrow row = *it;
- SRowRecord& rec = x_GetRecordByRow(row);
- bool b_old_vis = rec.IsVisible();
- if(b_old_vis != b_visible && row != master_row) {
- // state needs to be changed
- TLine line = rec.m_Line;
- // clip line, it can be invalid
- line = min(line, (TLine) m_vVisibleRows.size());
- v_indices.push_back(line);
- if(b_visible) {
- v_items.push_back(row);
- }
- }
- }
- if(b_visible) {
- TNumrowModelImpl::InsertItems(v_items, v_indices, false);
- } else {
- TNumrowModelImpl::DeleteItems(v_indices, false);
- }
- }
- if(m_bAutoSort) {
- x_DoUpdateRowsOrder(); // applying sorting
- x_DoUpdateRowPositions();
- }
-
- SetPortLimits();
- }
- }
- CGlPane& CAlnMultiModel::GetAlignPort()
- {
- return m_Port;
- }
- const CGlPane& CAlnMultiModel::GetAlignPort() const
- {
- return m_Port;
- }
- CAlnMultiModel::TNumrow CAlnMultiModel::GetLinesCount()
- {
- return m_vVisibleRows.size();
- }
- int CAlnMultiModel::GetFocusedItemIndex() const
- {
- return SLM_GetFocusedItemIndex();
- }
- bool CAlnMultiModel::IsItemSelected(int index) const
- {
- return SLM_IsItemSelected(index);
- }
- IAlignRow* CAlnMultiModel::GetRowByLine(int i_line)
- {
- return x_GetRowByLine(i_line);
- }
- int CAlnMultiModel::GetLineByRowNum(TNumrow row) const
- {
- const CAlnMultiModel::SRowRecord& rec = x_GetRecordByRow(row);
- return rec.IsVisible() ? rec.m_Line : -1;
- }
- IAlignRow* CAlnMultiModel::GetMasterRow()
- {
- return m_pMasterRow;
- }
- int CAlnMultiModel::GetLineByModelY(int Y) const
- {
- const TModelRect& rcL = m_Port.GetModelLimitsRect();
- if(Y < rcL.Top() || Y > rcL.Bottom())
- return -1;
- else {
- vector<int>::const_iterator it = lower_bound(m_vVisibleRowPos.begin(), m_vVisibleRowPos.end(), Y);
- return it - m_vVisibleRowPos.begin() - 1;
- }
- }
- int CAlnMultiModel::GetLinePosY(int index) const
- {
- return m_vVisibleRowPos[index];
- }
- int CAlnMultiModel::GetLineHeight(TLine line) const
- {
- return x_GetRowByLine(line)->GetHeightPixels();
- }
-
- bool CAlnMultiModel::IsRendererFocused()
- {
- return true;
- }
- void CAlnMultiModel::ShowAll()
- {
- vector<TNumrow> nothing;
- SetVisible(nothing, false, true); // hide nothing and make other visible
- }
- void CAlnMultiModel::EnableAutoSorting(bool b_en)
- {
- m_bAutoSort = b_en;
- }
- void CAlnMultiModel::UpdateSortOrder(void)
- {
- m_bAutoSort = true;
-
- x_DoUpdateRowsOrder();
- x_DoUpdateRowPositions();
- }
- /// order can be changed only for visible rows, hidden will be ignored
- void CAlnMultiModel::SetRowOrder(const vector<TNumrow>& rows, int pos)
- {
- m_bAutoSort = false; // cancel auto sorting
- int n_vis = m_vVisibleRows.size();
- if(pos >= 0 && pos < n_vis) {
- vector<SRowRecord*> new_vis(n_vis, (SRowRecord*)NULL);
- // new container to replace m_vVisibleRows
- // move specified rows to new_order and replace them with NULL in m_vVisibleRows
- int i = 0, line = pos;
- for( ; i < (int) rows.size() && line < n_vis; i++ ) {
- TNumrow row = rows[i];
- SRowRecord* p_rec = &x_GetRecordByRow(row);
- if(p_rec->IsVisible()) {
- new_vis[line] = p_rec;
- m_vVisibleRows[p_rec->m_Line] = NULL; // remove from m_vVisibleRows
- line++;
- }
- }
- // move the rest of the rows (those that are not NULL) preserving existing order
- // move first "pos" elements and insert them before "pos" position
- i = 0; // current postion in m_vVisibleRow
- int ins_i = 0; // insertion position in new_vis
- while(ins_i < pos) {
- for( ; m_vVisibleRows[i] == NULL && i < n_vis; i++ ) { // skip
- }
- _ASSERT(i < n_vis);
- new_vis[ins_i++] = m_vVisibleRows[i++];
- }
- // copy the rest of rows to new_vis after "line"
- ins_i = line;
- while(ins_i < n_vis) {
- for( ; m_vVisibleRows[i] == NULL && i < n_vis; i++ ) { // skip
- }
- _ASSERT(i < n_vis);
- new_vis[ins_i++] = m_vVisibleRows[i++];
- }
-
- // assign new_vis to m_vVisibleRows
- m_vVisibleRows = new_vis;
- x_DoUpdateRowLines();
- x_DoUpdateRowPositions();
- }
- }
- void CAlnMultiModel::SetDataSource(IAlnMultiDataSource* p_ds)
- {
- m_pDataSource = p_ds;
- x_UpdateOnDataChanged(); // before it called Widget's version of function
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// Update handlers
- void CAlnMultiModel::ClearRows()
- {
- TNumrowModelImpl::DeleteAllItems();
- NON_CONST_ITERATE(TRowToRecMap, it, m_RowToRec) {
- delete (*it)->m_pRow;
- delete *it;
- }
- m_RowToRec.clear();
- m_pMasterRow = NULL;
- m_vVisibleRows.clear();
- m_vVisibleRowPos.clear();
- }
- /// Creates IAlignRow objects for each row in the data source.
- void CAlnMultiModel::CreateRows()
- {
- if(m_pDataSource) {
- _ASSERT(m_RowToRec.size() == 0 && m_pMasterRow == NULL);
- const int aln_rows_n = m_pDataSource->GetNumRows();
- int pane_rows_n = aln_rows_n; // rows shown in align pane (Master row is not counted)
-
- TNumrow MasterRow = -1;
- if(m_pDataSource->IsSetAnchor()) {
- MasterRow = m_pDataSource->GetAnchor();
- --pane_rows_n;
- }
-
- m_vVisibleRows.resize(pane_rows_n);
- m_vVisibleRowPos.resize(pane_rows_n);
-
- TLine i_line = 0;
- m_RowToRec.resize(aln_rows_n);
- for( TNumrow row = 0; row < aln_rows_n; row++ ) {
- // call a factory method to create a row instance
- IAlignRow* p_row = x_CreateRow(row);
-
- SRowRecord* p_rec = new SRowRecord(p_row, i_line);
- m_RowToRec[row] = p_rec;
-
- if(row == MasterRow) {
- m_pMasterRow = p_row;
- p_rec->SetState(IAlignRow::fItemHidden, true);
- } else {
- m_vVisibleRows[i_line] = p_rec;
- i_line++;
- }
- }
- if(m_bAutoSort) {
- x_DoUpdateRowsOrder(); // applying sorting
- }
-
- // updating CSelListModelImpl
- TNumrowModelImpl::TItemVector vItems(pane_rows_n);
- for( size_t i = 0; i < m_vVisibleRows.size(); i++ ) {
- vItems[i] = m_vVisibleRows[i]->m_pRow->GetRowNum();
- }
- TNumrowModelImpl::SetItems(vItems, false, false);
-
- x_DoUpdateRowPositions();
- }
- }
-
- bool CAlnMultiModel::x_SortRows()
- {
- return true; // nothing has been changed
- }
- void CAlnMultiModel::x_DoUpdateRowsOrder()
- {
- _ASSERT(m_bAutoSort); // msut be called only when auto sorting is enabled
- TIndex i_focused = SLM_GetFocusedItemIndex();
- const SRowRecord* p_rec = (i_focused >= 0) ? m_vVisibleRows[i_focused] : NULL;
- if(x_SortRows()) {
- x_DoUpdateRowLines();
- // restore focus
- int line = p_rec ? p_rec->m_Line : -1;
- SLM_FocusItem(line);
- }
- }
- void CAlnMultiModel::x_DoUpdateRowLines()
- {
- for(size_t i = 0; i < m_vVisibleRows.size(); i++ ) {
- SRowRecord& rec = *m_vVisibleRows[i];
- rec.m_Line = i;
- }
- }
- void CAlnMultiModel::UpdateOnRowHChanged(void)
- {
- x_DoUpdateRowPositions();
- SetPortLimits();
- }
- /// recalculates vertical positions of row objects based on their order,
- /// visibility and height
- void CAlnMultiModel::x_DoUpdateRowPositions(void)
- {
- int N = m_vVisibleRows.size();
- m_vVisibleRowPos.resize(N);
-
- for( int total_H = 0, i = 0; i < N; i++ ) {
- IAlignRow* pRow = x_GetRowByLine(i);
- m_vVisibleRowPos[i] = total_H;
- total_H += pRow->GetHeightPixels();
- }
- }
- void CAlnMultiModel::SetPortLimits()
- {
- if (m_pDataSource) {
- double Start = m_pDataSource->GetAlnStart();
- double Stop = m_pDataSource->GetAlnStop();
-
- double H = 0;
- int iLast = m_vVisibleRows.size() - 1;
- if(iLast > 0)
- H = GetLinePosY(iLast) + GetLineHeight(iLast);
- m_Port.SetModelLimitsRect(TModelRect(Start, H - 1, Stop + 1, 0));
- } else
- m_Port.SetModelLimitsRect(TModelRect(0, -1, 0, 0));
- }
- void CAlnMultiModel::SetMasterRow(TNumrow new_master_row)
- {
- //Anchor the row to make it "Master"
- m_pDataSource->SetAnchor(new_master_row);
-
- // rearrange Row objects and items
- IAlignRow* pNewMaster = NULL;
- if(new_master_row != -1) { // remove row from the Align pane
- SRowRecord& rec = x_GetRecordByRow(new_master_row);
- pNewMaster = rec.m_pRow;
-
- rec.SetState(IAlignRow::fItemHidden, true);
- vector<int> vDelItems;
- vDelItems.push_back(rec.m_Line);
- DeleteItems(vDelItems, false);
- }
- if(m_pMasterRow) { // insert current Master into Align pane
- TNumrow row = m_pMasterRow->GetRowNum();
- SRowRecord& rec = x_GetRecordByRow(row);
- TLine line = min(rec.m_Line, (TLine) m_vVisibleRows.size());
-
- rec.SetState(IAlignRow::fItemHidden, false);
- InsertItem(line, m_pMasterRow->GetRowNum(), false);
- }
-
- m_pMasterRow = pNewMaster;
-
- if(m_bAutoSort) {
- x_DoUpdateRowsOrder(); // applying sorting
- }
- x_DoUpdateRowPositions();
-
- SetPortLimits(); // set new limits
- }
- void CAlnMultiModel::x_UpdateOnDataChanged()
- {
- ClearRows();
- if (m_pDataSource) {
- CreateRows();
- SetPortLimits();
- }
- }
- IAlignRow* CAlnMultiModel::x_GetRowByLine(int index)
- {
- _ASSERT(index >= 0 && (size_t) index < m_vVisibleRows.size());
- SRowRecord* p_rec = m_vVisibleRows[index];
- return static_cast<IAlignRow*>(p_rec->m_pRow);
- }
- const IAlignRow* CAlnMultiModel::x_GetRowByLine(int index) const
- {
- _ASSERT(index >= 0 && (size_t) index < m_vVisibleRows.size());
- SRowRecord* p_rec = m_vVisibleRows[index];
- return static_cast<IAlignRow*>(p_rec->m_pRow);
- }
- ////////////////////////////////////////////////////////////////////////////////
- // CSelListModelImpl virtual functions
- void CAlnMultiModel::x_SelectItem(TIndex index, bool b_sel)
- {
- m_vVisibleRows[index]->SetState(IAlignRow::fItemSelected, b_sel);
- }
- bool CAlnMultiModel::x_IsItemSelected(TIndex index) const
- {
- return m_vVisibleRows[index]->IsSelected();
- }
- // returns number of visible rows (lines)
- CAlnMultiModel::TIndex CAlnMultiModel::x_GetItemsCount() const
- {
- return m_vVisibleRows.size();
- }
- CAlnMultiModel::TItem CAlnMultiModel::x_GetItem(TIndex index) const
- {
- TNumrow row = x_GetRowByLine(index)->GetRowNum();
- return row;
- }
- void CAlnMultiModel::x_SetEntries(const TEntryVector& v_entries)
- {
- size_t entries_n = v_entries.size();
- m_vVisibleRows.resize(entries_n);
- for( size_t i = 0; i < entries_n; i++ ) {
- TNumrow row = v_entries[i].first;
- SRowRecord& rec = *m_RowToRec[row];
- rec.m_Line = i;
- rec.SetState(IAlignRow::fItemSelected, v_entries[i].second);
- rec.SetState(IAlignRow::fItemHidden, false);
- m_vVisibleRows[i] = &rec;
- }
- }
- CAlnMultiModel::TIndex CAlnMultiModel::x_GetItemIndex(const TItem& item)
- {
- SRowRecord& rec = *m_RowToRec[item];
- return rec.IsVisible() ? rec.m_Line : -1;
- }
- void CAlnMultiModel::x_InsertItem(TIndex index, const TItemEntry& entry)
- {
- TNumrow row = entry.first;
- SRowRecord* p_rec = m_RowToRec[row];
- p_rec->SetState(IAlignRow::fItemSelected, entry.second);
- p_rec->m_Line = index;
- m_vVisibleRows.insert(m_vVisibleRows.begin() + index, p_rec);
- }
- void CAlnMultiModel::x_CompleteInsertion()
- {
- x_DoUpdateRowLines();
- }
- void CAlnMultiModel::x_MarkItemForErase(TIndex index)
- {
- m_vVisibleRows[index]->SetState(IAlignRow::fItemHidden, true);
- m_vVisibleRows[index]->SetState(IAlignRow::fItemSelected, false);
- m_vVisibleRows[index] = NULL;
- }
- void CAlnMultiModel::x_EraseMarkedItems()
- {
- int shift = 0;
- int count = m_vVisibleRows.size();
- for(int i = 0; i < count; i++ ) {
- if(m_vVisibleRows[i]) {
- if(shift >0) {
- m_vVisibleRows[i - shift] = m_vVisibleRows[i];
- m_vVisibleRows[i - shift]->m_Line = i - shift;
- }
- } else shift++;
- }
- m_vVisibleRows.resize(m_vVisibleRows.size() - shift);
- }
- void CAlnMultiModel::x_ClearItems()
- {
- for( size_t i = 0; i < m_vVisibleRows.size(); i++ ) {
- m_vVisibleRows[i]->SetState(IAlignRow::fItemHidden, true);
- m_vVisibleRows[i]->SetState(IAlignRow::fItemSelected, false);
- }
- m_vVisibleRows.clear();
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: alnmulti_model.cpp,v $
- * Revision 1000.1 2004/06/01 21:07:07 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
- *
- * Revision 1.11 2004/05/21 22:27:52 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.10 2004/05/10 17:46:35 yazhuk
- * Addressed GCC warnings
- *
- * Revision 1.9 2004/04/27 15:36:28 yazhuk
- * Fixed SetVisivle() so that it does not change rows order
- *
- * Revision 1.8 2004/04/23 14:09:13 johnson
- * removed invalid ASSERT
- *
- * Revision 1.7 2004/04/22 17:09:41 yazhuk
- * Enable Auto Sorting from UpdateSortOrder()
- *
- * Revision 1.6 2004/04/06 19:38:11 dicuccio
- * Tweak for GCC - cast NULL to pointer type for vector<*>
- *
- * Revision 1.5 2004/04/06 16:04:05 yazhuk
- * Implemented GetSelectedRows(), EnableAutoSorting(), SetRowOrder()
- *
- * Revision 1.4 2004/04/02 16:39:42 yazhuk
- * Selection/visibility handling fixes
- *
- * Revision 1.3 2004/03/18 17:08:26 yazhuk
- * Modified SetVisible() to support "b_invert_others" argument
- *
- * Revision 1.2 2004/03/17 20:15:37 yazhuk
- * Refactored CAlnMultiModel interface
- *
- * Revision 1.1 2004/03/09 20:59:14 yazhuk
- * Initial revision. Factored out from CAlnMultiWidget.
- *
- * ===========================================================================
- */