[RAPPS]
[reactos.git] / reactos / base / applications / mspaint / history.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/history.cpp
5 * PURPOSE: Undo and redo functionality
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include "precomp.h"
12
13 /* FUNCTIONS ********************************************************/
14
15 void ImageModel::NotifyDimensionsChanged()
16 {
17 imageArea.SendMessage(WM_IMAGEMODELDIMENSIONSCHANGED);
18 }
19
20 void ImageModel::NotifyImageChanged()
21 {
22 imageArea.SendMessage(WM_IMAGEMODELIMAGECHANGED);
23 }
24
25 ImageModel::ImageModel()
26 {
27 currInd = 0;
28 undoSteps = 0;
29 redoSteps = 0;
30 imageSaved = TRUE;
31
32 // prepare a minimal usable bitmap
33 int imgXRes = 1;
34 int imgYRes = 1;
35
36 hDrawingDC = CreateCompatibleDC(NULL);
37 SelectObject(hDrawingDC, CreatePen(PS_SOLID, 0, paletteModel.GetFgColor()));
38 SelectObject(hDrawingDC, CreateSolidBrush(paletteModel.GetBgColor()));
39
40 hBms[0] = CreateDIBWithProperties(imgXRes, imgYRes);
41 SelectObject(hDrawingDC, hBms[0]);
42 Rectangle(hDrawingDC, 0 - 1, 0 - 1, imgXRes + 1, imgYRes + 1);
43 }
44
45 void ImageModel::CopyPrevious()
46 {
47 DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
48 hBms[(currInd + 1) % HISTORYSIZE] = (HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG);
49 currInd = (currInd + 1) % HISTORYSIZE;
50 if (undoSteps < HISTORYSIZE - 1)
51 undoSteps++;
52 redoSteps = 0;
53 SelectObject(hDrawingDC, hBms[currInd]);
54 imageSaved = FALSE;
55 }
56
57 void ImageModel::Undo()
58 {
59 if (undoSteps > 0)
60 {
61 int oldWidth = GetWidth();
62 int oldHeight = GetHeight();
63 selectionWindow.ShowWindow(SW_HIDE);
64 currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE;
65 SelectObject(hDrawingDC, hBms[currInd]);
66 undoSteps--;
67 if (redoSteps < HISTORYSIZE - 1)
68 redoSteps++;
69 if (GetWidth() != oldWidth || GetHeight() != oldHeight)
70 NotifyDimensionsChanged();
71 NotifyImageChanged();
72 }
73 }
74
75 void ImageModel::Redo()
76 {
77 if (redoSteps > 0)
78 {
79 int oldWidth = GetWidth();
80 int oldHeight = GetHeight();
81 selectionWindow.ShowWindow(SW_HIDE);
82 currInd = (currInd + 1) % HISTORYSIZE;
83 SelectObject(hDrawingDC, hBms[currInd]);
84 redoSteps--;
85 if (undoSteps < HISTORYSIZE - 1)
86 undoSteps++;
87 if (GetWidth() != oldWidth || GetHeight() != oldHeight)
88 NotifyDimensionsChanged();
89 NotifyImageChanged();
90 }
91 }
92
93 void ImageModel::ResetToPrevious()
94 {
95 DeleteObject(hBms[currInd]);
96 hBms[currInd] =
97 (HBITMAP) CopyImage(hBms[(currInd + HISTORYSIZE - 1) % HISTORYSIZE], IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG);
98 SelectObject(hDrawingDC, hBms[currInd]);
99 NotifyImageChanged();
100 }
101
102 void ImageModel::ClearHistory()
103 {
104 undoSteps = 0;
105 redoSteps = 0;
106 }
107
108 void ImageModel::Insert(HBITMAP hbm)
109 {
110 int oldWidth = GetWidth();
111 int oldHeight = GetHeight();
112 DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
113 hBms[(currInd + 1) % HISTORYSIZE] = hbm;
114 currInd = (currInd + 1) % HISTORYSIZE;
115 if (undoSteps < HISTORYSIZE - 1)
116 undoSteps++;
117 redoSteps = 0;
118 SelectObject(hDrawingDC, hBms[currInd]);
119 if (GetWidth() != oldWidth || GetHeight() != oldHeight)
120 NotifyDimensionsChanged();
121 NotifyImageChanged();
122 }
123
124 void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
125 {
126 HDC hdc;
127 HPEN oldPen;
128 HBRUSH oldBrush;
129 int oldWidth = GetWidth();
130 int oldHeight = GetHeight();
131
132 SelectObject(hDrawingDC, hBms[currInd]);
133 DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
134 hBms[(currInd + 1) % HISTORYSIZE] = CreateDIBWithProperties(nWidth, nHeight);
135 currInd = (currInd + 1) % HISTORYSIZE;
136 if (undoSteps < HISTORYSIZE - 1)
137 undoSteps++;
138 redoSteps = 0;
139
140 hdc = CreateCompatibleDC(hDrawingDC);
141 SelectObject(hdc, hBms[currInd]);
142
143 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, paletteModel.GetBgColor()));
144 oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(paletteModel.GetBgColor()));
145 Rectangle(hdc, 0, 0, nWidth, nHeight);
146 BitBlt(hdc, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), hDrawingDC, 0, 0, SRCCOPY);
147 DeleteObject(SelectObject(hdc, oldBrush));
148 DeleteObject(SelectObject(hdc, oldPen));
149 DeleteDC(hdc);
150 SelectObject(hDrawingDC, hBms[currInd]);
151
152 if (GetWidth() != oldWidth || GetHeight() != oldHeight)
153 NotifyDimensionsChanged();
154 NotifyImageChanged();
155 }
156
157 void ImageModel::SaveImage(LPTSTR lpFileName)
158 {
159 SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC, &fileTime, &fileSize, fileHPPM, fileVPPM);
160 imageSaved = TRUE;
161 }
162
163 BOOL ImageModel::IsImageSaved()
164 {
165 return imageSaved;
166 }
167
168 BOOL ImageModel::HasUndoSteps()
169 {
170 return undoSteps > 0;
171 }
172
173 BOOL ImageModel::HasRedoSteps()
174 {
175 return redoSteps > 0;
176 }
177
178 void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
179 {
180 int oldWidth = GetWidth();
181 int oldHeight = GetHeight();
182 Insert((HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP,
183 GetWidth() * nStretchPercentX / 100,
184 GetHeight() * nStretchPercentY / 100, 0));
185 if (GetWidth() != oldWidth || GetHeight() != oldHeight)
186 NotifyDimensionsChanged();
187 NotifyImageChanged();
188 }
189
190 int ImageModel::GetWidth()
191 {
192 return GetDIBWidth(hBms[currInd]);
193 }
194
195 int ImageModel::GetHeight()
196 {
197 return GetDIBHeight(hBms[currInd]);
198 }
199
200 void ImageModel::InvertColors()
201 {
202 RECT rect = {0, 0, GetWidth(), GetHeight()};
203 CopyPrevious();
204 InvertRect(hDrawingDC, &rect);
205 NotifyImageChanged();
206 }
207
208 void ImageModel::Clear(COLORREF color)
209 {
210 Rectangle(hDrawingDC, 0 - 1, 0 - 1, GetWidth() + 1, GetHeight() + 1);
211 NotifyImageChanged();
212 }
213
214 HDC ImageModel::GetDC()
215 {
216 return hDrawingDC;
217 }
218
219 void ImageModel::FlipHorizontally()
220 {
221 CopyPrevious();
222 StretchBlt(hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
223 GetWidth(), GetHeight(), SRCCOPY);
224 NotifyImageChanged();
225 }
226
227 void ImageModel::FlipVertically()
228 {
229 CopyPrevious();
230 StretchBlt(hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
231 GetWidth(), GetHeight(), SRCCOPY);
232 NotifyImageChanged();
233 }
234
235 void ImageModel::RotateNTimes90Degrees(int iN)
236 {
237 if (iN == 2)
238 {
239 CopyPrevious();
240 StretchBlt(hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(), GetDC(),
241 0, 0, GetWidth(), GetHeight(), SRCCOPY);
242 }
243 NotifyImageChanged();
244 }