mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 00:12:57 +00:00
[MSPAINT] Establish Undo/Redo management (#5347)
- Painting the canvas is done by overlaying the multiple layers. - Drawing each overlay is implemented as polymorphism of OOP. - Refine the Undo/Redo mechanism. - Some adjustments. CORE-17969
This commit is contained in:
parent
b7071f67a8
commit
e8c7e30030
25 changed files with 721 additions and 504 deletions
|
@ -21,6 +21,7 @@ SelectionModel::SelectionModel()
|
|||
, m_bShow(FALSE)
|
||||
{
|
||||
::SetRectEmpty(&m_rc);
|
||||
::SetRectEmpty(&m_rcOld);
|
||||
m_ptHit.x = m_ptHit.y = -1;
|
||||
}
|
||||
|
||||
|
@ -57,25 +58,13 @@ void SelectionModel::PushToPtStack(POINT pt)
|
|||
#undef GROW_COUNT
|
||||
}
|
||||
|
||||
void SelectionModel::ShiftPtStack(BOOL bPlus)
|
||||
void SelectionModel::ShiftPtStack(INT dx, INT dy)
|
||||
{
|
||||
if (bPlus)
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x += m_rc.left;
|
||||
pt.y += m_rc.top;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x -= m_rc.left;
|
||||
pt.y -= m_rc.top;
|
||||
}
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x += dx;
|
||||
pt.y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,16 +82,16 @@ void SelectionModel::BuildMaskFromPtStack()
|
|||
rc.right += 1;
|
||||
rc.bottom += 1;
|
||||
|
||||
m_rc = rc;
|
||||
|
||||
ShiftPtStack(FALSE);
|
||||
m_rc = m_rcOld = rc;
|
||||
|
||||
ClearMask();
|
||||
|
||||
ShiftPtStack(-m_rcOld.left, -m_rcOld.top);
|
||||
|
||||
HDC hdcMem = ::CreateCompatibleDC(NULL);
|
||||
m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
|
||||
HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
|
||||
FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
|
||||
::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
|
||||
HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
|
||||
HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
|
||||
::Polygon(hdcMem, m_ptStack, m_iPtSP);
|
||||
|
@ -110,34 +99,39 @@ void SelectionModel::BuildMaskFromPtStack()
|
|||
::SelectObject(hdcMem, hPenOld);
|
||||
::SelectObject(hdcMem, hbmOld);
|
||||
::DeleteDC(hdcMem);
|
||||
|
||||
ShiftPtStack(+m_rcOld.left, +m_rcOld.top);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
|
||||
{
|
||||
ShiftPtStack(TRUE);
|
||||
if (::IsRectEmpty(&m_rcOld))
|
||||
return;
|
||||
|
||||
HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN));
|
||||
HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg));
|
||||
::Polygon(hDCImage, m_ptStack, m_iPtSP);
|
||||
::DeleteObject(::SelectObject(hDCImage, hbrOld));
|
||||
::SelectObject(hDCImage, hPenOld);
|
||||
|
||||
ShiftPtStack(FALSE);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
|
||||
{
|
||||
Rect(hDCImage, m_rc.left, m_rc.top, m_rc.right, m_rc.bottom, crBg, crBg, 0, 1);
|
||||
if (::IsRectEmpty(&m_rcOld))
|
||||
return;
|
||||
|
||||
Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg, BOOL bBgTransparent)
|
||||
void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
|
||||
{
|
||||
CRect rc = *prc;
|
||||
CRect rc = m_rc;
|
||||
if (::IsRectEmpty(&rc))
|
||||
return;
|
||||
|
||||
BITMAP bm;
|
||||
GetObject(m_hbmColor, sizeof(BITMAP), &bm);
|
||||
if (!GetObject(m_hbmColor, sizeof(BITMAP), &bm))
|
||||
return;
|
||||
|
||||
COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
|
||||
|
||||
|
@ -161,23 +155,23 @@ void SelectionModel::GetSelectionContents(HDC hDCImage)
|
|||
::DeleteDC(hMemDC);
|
||||
}
|
||||
|
||||
BOOL SelectionModel::IsLanded() const
|
||||
{
|
||||
return !m_hbmColor;
|
||||
}
|
||||
|
||||
BOOL SelectionModel::TakeOff()
|
||||
{
|
||||
if (m_hbmColor || ::IsRectEmpty(&m_rc))
|
||||
if (!IsLanded() || ::IsRectEmpty(&m_rc))
|
||||
return FALSE;
|
||||
|
||||
HDC hDCImage = imageModel.GetDC();
|
||||
GetSelectionContents(hDCImage);
|
||||
m_rgbBack = paletteModel.GetBgColor();
|
||||
GetSelectionContents(imageModel.GetDC());
|
||||
|
||||
if (toolsModel.GetActiveTool() == TOOL_FREESEL)
|
||||
{
|
||||
DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
|
||||
ClearMask();
|
||||
DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
|
||||
}
|
||||
|
||||
m_rcOld = m_rc;
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
|
@ -185,16 +179,23 @@ BOOL SelectionModel::TakeOff()
|
|||
|
||||
void SelectionModel::Landing()
|
||||
{
|
||||
if (!m_hbmColor)
|
||||
if (IsLanded() && !m_bShow)
|
||||
{
|
||||
imageModel.NotifyImageChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
DrawSelection(imageModel.GetDC(), &m_rc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
|
||||
m_bShow = FALSE;
|
||||
|
||||
::SetRectEmpty(&m_rc);
|
||||
ClearMask();
|
||||
ClearColor();
|
||||
if (!::EqualRect(m_rc, m_rcOld) && !::IsRectEmpty(m_rc) && !::IsRectEmpty(m_rcOld))
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
canvasWindow.m_drawing = FALSE;
|
||||
toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
|
||||
}
|
||||
|
||||
HideSelection();
|
||||
}
|
||||
|
||||
void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
|
||||
|
@ -349,11 +350,11 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int
|
|||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
HBITMAP SelectionModel::GetBitmap()
|
||||
HBITMAP SelectionModel::CopyBitmap()
|
||||
{
|
||||
if (m_hbmColor == NULL)
|
||||
GetSelectionContents(imageModel.GetDC());
|
||||
return m_hbmColor;
|
||||
return CopyDIBImage(m_hbmColor);
|
||||
}
|
||||
|
||||
int SelectionModel::PtStackSize() const
|
||||
|
@ -435,15 +436,29 @@ void SelectionModel::ClearColor()
|
|||
}
|
||||
}
|
||||
|
||||
void SelectionModel::CancelSelection()
|
||||
void SelectionModel::HideSelection()
|
||||
{
|
||||
m_bShow = FALSE;
|
||||
ClearColor();
|
||||
ClearMask();
|
||||
::SetRectEmpty(&m_rc);
|
||||
::SetRectEmpty(&m_rcOld);
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void SelectionModel::DeleteSelection()
|
||||
{
|
||||
if (!m_bShow)
|
||||
return;
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
if (m_bShow)
|
||||
imageModel.Undo(TRUE);
|
||||
TakeOff();
|
||||
|
||||
m_bShow = FALSE;
|
||||
imageModel.NotifyImageChanged();
|
||||
imageModel.PushImageForUndo();
|
||||
if (toolsModel.GetActiveTool() == TOOL_FREESEL)
|
||||
DrawBackgroundPoly(imageModel.GetDC(), paletteModel.GetBgColor());
|
||||
else
|
||||
DrawBackgroundRect(imageModel.GetDC(), paletteModel.GetBgColor());
|
||||
|
||||
HideSelection();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue