2 * PROJECT: PAINT for ReactOS
4 * FILE: base/applications/mspaint/history.cpp
5 * PURPOSE: Undo and redo functionality
6 * PROGRAMMERS: Benedikt Freisen
11 ImageModel imageModel
;
13 /* FUNCTIONS ********************************************************/
15 void ImageModel::NotifyDimensionsChanged()
17 if (imageArea
.IsWindow())
18 imageArea
.SendMessage(WM_IMAGEMODELDIMENSIONSCHANGED
);
21 void ImageModel::NotifyImageChanged()
23 if (imageArea
.IsWindow())
24 imageArea
.SendMessage(WM_IMAGEMODELIMAGECHANGED
);
27 ImageModel::ImageModel()
34 // prepare a minimal usable bitmap
38 hDrawingDC
= CreateCompatibleDC(NULL
);
39 SelectObject(hDrawingDC
, CreatePen(PS_SOLID
, 0, paletteModel
.GetFgColor()));
40 SelectObject(hDrawingDC
, CreateSolidBrush(paletteModel
.GetBgColor()));
42 hBms
[0] = CreateDIBWithProperties(imgXRes
, imgYRes
);
43 SelectObject(hDrawingDC
, hBms
[0]);
44 Rectangle(hDrawingDC
, 0 - 1, 0 - 1, imgXRes
+ 1, imgYRes
+ 1);
47 void ImageModel::CopyPrevious()
49 ATLTRACE("%s: %d\n", __FUNCTION__
, currInd
);
50 DeleteObject(hBms
[(currInd
+ 1) % HISTORYSIZE
]);
51 hBms
[(currInd
+ 1) % HISTORYSIZE
] = CopyDIBImage(hBms
[currInd
]);
52 currInd
= (currInd
+ 1) % HISTORYSIZE
;
53 if (undoSteps
< HISTORYSIZE
- 1)
56 SelectObject(hDrawingDC
, hBms
[currInd
]);
60 void ImageModel::Undo(BOOL bClearRedo
)
62 ATLTRACE("%s: %d\n", __FUNCTION__
, undoSteps
);
65 int oldWidth
= GetWidth();
66 int oldHeight
= GetHeight();
67 selectionModel
.m_bShow
= FALSE
;
68 currInd
= (currInd
+ HISTORYSIZE
- 1) % HISTORYSIZE
;
69 SelectObject(hDrawingDC
, hBms
[currInd
]);
73 else if (redoSteps
< HISTORYSIZE
- 1)
75 if (GetWidth() != oldWidth
|| GetHeight() != oldHeight
)
76 NotifyDimensionsChanged();
81 void ImageModel::Redo()
83 ATLTRACE("%s: %d\n", __FUNCTION__
, redoSteps
);
86 int oldWidth
= GetWidth();
87 int oldHeight
= GetHeight();
88 selectionModel
.m_bShow
= FALSE
;
89 currInd
= (currInd
+ 1) % HISTORYSIZE
;
90 SelectObject(hDrawingDC
, hBms
[currInd
]);
92 if (undoSteps
< HISTORYSIZE
- 1)
94 if (GetWidth() != oldWidth
|| GetHeight() != oldHeight
)
95 NotifyDimensionsChanged();
100 void ImageModel::ResetToPrevious()
102 ATLTRACE("%s: %d\n", __FUNCTION__
, currInd
);
103 DeleteObject(hBms
[currInd
]);
104 hBms
[currInd
] = CopyDIBImage(hBms
[(currInd
+ HISTORYSIZE
- 1) % HISTORYSIZE
]);
105 SelectObject(hDrawingDC
, hBms
[currInd
]);
106 NotifyImageChanged();
109 void ImageModel::ClearHistory()
115 void ImageModel::Insert(HBITMAP hbm
)
117 int oldWidth
= GetWidth();
118 int oldHeight
= GetHeight();
119 DeleteObject(hBms
[(currInd
+ 1) % HISTORYSIZE
]);
120 hBms
[(currInd
+ 1) % HISTORYSIZE
] = hbm
;
121 currInd
= (currInd
+ 1) % HISTORYSIZE
;
122 if (undoSteps
< HISTORYSIZE
- 1)
125 SelectObject(hDrawingDC
, hBms
[currInd
]);
126 if (GetWidth() != oldWidth
|| GetHeight() != oldHeight
)
127 NotifyDimensionsChanged();
128 NotifyImageChanged();
131 void ImageModel::Crop(int nWidth
, int nHeight
, int nOffsetX
, int nOffsetY
)
136 int oldWidth
= GetWidth();
137 int oldHeight
= GetHeight();
144 SelectObject(hDrawingDC
, hBms
[currInd
]);
145 DeleteObject(hBms
[(currInd
+ 1) % HISTORYSIZE
]);
146 hBms
[(currInd
+ 1) % HISTORYSIZE
] = CreateDIBWithProperties(nWidth
, nHeight
);
147 currInd
= (currInd
+ 1) % HISTORYSIZE
;
148 if (undoSteps
< HISTORYSIZE
- 1)
152 hdc
= CreateCompatibleDC(hDrawingDC
);
153 SelectObject(hdc
, hBms
[currInd
]);
155 oldPen
= (HPEN
) SelectObject(hdc
, CreatePen(PS_SOLID
, 1, paletteModel
.GetBgColor()));
156 oldBrush
= (HBRUSH
) SelectObject(hdc
, CreateSolidBrush(paletteModel
.GetBgColor()));
157 Rectangle(hdc
, 0, 0, nWidth
, nHeight
);
158 BitBlt(hdc
, -nOffsetX
, -nOffsetY
, GetWidth(), GetHeight(), hDrawingDC
, 0, 0, SRCCOPY
);
159 DeleteObject(SelectObject(hdc
, oldBrush
));
160 DeleteObject(SelectObject(hdc
, oldPen
));
162 SelectObject(hDrawingDC
, hBms
[currInd
]);
164 if (GetWidth() != oldWidth
|| GetHeight() != oldHeight
)
165 NotifyDimensionsChanged();
166 NotifyImageChanged();
169 void ImageModel::SaveImage(LPTSTR lpFileName
)
171 SaveDIBToFile(hBms
[currInd
], lpFileName
, hDrawingDC
);
174 BOOL
ImageModel::IsImageSaved() const
179 BOOL
ImageModel::HasUndoSteps() const
181 return undoSteps
> 0;
184 BOOL
ImageModel::HasRedoSteps() const
186 return redoSteps
> 0;
189 void ImageModel::StretchSkew(int nStretchPercentX
, int nStretchPercentY
, int nSkewDegX
, int nSkewDegY
)
191 int oldWidth
= GetWidth();
192 int oldHeight
= GetHeight();
193 INT newWidth
= oldWidth
* nStretchPercentX
/ 100;
194 INT newHeight
= oldHeight
* nStretchPercentY
/ 100;
195 if (oldWidth
!= newWidth
|| oldHeight
!= newHeight
)
197 HBITMAP hbm0
= CopyDIBImage(hBms
[currInd
], newWidth
, newHeight
);
202 HBITMAP hbm1
= SkewDIB(hDrawingDC
, hBms
[currInd
], nSkewDegX
, FALSE
);
207 HBITMAP hbm2
= SkewDIB(hDrawingDC
, hBms
[currInd
], nSkewDegY
, TRUE
);
210 if (GetWidth() != oldWidth
|| GetHeight() != oldHeight
)
211 NotifyDimensionsChanged();
212 NotifyImageChanged();
215 int ImageModel::GetWidth() const
217 return GetDIBWidth(hBms
[currInd
]);
220 int ImageModel::GetHeight() const
222 return GetDIBHeight(hBms
[currInd
]);
225 void ImageModel::InvertColors()
227 RECT rect
= {0, 0, GetWidth(), GetHeight()};
229 InvertRect(hDrawingDC
, &rect
);
230 NotifyImageChanged();
233 void ImageModel::Clear(COLORREF color
)
235 Rectangle(hDrawingDC
, 0 - 1, 0 - 1, GetWidth() + 1, GetHeight() + 1);
236 NotifyImageChanged();
239 HDC
ImageModel::GetDC()
244 void ImageModel::FlipHorizontally()
247 StretchBlt(hDrawingDC
, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
248 GetWidth(), GetHeight(), SRCCOPY
);
249 NotifyImageChanged();
252 void ImageModel::FlipVertically()
255 StretchBlt(hDrawingDC
, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
256 GetWidth(), GetHeight(), SRCCOPY
);
257 NotifyImageChanged();
260 void ImageModel::RotateNTimes90Degrees(int iN
)
266 DeleteObject(hBms
[(currInd
+ 1) % HISTORYSIZE
]);
267 hBms
[(currInd
+ 1) % HISTORYSIZE
] = Rotate90DegreeBlt(hDrawingDC
, GetWidth(), GetHeight(), iN
== 1, FALSE
);
268 currInd
= (currInd
+ 1) % HISTORYSIZE
;
269 if (undoSteps
< HISTORYSIZE
- 1)
272 SelectObject(hDrawingDC
, hBms
[currInd
]);
274 NotifyDimensionsChanged();
278 StretchBlt(hDrawingDC
, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), GetDC(),
279 0, 0, GetWidth(), GetHeight(), SRCCOPY
);
282 NotifyImageChanged();
285 void ImageModel::DeleteSelection()
287 if (!selectionModel
.m_bShow
)
290 selectionModel
.TakeOff();
291 selectionModel
.m_bShow
= FALSE
;
292 selectionModel
.ClearColor();
293 selectionModel
.ClearMask();
294 NotifyImageChanged();
297 void ImageModel::Bound(POINT
& pt
)
299 pt
.x
= max(0, min(pt
.x
, GetWidth()));
300 pt
.y
= max(0, min(pt
.y
, GetHeight()));