📄 block_multiple_alignment.cpp
字号:
if (to >= totalWidth) to = totalWidth - 1; // find first residue within range while (from <= to) { GetSequenceAndIndexAt(from, row, justification, &sequence, &fromIndex, &ignored); if (fromIndex >= 0) break; ++from; } if (from > to) return; // find last residue within range while (to >= from) { GetSequenceAndIndexAt(to, row, justification, &sequence, &toIndex, &ignored); if (toIndex >= 0) break; --to; } if (toggle) GlobalMessenger()->ToggleHighlights(sequence, fromIndex, toIndex); else GlobalMessenger()->AddHighlights(sequence, fromIndex, toIndex);}void BlockMultipleAlignment::GetAlignedBlockPosition(int alignmentIndex, int *blockColumn, int *blockWidth) const{ *blockColumn = *blockWidth = -1; const BlockInfo& info = blockMap[alignmentIndex]; if (info.block->IsAligned()) { *blockColumn = info.blockColumn; *blockWidth = info.block->width; }}Block * BlockMultipleAlignment::GetBlockBefore(const Block *block) const{ Block *prevBlock = NULL; BlockList::const_iterator b, be = blocks.end(); for (b=blocks.begin(); b!=be; ++b) { if (*b == block) break; prevBlock = *b; } return prevBlock;}const UnalignedBlock * BlockMultipleAlignment::GetUnalignedBlockBefore( const UngappedAlignedBlock *aBlock) const{ const Block *prevBlock; if (aBlock) prevBlock = GetBlockBefore(aBlock); else prevBlock = blocks.back(); return dynamic_cast<const UnalignedBlock*>(prevBlock);}Block * BlockMultipleAlignment::GetBlockAfter(const Block *block) const{ BlockList::const_iterator b, be = blocks.end(); for (b=blocks.begin(); b!=be; ++b) { if (*b == block) { ++b; if (b == be) break; return *b; } } return NULL;}void BlockMultipleAlignment::InsertBlockBefore(Block *newBlock, const Block *insertAt){ BlockList::iterator b, be = blocks.end(); for (b=blocks.begin(); b!=be; ++b) { if (*b == insertAt) { blocks.insert(b, newBlock); return; } } WARNINGMSG("BlockMultipleAlignment::InsertBlockBefore() - couldn't find insertAt block");}void BlockMultipleAlignment::InsertBlockAfter(const Block *insertAt, Block *newBlock){ BlockList::iterator b, be = blocks.end(); for (b=blocks.begin(); b!=be; ++b) { if (*b == insertAt) { ++b; blocks.insert(b, newBlock); return; } } WARNINGMSG("BlockMultipleAlignment::InsertBlockBefore() - couldn't find insertAt block");}void BlockMultipleAlignment::RemoveBlock(Block *block){ BlockList::iterator b, be = blocks.end(); for (b=blocks.begin(); b!=be; ++b) { if (*b == block) { delete *b; blocks.erase(b); InitCache(); return; } } WARNINGMSG("BlockMultipleAlignment::RemoveBlock() - couldn't find block");}bool BlockMultipleAlignment::MoveBlockBoundary(int columnFrom, int columnTo){ int blockColumn, blockWidth; GetAlignedBlockPosition(columnFrom, &blockColumn, &blockWidth); if (blockColumn < 0 || blockWidth <= 0) return false; TRACEMSG("trying to move block boundary from " << columnFrom << " to " << columnTo); const BlockInfo& info = blockMap[columnFrom]; int row, requestedShift = columnTo - columnFrom, actualShift = 0; const Block::Range *range; // shrink block from left if (blockColumn == 0 && requestedShift > 0 && requestedShift < info.block->width) { actualShift = requestedShift; TRACEMSG("shrinking block from left"); for (row=0; row<NRows(); ++row) { range = info.block->GetRangeOfRow(row); info.block->SetRangeOfRow(row, range->from + requestedShift, range->to); } info.block->width -= requestedShift; Block *prevBlock = GetBlockBefore(info.block); if (prevBlock && !prevBlock->IsAligned()) { for (row=0; row<NRows(); ++row) { range = prevBlock->GetRangeOfRow(row); prevBlock->SetRangeOfRow(row, range->from, range->to + requestedShift); } prevBlock->width += requestedShift; } else { Block *newUnalignedBlock = CreateNewUnalignedBlockBetween(prevBlock, info.block); if (newUnalignedBlock) InsertBlockBefore(newUnalignedBlock, info.block); TRACEMSG("added new unaligned block"); } } // shrink block from right (requestedShift < 0) else if (blockColumn == info.block->width - 1 && requestedShift < 0 && requestedShift > -info.block->width) { actualShift = requestedShift; TRACEMSG("shrinking block from right"); for (row=0; row<NRows(); ++row) { range = info.block->GetRangeOfRow(row); info.block->SetRangeOfRow(row, range->from, range->to + requestedShift); } info.block->width += requestedShift; Block *nextBlock = GetBlockAfter(info.block); if (nextBlock && !nextBlock->IsAligned()) { for (row=0; row<NRows(); ++row) { range = nextBlock->GetRangeOfRow(row); nextBlock->SetRangeOfRow(row, range->from + requestedShift, range->to); } nextBlock->width -= requestedShift; } else { Block *newUnalignedBlock = CreateNewUnalignedBlockBetween(info.block, nextBlock); if (newUnalignedBlock) InsertBlockAfter(info.block, newUnalignedBlock); TRACEMSG("added new unaligned block"); } } // grow block to right else if (blockColumn == info.block->width - 1 && requestedShift > 0) { Block *nextBlock = GetBlockAfter(info.block); if (nextBlock && !nextBlock->IsAligned()) { int nRes; actualShift = requestedShift; for (row=0; row<NRows(); ++row) { range = nextBlock->GetRangeOfRow(row); nRes = range->to - range->from + 1; if (nRes < actualShift) actualShift = nRes; } if (actualShift) { TRACEMSG("growing block to right"); for (row=0; row<NRows(); ++row) { range = info.block->GetRangeOfRow(row); info.block->SetRangeOfRow(row, range->from, range->to + actualShift); range = nextBlock->GetRangeOfRow(row); nextBlock->SetRangeOfRow(row, range->from + actualShift, range->to); } info.block->width += actualShift; nextBlock->width -= actualShift; if (nextBlock->width == 0) { RemoveBlock(nextBlock); TRACEMSG("removed empty block"); } } } } // grow block to left (requestedShift < 0) else if (blockColumn == 0 && requestedShift < 0) { Block *prevBlock = GetBlockBefore(info.block); if (prevBlock && !prevBlock->IsAligned()) { int nRes; actualShift = requestedShift; for (row=0; row<NRows(); ++row) { range = prevBlock->GetRangeOfRow(row); nRes = range->to - range->from + 1; if (nRes < -actualShift) actualShift = -nRes; } if (actualShift) { TRACEMSG("growing block to left"); for (row=0; row<NRows(); ++row) { range = info.block->GetRangeOfRow(row); info.block->SetRangeOfRow(row, range->from + actualShift, range->to); range = prevBlock->GetRangeOfRow(row); prevBlock->SetRangeOfRow(row, range->from, range->to + actualShift); } info.block->width -= actualShift; prevBlock->width += actualShift; if (prevBlock->width == 0) { RemoveBlock(prevBlock); TRACEMSG("removed empty block"); } } } } if (actualShift != 0) { UpdateBlockMapAndColors(); return true; } else return false;}bool BlockMultipleAlignment::ShiftRow(int row, int fromAlignmentIndex, int toAlignmentIndex, eUnalignedJustification justification){ if (fromAlignmentIndex == toAlignmentIndex) return false; Block *blockFrom = blockMap[fromAlignmentIndex].block, *blockTo = blockMap[toAlignmentIndex].block; // at least one end of the drag must be in an aligned block UngappedAlignedBlock *ABlock = dynamic_cast<UngappedAlignedBlock*>(blockFrom); if (ABlock) { if (blockTo != blockFrom && blockTo->IsAligned()) return false; } else { ABlock = dynamic_cast<UngappedAlignedBlock*>(blockTo); if (!ABlock) return false; } // and the other must be in the same aligned block or an adjacent unaligned block UnalignedBlock *prevUABlock = dynamic_cast<UnalignedBlock*>(GetBlockBefore(ABlock)), *nextUABlock = dynamic_cast<UnalignedBlock*>(GetBlockAfter(ABlock)); if (blockFrom != blockTo && ((ABlock == blockFrom && prevUABlock != blockTo && nextUABlock != blockTo) || (ABlock == blockTo && prevUABlock != blockFrom && nextUABlock != blockFrom))) return false; int requestedShift, actualShift = 0, width = 0; // slightly different behaviour when dragging from unaligned to aligned... if (!blockFrom->IsAligned()) { int fromSeqIndex, toSeqIndex; GetSequenceAndIndexAt(fromAlignmentIndex, row, justification, NULL, &fromSeqIndex, NULL); GetSequenceAndIndexAt(toAlignmentIndex, row, justification, NULL, &toSeqIndex, NULL); if (fromSeqIndex < 0 || toSeqIndex < 0) return false; requestedShift = toSeqIndex - fromSeqIndex; } // vs. dragging from aligned else { requestedShift = toAlignmentIndex - fromAlignmentIndex; } const Block::Range *prevRange = NULL, *nextRange = NULL, *range = ABlock->GetRangeOfRow(row); if (prevUABlock) prevRange = prevUABlock->GetRangeOfRow(row); if (nextUABlock) nextRange = nextUABlock->GetRangeOfRow(row); if (requestedShift > 0) { if (prevUABlock) width = prevRange->to - prevRange->from + 1; actualShift = (width > requestedShift) ? requestedShift : width; } else { if (nextUABlock) width = nextRange->to - nextRange->from + 1; actualShift = (width > -requestedShift) ? requestedShift : -width; } if (actualShift == 0) return false; TRACEMSG("shifting row " << row << " by " << actualShift); ABlock->SetRangeOfRow(row, range->from - actualShift, range->to - actualShift); if (prevUABlock) { prevUABlock->SetRangeOfRow(row, prevRange->from, prevRange->to - actualShift); prevUABlock->width = 0; for (int i=0; i<NRows(); ++i) { prevRange = prevUABlock->GetRangeOfRow(i); width = prevRange->to - prevRange->from + 1; if (width < 0) ERRORMSG("BlockMultipleAlignment::ShiftRow() - negative width on left"); if (width > prevUABlock->width) prevUABlock->width = width; } if (prevUABlock->width == 0) { TRACEMSG("removing zero-width unaligned block on left"); RemoveBlock(prevUABlock); } } else { TRACEMSG("creating unaligned block on left"); prevUABlock = CreateNewUnalignedBlockBetween(GetBlockBefore(ABlock), ABlock); InsertBlockBefore(prevUABlock, ABlock); } if (nextUABlock) { nextUABlock->SetRangeOfRow(row, nextRange->from - actualShift, nextRange->to); nextUABlock->width = 0; for (int i=0; i<NRows(); ++i) { nextRange = nextUABlock->GetRangeOfRow(i); width = nextRange->to - nextRange->from + 1; if (width < 0) ERRORMSG("BlockMultipleAlignment::ShiftRow() - negative width on right"); if (width > nextUABlock->width) nextUABlock->width = width; } if (nextUABlock->width == 0) { TRACEMSG("removing zero-width unaligned block on right"); RemoveBlock(nextUABlock); } } else { TRACEMSG("creating unaligned block on right"); nextUABlock = CreateNewUnalignedBlockBetween(ABlock, GetBlockAfter(ABlock)); InsertBlockAfter(ABlock, nextUABlock); } if (!CheckAlignedBlock(ABlock)) ERRORMSG("BlockMultipleAlignment::ShiftRow() - shift failed to create valid aligned block"); UpdateBlockMapAndColors(); return true;}bool BlockMultipleAlignment::SplitBlock(int alignmentIndex){ const BlockInfo& info = blockMap[alignmentIndex]; if (!info.block->IsAligned() || info.block->width < 2 || info.blockColumn == 0) return false; TRACEMSG("splitting block"); UngappedAlignedBlock *newAlignedBlock = new UngappedAlignedBlock(this); newAlignedBlock->width = info.block->width - info.blockColumn; info.block->width = info.blockColumn; const Block::Range *range; int oldTo; for (int row=0; row<NRows(); ++row) { range = info.block->GetRangeOfRow(row); oldTo = range->to; info.block->SetRangeOfRow(row, range->from, range->from + info.block->width - 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -