File: | home/HaikuArchives/ArtPaint/artpaint/viewmanipulators/CropManipulator.cpp |
Warning: | line 402, column 2 Potential leak of memory pointed to by 'settings' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright 2003, Heikki Suhonen | |||
3 | * Copyright 2009, Karsten Heimrich | |||
4 | * Distributed under the terms of the MIT License. | |||
5 | * | |||
6 | * Authors: | |||
7 | * Heikki Suhonen <heikki.suhonen@gmail.com> | |||
8 | * Karsten Heimrich <host.haiku@gmx.de> | |||
9 | * Dale Cieslak <dcieslak@yahoo.com> | |||
10 | * | |||
11 | */ | |||
12 | ||||
13 | #include "CropManipulator.h" | |||
14 | ||||
15 | #include "MessageConstants.h" | |||
16 | #include "NumberControl.h" | |||
17 | ||||
18 | ||||
19 | #include <Bitmap.h> | |||
20 | #include <Catalog.h> | |||
21 | #include <GroupLayout.h> | |||
22 | #include <GroupLayoutBuilder.h> | |||
23 | #include <StatusBar.h> | |||
24 | #include <Window.h> | |||
25 | ||||
26 | ||||
27 | #include <new> | |||
28 | ||||
29 | ||||
30 | #undef B_TRANSLATION_CONTEXT"Manipulators" | |||
31 | #define B_TRANSLATION_CONTEXT"Manipulators" "Manipulators" | |||
32 | ||||
33 | ||||
34 | using ArtPaint::Interface::NumberControl; | |||
35 | ||||
36 | ||||
37 | CropManipulator::CropManipulator(BBitmap *bm) | |||
38 | : WindowGUIManipulator() | |||
39 | { | |||
40 | settings = new CropManipulatorSettings(); | |||
41 | config_view = NULL__null; | |||
42 | ||||
43 | min_x = 0; | |||
44 | max_x = 0; | |||
45 | min_y = 0; | |||
46 | max_y = 0; | |||
47 | ||||
48 | if (bm != NULL__null) { | |||
49 | BRect rect = bm->Bounds(); | |||
50 | settings->left = min_x = rect.left; | |||
51 | settings->right = max_x = rect.right; | |||
52 | settings->top = min_y = rect.top; | |||
53 | settings->bottom = max_y = rect.bottom; | |||
54 | } | |||
55 | } | |||
56 | ||||
57 | ||||
58 | ||||
59 | CropManipulator::~CropManipulator() | |||
60 | { | |||
61 | if (config_view != NULL__null) { | |||
62 | config_view->RemoveSelf(); | |||
63 | delete config_view; | |||
64 | } | |||
65 | ||||
66 | delete settings; | |||
67 | } | |||
68 | ||||
69 | ||||
70 | void CropManipulator::MouseDown(BPoint point,uint32,BView*,bool first) | |||
71 | { | |||
72 | previous_left = settings->left; | |||
73 | previous_right = settings->right; | |||
74 | previous_top = settings->top; | |||
75 | previous_bottom = settings->bottom; | |||
76 | ||||
77 | point.x = floor(point.x); | |||
78 | point.y = floor(point.y); | |||
79 | ||||
80 | if (first == TRUE1) { | |||
81 | // Here we select which grabbles to move | |||
82 | move_left = move_right = move_top = move_bottom = FALSE0; | |||
83 | if (fabs(point.x - settings->left) < 50) | |||
84 | if (fabs(point.x-settings->left)<fabs(point.x-(settings->left+(settings->right-settings->left)/2))) | |||
85 | move_left = TRUE1; | |||
86 | if (fabs(point.x - settings->right) < 50) | |||
87 | if (fabs(point.x-settings->right)<fabs(point.x-(settings->left+(settings->right-settings->left)/2))) | |||
88 | move_right = TRUE1; | |||
89 | if ((move_left == TRUE1) && (move_right == TRUE1)) { | |||
90 | if (fabs(point.x - settings->left) > fabs(point.x - settings->right)) | |||
91 | move_left = FALSE0; | |||
92 | else | |||
93 | move_right = FALSE0; | |||
94 | } | |||
95 | ||||
96 | if (fabs(point.y - settings->top) < 50) | |||
97 | if (fabs(point.y-settings->top)<fabs(point.y-(settings->top+(settings->bottom-settings->top)/2))) | |||
98 | move_top = TRUE1; | |||
99 | if (fabs(point.y - settings->bottom) < 50) | |||
100 | if (fabs(point.y-settings->bottom)<fabs(point.y-(settings->top+(settings->bottom-settings->top)/2))) | |||
101 | move_bottom = TRUE1; | |||
102 | if ((move_top == TRUE1) && (move_bottom == TRUE1)) { | |||
103 | if (fabs(point.y - settings->top) > fabs(point.y - settings->bottom)) | |||
104 | move_top = FALSE0; | |||
105 | else | |||
106 | move_bottom = FALSE0; | |||
107 | } | |||
108 | ||||
109 | ||||
110 | if ((move_left == FALSE0) && (move_top == FALSE0) && (move_right == FALSE0) && (move_bottom == FALSE0)) | |||
111 | move_all = TRUE1; | |||
112 | else | |||
113 | move_all = FALSE0; | |||
114 | ||||
115 | ||||
116 | } | |||
117 | else { | |||
118 | if (move_left == TRUE1) | |||
119 | settings->left = min_c(point.x,settings->right)((point.x)>(settings->right)?(settings->right):(point .x)); | |||
120 | if (move_right == TRUE1) | |||
121 | settings->right = max_c(settings->left,point.x)((settings->left)>(point.x)?(settings->left):(point. x)); | |||
122 | ||||
123 | if (move_top == TRUE1) | |||
124 | settings->top = min_c(point.y,settings->bottom)((point.y)>(settings->bottom)?(settings->bottom):(point .y)); | |||
125 | if (move_bottom == TRUE1) | |||
126 | settings->bottom = max_c(settings->top,point.y)((settings->top)>(point.y)?(settings->top):(point.y) ); | |||
127 | ||||
128 | ||||
129 | if (move_all == TRUE1) { | |||
130 | float width = settings->right - settings->left; | |||
131 | float height = settings->bottom - settings->top; | |||
132 | ||||
133 | float new_left,new_top,new_right,new_bottom; | |||
134 | ||||
135 | new_left = point.x-width/2; | |||
136 | new_right = new_left + width; | |||
137 | new_top = point.y-height/2; | |||
138 | new_bottom = new_top + height; | |||
139 | ||||
140 | settings->left = new_left; | |||
141 | settings->top = new_top; | |||
142 | settings->right = new_right; | |||
143 | settings->bottom = new_bottom; | |||
144 | ||||
145 | } | |||
146 | } | |||
147 | ||||
148 | if ((previous_left != settings->left) || (previous_right != settings->right) || | |||
149 | (previous_top != settings->top) || (previous_bottom != settings->bottom)) | |||
150 | if (config_view != NULL__null) | |||
151 | config_view->SetValues(settings->left,settings->right,settings->top,settings->bottom); | |||
152 | } | |||
153 | ||||
154 | ||||
155 | BRegion CropManipulator::Draw(BView *view,float mag_scale) | |||
156 | { | |||
157 | int32 DRAGGER_SIZE = 5; | |||
158 | // Draw all the data that needs to be drawn | |||
159 | BRect bounds = BRect(mag_scale*settings->left,mag_scale*settings->top,mag_scale*(settings->right+1)-1,mag_scale*(settings->bottom+1)-1); | |||
160 | bounds.left = floor(bounds.left); | |||
161 | bounds.top = floor(bounds.top); | |||
162 | bounds.right = ceil(bounds.right); | |||
163 | bounds.bottom = ceil(bounds.bottom); | |||
164 | ||||
165 | bool draw_draggers = FALSE0; | |||
166 | BRect dragger_rect = BRect(0,0,DRAGGER_SIZE-1,DRAGGER_SIZE-1); | |||
167 | float f_bottom = bounds.bottom; | |||
168 | float f_top = bounds.top; | |||
169 | float f_left = bounds.left; | |||
170 | float f_right = bounds.right; | |||
171 | ||||
172 | if ( (f_bottom-f_top> 3*DRAGGER_SIZE+10) && (f_right-f_left > 3*DRAGGER_SIZE+10) ) { | |||
173 | draw_draggers = TRUE1; | |||
174 | } | |||
175 | view->StrokeRect(bounds,B_MIXED_COLORS); | |||
176 | if (draw_draggers == TRUE1) { | |||
177 | dragger_rect.OffsetTo(bounds.LeftTop()); | |||
178 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
179 | ||||
180 | dragger_rect.OffsetTo(bounds.LeftTop()+BPoint((f_right-f_left)/2-DRAGGER_SIZE/2,0)); | |||
181 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
182 | ||||
183 | dragger_rect.OffsetTo(bounds.LeftTop()+BPoint(f_right-f_left-DRAGGER_SIZE+1,0)); | |||
184 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
185 | ||||
186 | dragger_rect.OffsetTo(bounds.LeftTop()+BPoint(0,(f_bottom-f_top)/2-DRAGGER_SIZE/2)); | |||
187 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
188 | ||||
189 | dragger_rect.OffsetTo(bounds.RightTop()+BPoint(-DRAGGER_SIZE+1,(f_bottom-f_top)/2-DRAGGER_SIZE/2)); | |||
190 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
191 | ||||
192 | dragger_rect.OffsetTo(bounds.LeftBottom()+BPoint(0,-DRAGGER_SIZE+1)); | |||
193 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
194 | ||||
195 | dragger_rect.OffsetTo(bounds.LeftBottom()+BPoint((f_right-f_left)/2-DRAGGER_SIZE/2,-DRAGGER_SIZE+1)); | |||
196 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
197 | ||||
198 | dragger_rect.OffsetTo(bounds.LeftBottom()+BPoint(f_right-f_left-DRAGGER_SIZE+1,-DRAGGER_SIZE+1)); | |||
199 | view->FillRect(dragger_rect,B_MIXED_COLORS); | |||
200 | } | |||
201 | ||||
202 | BRegion updated_region; | |||
203 | ||||
204 | bounds.InsetBy(-1,-1); | |||
205 | updated_region.Set(bounds); | |||
206 | bounds.InsetBy(DRAGGER_SIZE+2,DRAGGER_SIZE+2); | |||
207 | updated_region.Exclude(bounds); | |||
208 | ||||
209 | return updated_region; | |||
210 | } | |||
211 | ||||
212 | ||||
213 | ||||
214 | BBitmap* CropManipulator::ManipulateBitmap(ManipulatorSettings *set, | |||
215 | BBitmap *original, Selection*, BStatusBar *status_bar) | |||
216 | { | |||
217 | CropManipulatorSettings* new_settings = | |||
218 | dynamic_cast<CropManipulatorSettings*> (set); | |||
219 | ||||
220 | if (new_settings == NULL__null) | |||
221 | return NULL__null; | |||
222 | ||||
223 | float left = new_settings->left; | |||
224 | float right = new_settings->right; | |||
225 | float top = new_settings->top; | |||
226 | float bottom = new_settings->bottom; | |||
227 | ||||
228 | if ( ((right-left) == original->Bounds().Width()) && ((bottom-top) == original->Bounds().Height())) | |||
229 | return NULL__null; | |||
230 | ||||
231 | // Create a new bitmap here and copy the appropriate part from original. | |||
232 | // Return the new bitmap. | |||
233 | BBitmap *new_bitmap; | |||
234 | new_bitmap = new BBitmap(BRect(0,0,right-left,bottom-top),B_RGB_32_BIT); | |||
235 | if (new_bitmap->IsValid() == FALSE0) | |||
236 | throw std::bad_alloc(); | |||
237 | ||||
238 | uint32 *orig_bits = (uint32*)original->Bits(); | |||
239 | uint32 *new_bits = (uint32*)new_bitmap->Bits(); | |||
240 | int32 original_bpr = original->BytesPerRow()/4; | |||
241 | float height = bottom-top+1; | |||
242 | BMessage progress_message = BMessage(B_UPDATE_STATUS_BAR); | |||
243 | progress_message.AddFloat("delta",0.0); | |||
244 | ||||
245 | union { | |||
246 | uint8 bytes[4]; | |||
247 | uint32 word; | |||
248 | } background; | |||
249 | ||||
250 | background.bytes[0] = 0xFF; | |||
251 | background.bytes[1] = 0xFF; | |||
252 | background.bytes[2] = 0xFF; | |||
253 | background.bytes[3] = 0x00; | |||
254 | ||||
255 | for (int32 y=(int32)top;y<=bottom;y++) { | |||
256 | for (int32 x=(int32)left;x<=right;x++) { | |||
257 | if ((x>=0) && (y>=0) && (x<=original->Bounds().right) && (y<=original->Bounds().bottom)) | |||
258 | *new_bits++ = *(orig_bits + x +y*original_bpr); | |||
259 | else | |||
260 | *new_bits++ = background.word; | |||
261 | } | |||
262 | if ((y%10 == 0) && (status_bar != NULL__null)) { | |||
263 | progress_message.ReplaceFloat("delta",(100.0)/height*10.0); | |||
264 | status_bar->Window()->PostMessage(&progress_message,status_bar); | |||
265 | } | |||
266 | } | |||
267 | ||||
268 | return new_bitmap; | |||
269 | } | |||
270 | ||||
271 | int32 CropManipulator::PreviewBitmap(Selection*,bool,BRegion*) | |||
272 | { | |||
273 | if ((previous_left == settings->left) && (previous_right == settings->right) && | |||
274 | (previous_top == settings->top) && (previous_bottom == settings->bottom)) | |||
275 | return DRAW_NOTHING; | |||
276 | else | |||
277 | return DRAW_ONLY_GUI; | |||
278 | } | |||
279 | ||||
280 | void CropManipulator::SetPreviewBitmap(BBitmap *bm) | |||
281 | { | |||
282 | if (bm != NULL__null) { | |||
283 | BRect rect = bm->Bounds(); | |||
284 | settings->left = min_x = rect.left; | |||
285 | settings->right = max_x = rect.right; | |||
286 | settings->top = min_y = rect.top; | |||
287 | settings->bottom = max_y = rect.bottom; | |||
288 | } | |||
289 | else { | |||
290 | settings->left = min_x = 0; | |||
291 | settings->right = max_x = 0; | |||
292 | settings->top = min_y = 0; | |||
293 | settings->bottom = max_y = 0; | |||
294 | } | |||
295 | ||||
296 | if (config_view != NULL__null) { | |||
297 | config_view->SetValues(settings->left,settings->right,settings->top,settings->bottom); | |||
298 | } | |||
299 | } | |||
300 | ||||
301 | void CropManipulator::SetValues(float x1, float x2, float y1, float y2) | |||
302 | { | |||
303 | previous_left = settings->left; | |||
304 | previous_right = settings->right; | |||
305 | previous_top = settings->top; | |||
306 | previous_bottom = settings->bottom; | |||
307 | ||||
308 | settings->left = x1; | |||
309 | settings->right = x2; | |||
310 | settings->top = y1; | |||
311 | settings->bottom = y2; | |||
312 | ||||
313 | settings->left = min_c(settings->left,settings->right)((settings->left)>(settings->right)?(settings->right ):(settings->left)); | |||
314 | settings->right = max_c(settings->left,settings->right)((settings->left)>(settings->right)?(settings->left ):(settings->right)); | |||
315 | ||||
316 | settings->top = min_c(settings->top,settings->bottom)((settings->top)>(settings->bottom)?(settings->bottom ):(settings->top)); | |||
317 | settings->bottom = max_c(settings->top,settings->bottom)((settings->top)>(settings->bottom)?(settings->top ):(settings->bottom)); | |||
318 | ||||
319 | if (config_view != NULL__null) { | |||
320 | config_view->SetValues(settings->left,settings->right,settings->top,settings->bottom); | |||
321 | } | |||
322 | } | |||
323 | ||||
324 | ||||
325 | ManipulatorSettings* | |||
326 | CropManipulator::ReturnSettings() | |||
327 | { | |||
328 | return new CropManipulatorSettings(settings); | |||
329 | } | |||
330 | ||||
331 | ||||
332 | BView* | |||
333 | CropManipulator::MakeConfigurationView(const BMessenger& target) | |||
334 | { | |||
335 | config_view = new CropManipulatorView(this, target); | |||
| ||||
336 | config_view->SetValues(settings->left, settings->right, settings->top, | |||
337 | settings->bottom); | |||
338 | return config_view; | |||
339 | } | |||
340 | ||||
341 | ||||
342 | const char* | |||
343 | CropManipulator::ReturnName() | |||
344 | { | |||
345 | return B_TRANSLATE("Crop" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Crop" "\xE2\x80\xA6"), "Manipulators"); | |||
346 | } | |||
347 | ||||
348 | ||||
349 | const char* | |||
350 | CropManipulator::ReturnHelpString() | |||
351 | { | |||
352 | return B_TRANSLATE("Use the handles or number-fields to set the new borders.")BLocaleRoster::Default()->GetCatalog()->GetString(("Use the handles or number-fields to set the new borders." ), "Manipulators"); | |||
353 | } | |||
354 | ||||
355 | ||||
356 | // #pragma mark -- CropManipulatorView | |||
357 | ||||
358 | ||||
359 | CropManipulatorView::CropManipulatorView(CropManipulator* manipulator, | |||
360 | const BMessenger& target) | |||
361 | : WindowGUIManipulatorView() | |||
362 | , fTarget(target) | |||
363 | , fManipulator(manipulator) | |||
364 | { | |||
365 | fTopCrop = new NumberControl(B_TRANSLATE("Top:")BLocaleRoster::Default()->GetCatalog()->GetString(("Top:" ), "Manipulators"), "", | |||
366 | new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5, true); | |||
367 | fLeftCrop = new NumberControl(B_TRANSLATE("Left:")BLocaleRoster::Default()->GetCatalog()->GetString(("Left:" ), "Manipulators"), "", | |||
368 | new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5, true); | |||
369 | fRightCrop = new NumberControl(B_TRANSLATE("Right:")BLocaleRoster::Default()->GetCatalog()->GetString(("Right:" ), "Manipulators"), | |||
370 | "", new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5); | |||
371 | fBottomCrop = new NumberControl(B_TRANSLATE("Bottom:")BLocaleRoster::Default()->GetCatalog()->GetString(("Bottom:" ), "Manipulators"), | |||
372 | "", new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5); | |||
373 | ||||
374 | SetLayout(new BGroupLayout(B_HORIZONTAL)); | |||
375 | AddChild(BGroupLayoutBuilder(B_VERTICAL, 5.0) | |||
376 | .AddGroup(B_HORIZONTAL) | |||
377 | .AddGlue() | |||
378 | .Add(fTopCrop) | |||
379 | .AddGlue() | |||
380 | .End() | |||
381 | .AddGroup(B_HORIZONTAL) | |||
382 | .AddGlue() | |||
383 | .Add(fLeftCrop) | |||
384 | .AddGlue() | |||
385 | .AddStrut(80.0) | |||
386 | .AddGlue() | |||
387 | .Add(fRightCrop) | |||
388 | .AddGlue() | |||
389 | .End() | |||
390 | .AddGroup(B_HORIZONTAL) | |||
391 | .AddGlue() | |||
392 | .Add(fBottomCrop) | |||
393 | .AddGlue() | |||
394 | .End() | |||
395 | ); | |||
396 | ||||
397 | CropManipulatorSettings* settings | |||
398 | = (CropManipulatorSettings*)manipulator->ReturnSettings(); | |||
399 | fTopCrop->SetValue(settings->top); | |||
400 | fLeftCrop->SetValue(settings->left); | |||
401 | fRightCrop->SetValue(settings->right); | |||
402 | fBottomCrop->SetValue(settings->bottom); | |||
| ||||
403 | } | |||
404 | ||||
405 | ||||
406 | void | |||
407 | CropManipulatorView::AttachedToWindow() | |||
408 | { | |||
409 | fTopCrop->SetTarget(this); | |||
410 | fTopCrop->MakeFocus(true); | |||
411 | ||||
412 | fLeftCrop->SetTarget(this); | |||
413 | fRightCrop->SetTarget(this); | |||
414 | fBottomCrop->SetTarget(this); | |||
415 | ||||
416 | WindowGUIManipulatorView::AttachedToWindow(); | |||
417 | } | |||
418 | ||||
419 | ||||
420 | void | |||
421 | CropManipulatorView::SetValues(float x1, float x2, float y1, float y2) | |||
422 | { | |||
423 | BWindow* window = Window(); | |||
424 | if (window && window->Lock()) { | |||
425 | left = x1; | |||
426 | right = x2; | |||
427 | top = y1; | |||
428 | bottom = y2; | |||
429 | ||||
430 | if (left != fLeftCrop->Value()) | |||
431 | fLeftCrop->SetValue(int32(left)); | |||
432 | ||||
433 | if (right != fRightCrop->Value()) | |||
434 | fRightCrop->SetValue(int32(right)); | |||
435 | ||||
436 | if (top != fTopCrop->Value()) | |||
437 | fTopCrop->SetValue(int32(top)); | |||
438 | ||||
439 | if (bottom != fBottomCrop->Value()) | |||
440 | fBottomCrop->SetValue(int32(bottom)); | |||
441 | ||||
442 | window->Unlock(); | |||
443 | } | |||
444 | } | |||
445 | ||||
446 | ||||
447 | void | |||
448 | CropManipulatorView::MessageReceived(BMessage *message) | |||
449 | { | |||
450 | switch (message->what) { | |||
451 | case HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi': { | |||
452 | fManipulator->SetValues(fLeftCrop->Value(), | |||
453 | fRightCrop->Value(), fTopCrop->Value(), | |||
454 | fBottomCrop->Value()); | |||
455 | fTarget.SendMessage(message); | |||
456 | } break; | |||
457 | ||||
458 | default: { | |||
459 | WindowGUIManipulatorView::MessageReceived(message); | |||
460 | } break; | |||
461 | } | |||
462 | } |