예제 #1
0
/** 
 * @brief Draws rect indicating visible area in file views.
 *
 * @param [in] nTopLine New topline for indicator
 * @param [in] nBottomLine New bottomline for indicator
 * @todo This function dublicates too much DrawRect() code.
 */
void CLocationView::DrawVisibleAreaRect(CDC *pClientDC, int nTopLine, int nBottomLine)
{
	CMergeDoc* pDoc = GetDocument();
	if (nTopLine == -1)
		nTopLine = pDoc->GetRightView()->GetTopSubLine();
	
	if (nBottomLine == -1)
	{
		const int nScreenLines = pDoc->GetRightView()->GetScreenLines();
		nBottomLine = nTopLine + nScreenLines;
	}

	CRect rc;
	GetClientRect(rc);
	const int nbLines = min(m_view[MERGE_VIEW_LEFT]->GetSubLineCount(),
			m_view[MERGE_VIEW_RIGHT]->GetSubLineCount());

	int nTopCoord = static_cast<int>(Y_OFFSET +
			(static_cast<double>(nTopLine * m_lineInPix)));
	int nBottomCoord = static_cast<int>(Y_OFFSET +
			(static_cast<double>(nBottomLine * m_lineInPix)));
	
	double xbarBottom = min(nbLines / m_pixInLines + Y_OFFSET, rc.Height() - Y_OFFSET);
	int barBottom = (int)xbarBottom;
	// Make sure bottom coord is in bar range
	nBottomCoord = min(nBottomCoord, barBottom);

	// Ensure visible area is at least minimum height
	if (nBottomCoord - nTopCoord < INDICATOR_MIN_HEIGHT)
	{
		// If area is near top of file, add additional area to bottom
		// of the bar and vice versa.
		if (nTopCoord < Y_OFFSET + 20)
			nBottomCoord += INDICATOR_MIN_HEIGHT - (nBottomCoord - nTopCoord);
		else
		{
			// Make sure locationbox has min hight
			if ((nBottomCoord - nTopCoord) < INDICATOR_MIN_HEIGHT)
			{
				// If we have a high number of lines, it may be better
				// to keep the topline, otherwise the cursor can 
				// jump up and down unexpected
				nBottomCoord = nTopCoord + INDICATOR_MIN_HEIGHT;
			}
		}
	}

	// Store current values for later use (to check if area changes)
	m_visibleTop = nTopCoord;
	m_visibleBottom = nBottomCoord;

	CRect rcVisibleArea(2, m_visibleTop, rc.right - 2, m_visibleBottom);
	CBitmap *pBitmap = CopyRectToBitmap(pClientDC, rcVisibleArea);
	CBitmap *pDarkenedBitmap = GetDarkenedBitmap(pClientDC, pBitmap);
	DrawBitmap(pClientDC, rcVisibleArea.left, rcVisibleArea.top, pDarkenedBitmap);
	delete pDarkenedBitmap;
	delete pBitmap;
}
예제 #2
0
/**
 * @brief Handle scroll events sent directly.
 *
 */
void CLocationView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar)
{
	if (pScrollBar == NULL)
	{
		// Scroll did not come frome a scroll bar
		// Send it to the right view instead
 	  CMergeDoc *pDoc = GetDocument();
		pDoc->GetRightView()->SendMessage(WM_VSCROLL,
			MAKELONG(nSBCode, nPos), (LPARAM)NULL);
		return;
	}
	CView::OnVScroll (nSBCode, nPos, pScrollBar);
}
예제 #3
0
/** 
 * @brief Update view.
 */
void CLocationView::OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint )
{
	UNREFERENCED_PARAMETER(pSender);
	UNREFERENCED_PARAMETER(lHint);
	CMergeDoc* pDoc = GetDocument();
	m_view[MERGE_VIEW_LEFT] = pDoc->GetLeftView();
	m_view[MERGE_VIEW_RIGHT] = pDoc->GetRightView();

	// Give pointer to MergeEditView
	m_view[MERGE_VIEW_LEFT]->SetLocationView(this);
	m_view[MERGE_VIEW_RIGHT]->SetLocationView(this);

	m_bRecalculateBlocks = TRUE;
	Invalidate();
}
예제 #4
0
/**
 * @brief Copy diff from right pane to left pane
 */
void CMergeDiffDetailView::OnR2l()
{
	// Check that left side is not readonly
	if (IsReadOnly(0))
		return;

	CMergeDoc *pDoc = GetDocument();
	int currentDiff = pDoc->GetCurrentDiff();

	if (currentDiff != -1 && pDoc->m_diffList.IsDiffSignificant(currentDiff))
	{
		WaitStatusCursor waitstatus(IDS_STATUS_COPYR2L);
		pDoc->ListCopy(1, 0, currentDiff);
	}
}
예제 #5
0
BOOL CMergeDiffDetailView::PreTranslateMessage(MSG* pMsg)
{
	// Check if we got 'ESC pressed' -message
	if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_ESCAPE)) 
	{
		// Ask about saving unsaved document, allow to cancel closing
		CMergeDoc *pd = GetDocument();
		if (pd->PromptAndSaveIfNeeded(TRUE))
		{
			AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_FILE_CLOSE);
			return FALSE;
		}
		else
			return TRUE;
	}
	return CCrystalTextView::PreTranslateMessage(pMsg);
}
예제 #6
0
/**
 * @brief Close MergeDocs opened from DirDoc.
 *
 * Asks confirmation for docs containing unsaved data and then
 * closes MergeDocs.
 * @return TRUE if success, FALSE if user canceled or closing failed
 */
BOOL CDirDoc::CloseMergeDocs()
{
	POSITION pos = m_MergeDocs.GetHeadPosition();
	while (pos)
	{
		CMergeDoc * pMergeDoc = m_MergeDocs.GetNext(pos);
		if (!pMergeDoc->CloseNow())
			return FALSE;
	}
	pos = m_HexMergeDocs.GetHeadPosition();
	while (pos)
	{
		CHexMergeDoc * pHexMergeDoc = m_HexMergeDocs.GetNext(pos);
		if (!pHexMergeDoc->CloseNow())
			return FALSE;
	}
	return TRUE;
}
예제 #7
0
/**
 * @brief Obtain a merge doc to display a difference in files.
 * @param [out] pNew Set to TRUE if a new doc is created,
 * and FALSE if an existing one reused.
 * @return Pointer to CMergeDoc to use (new or existing). 
 */
CMergeDoc * CDirDoc::GetMergeDocForDiff(BOOL * pNew)
{
	CMergeDoc * pMergeDoc = 0;
	// policy -- use an existing merge doc if available
	const BOOL bMultiDocs = GetOptionsMgr()->GetBool(OPT_MULTIDOC_MERGEDOCS);
	if (!bMultiDocs && !m_MergeDocs.IsEmpty())
	{
		*pNew = FALSE;
		pMergeDoc = m_MergeDocs.GetHead();
	}
	else
	{
		// Create a new merge doc
		pMergeDoc = (CMergeDoc*)theApp.m_pDiffTemplate->OpenDocumentFile(NULL);
		AddMergeDoc(pMergeDoc);
		pMergeDoc->SetDirDoc(this);
		*pNew = TRUE;
	}
	return pMergeDoc;
}
예제 #8
0
/**
 * @brief Destructor.
 *
 * Clears document list and deleted possible archive-temp files.
 */
CDirDoc::~CDirDoc()
{
	delete m_pCtxt;
	delete m_pCompareStats;

	// Inform all of our merge docs that we're closing
	POSITION pos = m_MergeDocs.GetHeadPosition();
	while (pos)
	{
		CMergeDoc * pMergeDoc = m_MergeDocs.GetNext(pos);
		pMergeDoc->DirDocClosing(this);
	}
	pos = m_HexMergeDocs.GetHeadPosition();
	while (pos)
	{
		CHexMergeDoc * pHexMergeDoc = m_HexMergeDocs.GetNext(pos);
		pHexMergeDoc->DirDocClosing(this);
	}
	// Delete all temporary folders belonging to this document
	while (m_pTempPathContext)
	{
		m_pTempPathContext = m_pTempPathContext->DeleteHead();
	}
}
예제 #9
0
/**
 * Show context menu and handle user selection.
 */
void CLocationView::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	if (point.x == -1 && point.y == -1)
	{
		//keystroke invocation
		CRect rect;
		GetClientRect(rect);
		ClientToScreen(rect);

		point = rect.TopLeft();
		point.Offset(5, 5);
	}

	CRect rc;
	CPoint pt = point;
	GetClientRect(rc);
	ScreenToClient(&pt);
	BCMenu menu;
	VERIFY(menu.LoadMenu(IDR_POPUP_LOCATIONBAR));
	theApp.TranslateMenu(menu.m_hMenu);

	BCMenu* pPopup = (BCMenu *) menu.GetSubMenu(0);
	ASSERT(pPopup != NULL);

	CCmdUI cmdUI;
	cmdUI.m_pMenu = pPopup;
	cmdUI.m_nIndexMax = cmdUI.m_pMenu->GetMenuItemCount();
	for (cmdUI.m_nIndex = 0 ; cmdUI.m_nIndex < cmdUI.m_nIndexMax ; ++cmdUI.m_nIndex)
	{
		cmdUI.m_nID = cmdUI.m_pMenu->GetMenuItemID(cmdUI.m_nIndex);
		switch (cmdUI.m_nID)
		{
		case ID_DISPLAY_MOVED_NONE:
			cmdUI.SetRadio(m_displayMovedBlocks == DISPLAY_MOVED_NONE);
			break;
		case ID_DISPLAY_MOVED_ALL:
			cmdUI.SetRadio(m_displayMovedBlocks == DISPLAY_MOVED_ALL);
			break;
		case ID_DISPLAY_MOVED_FOLLOW_DIFF:
			cmdUI.SetRadio(m_displayMovedBlocks == DISPLAY_MOVED_FOLLOW_DIFF);
			break;
		}
	}

	CString strItem;
	CString strNum;
	int nLine = -1;
	int bar = IsInsideBar(rc, pt);

	// If cursor over bar, format string with linenumber, else disable item
	if (bar != BAR_NONE)
	{
		// If outside bar area use left bar
		if (bar == BAR_YAREA)
			bar = BAR_LEFT;
		nLine = GetLineFromYPos(pt.y, bar);
		strNum.Format(_T("%d"), nLine + 1); // Show linenumber not lineindex
	}
	else
		pPopup->EnableMenuItem(ID_LOCBAR_GOTODIFF, MF_GRAYED);
	LangFormatString1(strItem, ID_LOCBAR_GOTOLINE_FMT, strNum);
	pPopup->SetMenuText(ID_LOCBAR_GOTODIFF, strItem, MF_BYCOMMAND);

	// invoke context menu
	// we don't want to use the main application handlers, so we use flags TPM_NONOTIFY | TPM_RETURNCMD
	// and handle the command after TrackPopupMenu
	int command = pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_NONOTIFY  | TPM_RETURNCMD, point.x, point.y, AfxGetMainWnd());

	CMergeDoc* pDoc = GetDocument();
	switch (command)
	{
	case ID_LOCBAR_GOTODIFF:
		m_view[MERGE_VIEW_LEFT]->GotoLine(nLine, true, bar);
	if (bar == BAR_LEFT || bar == BAR_RIGHT)
		m_view[bar]->SetFocus();
		break;
	case ID_EDIT_WMGOTO:
		m_view[MERGE_VIEW_LEFT]->WMGoto();
		break;
	case ID_DISPLAY_MOVED_NONE:
		SetConnectMovedBlocks(DISPLAY_MOVED_NONE);
		pDoc->SetDetectMovedBlocks(FALSE);
		break;
	case ID_DISPLAY_MOVED_ALL:
		SetConnectMovedBlocks(DISPLAY_MOVED_ALL);
		pDoc->SetDetectMovedBlocks(TRUE);
		break;
	case ID_DISPLAY_MOVED_FOLLOW_DIFF:
		SetConnectMovedBlocks(DISPLAY_MOVED_FOLLOW_DIFF);
		pDoc->SetDetectMovedBlocks(TRUE);
		break;
	}
}
예제 #10
0
/** 
 * @brief Draw maps of files.
 *
 * Draws maps of differences in files. Difference list is walked and
 * every difference is drawn with same colors as in editview.
 * @note We MUST use doubles when calculating coords to avoid rounding
 * to integers. Rounding causes miscalculation of coords.
 * @sa CLocationView::DrawRect()
 */
void CLocationView::OnDraw(CDC* pDC)
{
	ASSERT(m_view[MERGE_VIEW_LEFT] != NULL);
	ASSERT(m_view[MERGE_VIEW_RIGHT] != NULL);

	if (m_view[MERGE_VIEW_LEFT] == NULL || m_view[MERGE_VIEW_RIGHT] == NULL)
		return;

	if (!m_view[MERGE_VIEW_LEFT]->IsInitialized()) return;

	CRect rc;
	GetClientRect(&rc);

	CMemDC dc(pDC, &rc);

	COLORREF cr0 = CLR_NONE; // Left side color
	COLORREF cr1 = CLR_NONE; // Right side color
	COLORREF crt = CLR_NONE; // Text color
	BOOL bwh = FALSE;

	m_movedLines.RemoveAll();

	CalculateBars();
	DrawBackground(&dc);

	// Draw bar outlines
	CPen* oldObj = (CPen*)dc.SelectStockObject(BLACK_PEN);
	CBrush brush(m_view[0]->GetColor(COLORINDEX_WHITESPACE));
	CBrush* oldBrush = (CBrush*)dc.SelectObject(&brush);
	dc.Rectangle(m_leftBar);
	dc.Rectangle(m_rightBar);
	dc.SelectObject(oldBrush);
	dc.SelectObject(oldObj);

	// Iterate the differences list and draw differences as colored blocks.

	// Don't recalculate blocks if we earlier determined it is not needed
	// This may save lots of processing
	if (m_bRecalculateBlocks)
		CalculateBlocks();

	CMergeDoc *pDoc = GetDocument();
	int nPrevEndY = -1;
	const int nCurDiff = pDoc->GetCurrentDiff();

	vector<DiffBlock>::const_iterator iter = m_diffBlocks.begin();
	while (iter != m_diffBlocks.end())
	{
		CMergeEditView *pView = m_view[MERGE_VIEW_LEFT];
		const BOOL bInsideDiff = (nCurDiff == (*iter).diff_index);

		if ((nPrevEndY != (*iter).bottom_coord) || bInsideDiff)
		{
			// Draw left side block
			m_view[MERGE_VIEW_LEFT]->GetLineColors2((*iter).top_line, 0, cr0, crt, bwh);
			CRect r0(m_leftBar.left, (*iter).top_coord, m_leftBar.right, (*iter).bottom_coord);
			DrawRect(&dc, r0, cr0, bInsideDiff);

			// Draw right side block
			m_view[MERGE_VIEW_RIGHT]->GetLineColors2((*iter).top_line, 0, cr1, crt, bwh);
			CRect r1(m_rightBar.left, (*iter).top_coord, m_rightBar.right, (*iter).bottom_coord);
			DrawRect(&dc, r1, cr1, bInsideDiff);
		}
		nPrevEndY = (*iter).bottom_coord;

		// Test if we draw a connector
		BOOL bDisplayConnectorFromLeft = FALSE;
		BOOL bDisplayConnectorFromRight = FALSE;

		switch (m_displayMovedBlocks)
		{
		case DISPLAY_MOVED_FOLLOW_DIFF:
			// display moved block only for current diff
			if (!bInsideDiff)
				break;
			// two sides may be linked to a block somewhere else
			bDisplayConnectorFromLeft = TRUE;
			bDisplayConnectorFromRight = TRUE;
			break;
		case DISPLAY_MOVED_ALL:
			// we display all moved blocks, so once direction is enough
			bDisplayConnectorFromLeft = TRUE;
			break;
		default:
			break;
		}

		if (bDisplayConnectorFromLeft)
		{
			int apparent0 = (*iter).top_line;
			int apparent1 = pDoc->RightLineInMovedBlock(apparent0);
			const int nBlockHeight = (*iter).bottom_line - (*iter).top_line;
			if (apparent1 != -1)
			{
				MovedLine line;
				CPoint start;
				CPoint end;

				apparent0 = pView->GetSubLineIndex(apparent0);
				apparent1 = pView->GetSubLineIndex(apparent1);

				start.x = m_leftBar.right;
				int leftUpper = (int) (apparent0 * m_lineInPix + Y_OFFSET);
				int leftLower = (int) ((nBlockHeight + apparent0) * m_lineInPix + Y_OFFSET);
				start.y = leftUpper + (leftLower - leftUpper) / 2;
				end.x = m_rightBar.left;
				int rightUpper = (int) (apparent1 * m_lineInPix + Y_OFFSET);
				int rightLower = (int) ((nBlockHeight + apparent1) * m_lineInPix + Y_OFFSET);
				end.y = rightUpper + (rightLower - rightUpper) / 2;
				line.ptLeft = start;
				line.ptRight = end;
				m_movedLines.AddTail(line);
			}
		}

		if (bDisplayConnectorFromRight)
		{
			int apparent1 = (*iter).top_line;
			int apparent0 = pDoc->LeftLineInMovedBlock(apparent1);
			const int nBlockHeight = (*iter).bottom_line - (*iter).top_line;
			if (apparent0 != -1)
			{
				MovedLine line;
				CPoint start;
				CPoint end;

				apparent0 = pView->GetSubLineIndex(apparent0);
				apparent1 = pView->GetSubLineIndex(apparent1);

				start.x = m_leftBar.right;
				int leftUpper = (int) (apparent0 * m_lineInPix + Y_OFFSET);
				int leftLower = (int) ((nBlockHeight + apparent0) * m_lineInPix + Y_OFFSET);
				start.y = leftUpper + (leftLower - leftUpper) / 2;
				end.x = m_rightBar.left;
				int rightUpper = (int) (apparent1 * m_lineInPix + Y_OFFSET);
				int rightLower = (int) ((nBlockHeight + apparent1) * m_lineInPix + Y_OFFSET);
				end.y = rightUpper + (rightLower - rightUpper) / 2;
				line.ptLeft = start;
				line.ptRight = end;
				m_movedLines.AddTail(line);
			}
		}
		++iter;
	}

	if (m_displayMovedBlocks != DISPLAY_MOVED_NONE)
		DrawConnectLines(&dc);

	if (m_pSavedBackgroundBitmap)
		delete m_pSavedBackgroundBitmap;
	m_pSavedBackgroundBitmap = CopyRectToBitmap(&dc, rc);

	// Since we have invalidated locationbar there is no previous
	// arearect to remove
	m_visibleTop = -1;
	m_visibleBottom = -1;
	DrawVisibleAreaRect(&dc);

	m_bDrawn = true;
}
예제 #11
0
void CMergeDiffDetailView::OnRefresh()
{
	CMergeDoc *pd = GetDocument();
	ASSERT(pd);
	pd->FlushAndRescan(TRUE);
}