Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/viewmanipulators/RotationManipulator.cpp
Warning:line 285, column 11
Although the value stored to 'green' is used in the enclosing expression, the value is never actually read from 'green'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-haiku -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name RotationManipulator.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /boot/system/lib/clang/12.0.1 -iquote ./ -iquote artpaint/ -iquote artpaint/Utilities/ -iquote artpaint/application/ -iquote artpaint/controls/ -iquote artpaint/layers/ -iquote artpaint/paintwindow/ -iquote artpaint/tools/ -iquote artpaint/viewmanipulators/ -iquote artpaint/windows/ -iquote objects_artpaint/ -isystem /boot/system/develop/headers/private/interface -internal-isystem /system/develop/headers/c++ -internal-isystem /system/develop/headers/c++/x86_64-unknown-haiku -internal-isystem /system/develop/headers/c++/backward -O3 -fdeprecated-macro -fdebug-compilation-dir /boot/home/HaikuArchives/ArtPaint -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2022-06-19-103017-1294-1 -x c++ artpaint/viewmanipulators/RotationManipulator.cpp
1/*
2 * Copyright 2003, Heikki Suhonen
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Heikki Suhonen <heikki.suhonen@gmail.com>
7 * Dale Cieslak <dcieslak@yahoo.com>
8 *
9 */
10
11#include "HSPolygon.h"
12#include "ImageView.h"
13#include "MessageConstants.h"
14#include "PixelOperations.h"
15#include "RotationManipulator.h"
16#include "Selection.h"
17
18
19#include <Catalog.h>
20#include <ClassInfo.h>
21#include <LayoutBuilder.h>
22#include <StatusBar.h>
23#include <TextControl.h>
24#include <Window.h>
25
26
27#include <ctype.h>
28#include <math.h>
29#include <new>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34
35#undef B_TRANSLATION_CONTEXT"Manipulators"
36#define B_TRANSLATION_CONTEXT"Manipulators" "Manipulators"
37
38
39#define PI3.14159265358979323846 M_PI3.14159265358979323846
40
41
42RotationManipulator::RotationManipulator(BBitmap *bitmap)
43 : WindowGUIManipulator()
44{
45 settings = new RotationManipulatorSettings();
46 config_view = NULL__null;
47 preview_bitmap = NULL__null;
48 copy_of_the_preview_bitmap = NULL__null;
49
50 SetPreviewBitmap(bitmap);
51
52 last_calculated_resolution = 0;
53
54 BPoint poly_points[8];
55 poly_points[0] = BPoint(-5,0);
56 poly_points[1] = BPoint(0,0);
57 poly_points[2] = BPoint(0,-5);
58 poly_points[3] = BPoint(0,0);
59 poly_points[4] = BPoint(5,0);
60 poly_points[5] = BPoint(0,0);
61 poly_points[6] = BPoint(0,5);
62 poly_points[7] = BPoint(0,0);
63
64 view_polygon = new HSPolygon(poly_points,8);
65}
66
67
68
69RotationManipulator::~RotationManipulator()
70{
71 delete copy_of_the_preview_bitmap;
72 delete view_polygon;
73
74 if (config_view != NULL__null) {
75 config_view->RemoveSelf();
76 delete config_view;
77 }
78}
79
80
81void RotationManipulator::SetPreviewBitmap(BBitmap *bitmap)
82{
83 if (config_view != NULL__null) {
84 config_view->SetAngle(0.0);
85 }
86
87 if ((bitmap == NULL__null) || (preview_bitmap == NULL__null) || (bitmap->Bounds() != preview_bitmap->Bounds())) {
88 try {
89 if (preview_bitmap != NULL__null) {
90 delete copy_of_the_preview_bitmap;
91 }
92 if (bitmap != NULL__null) {
93 preview_bitmap = bitmap;
94 copy_of_the_preview_bitmap = DuplicateBitmap(preview_bitmap);
95 BRect bounds = preview_bitmap->Bounds();
96 settings->origo = BPoint((bounds.right-bounds.left)/2+bounds.left,(bounds.bottom-bounds.top)/2+bounds.top);
97 }
98 else {
99 preview_bitmap = NULL__null;
100 copy_of_the_preview_bitmap = NULL__null;
101 }
102 }
103 catch (std::bad_alloc e) {
104 preview_bitmap = NULL__null;
105 copy_of_the_preview_bitmap=NULL__null;
106 throw e;
107 }
108 }
109 else {
110 // Just update the copy_of_the_preview_bitmap
111 preview_bitmap = bitmap;
112 uint32 *source = (uint32*)preview_bitmap->Bits();
113 uint32 *target = (uint32*)copy_of_the_preview_bitmap->Bits();
114 int32 bitslength = min_c(preview_bitmap->BitsLength(),copy_of_the_preview_bitmap->BitsLength())((preview_bitmap->BitsLength())>(copy_of_the_preview_bitmap
->BitsLength())?(copy_of_the_preview_bitmap->BitsLength
()):(preview_bitmap->BitsLength()))
;
115 memcpy(target,source,bitslength);
116 }
117
118 if (preview_bitmap != NULL__null) {
119 double speed = GetSystemClockSpeed() / 15000;
120
121 BRect bounds = preview_bitmap->Bounds();
122 float num_pixels = (bounds.Width()+1) * (bounds.Height() + 1);
123 lowest_available_quality = 1;
124 while ((2*num_pixels/lowest_available_quality/lowest_available_quality) > speed)
125 lowest_available_quality *= 2;
126
127 highest_available_quality = max_c(lowest_available_quality/2,1)((lowest_available_quality/2)>(1)?(lowest_available_quality
/2):(1))
;
128 }
129 else {
130 lowest_available_quality = 1;
131 highest_available_quality = 1;
132 }
133 last_calculated_resolution = lowest_available_quality;
134}
135
136
137BRegion RotationManipulator::Draw(BView *view,float mag_scale)
138{
139 float x = settings->origo.x;
140 float y = settings->origo.y;
141
142 view->StrokeLine(BPoint(mag_scale*x-10,mag_scale*y),BPoint(mag_scale*x+10,mag_scale*y),B_MIXED_COLORS);
143 view->StrokeLine(BPoint(mag_scale*x,mag_scale*y-10),BPoint(mag_scale*x,mag_scale*y+10),B_MIXED_COLORS);
144 view->StrokeEllipse(BRect(BPoint(mag_scale*x-5,mag_scale*y-5),BPoint(mag_scale*x+5,mag_scale*y+5)),B_MIXED_COLORS);
145
146 BRegion updated_region;
147 updated_region.Set(BRect(mag_scale*x-10,mag_scale*y-10,mag_scale*x+10,mag_scale*y+10));
148 return updated_region;
149}
150
151
152void RotationManipulator::MouseDown(BPoint point,uint32 buttons,BView*,bool first_click)
153{
154 if (first_click == TRUE1) {
155 if (!(buttons & B_PRIMARY_MOUSE_BUTTON) || ((fabs(point.x-settings->origo.x)<10) && (fabs(point.y-settings->origo.y)<10)))
156 move_origo = TRUE1;
157 else
158 move_origo = FALSE0;
159 }
160
161 if (!move_origo) {
162 // Here we calculate the new angle
163 previous_angle = settings->angle;
164 float new_angle;
165
166 float dy = point.y - settings->origo.y;
167 float dx = point.x - settings->origo.x;
168 new_angle = atan2(dy,dx);
169 new_angle = new_angle / PI3.14159265358979323846 *180;
170 if (first_click == TRUE1) {
171 starting_angle = new_angle;
172 }
173 else {
174 settings->angle += new_angle - starting_angle;
175 starting_angle = new_angle;
176 if ((config_view != NULL__null) && (new_angle != previous_angle)) {
177 config_view->SetAngle(settings->angle);
178 }
179 }
180 }
181 else {
182 // Set the new origo for rotation and reset the angle.
183 previous_angle = settings->angle;
184 settings->angle = 0;
185
186 settings->origo = point;
187 }
188}
189
190
191BBitmap* RotationManipulator::ManipulateBitmap(ManipulatorSettings *set,BBitmap *original,Selection *selection,BStatusBar *status_bar)
192{
193 // Here move the contents of the original-bitmap to the new_bitmap,
194 // rotated by s->angle around s->origin.
195 RotationManipulatorSettings *new_settings = cast_as(set,RotationManipulatorSettings)(dynamic_cast<RotationManipulatorSettings*>(set));
196 if (new_settings == NULL__null)
197 return NULL__null;
198
199 if (original == NULL__null)
200 return NULL__null;
201
202 if (new_settings->angle == 0)
203 return NULL__null;
204
205 BBitmap *new_bitmap;
206 if (original != preview_bitmap) {
207 original->Lock();
208 BRect bitmap_frame = original->Bounds();
209 new_bitmap = new BBitmap(bitmap_frame,B_RGB32);
210 original->Unlock();
211 if (new_bitmap->IsValid() == FALSE0)
212 throw std::bad_alloc();
213 }
214 else {
215 new_bitmap = original;
216 original = copy_of_the_preview_bitmap;
217 }
218
219 // We should calculate the new pixel value as weighted average from the
220 // four pixels that will be under the inverse-rotated pixel.
221 //
222 // X X When inverse rotated from new bitmap,
223 // X X the pixel will cover four pixels, each
224 // with a different weight.
225 //
226 BPoint center = new_settings->origo;
227
228 float the_angle = new_settings->angle;
229 float sin_angle = sin(-the_angle/360*2*PI3.14159265358979323846);
230 float cos_angle = cos(-the_angle/360*2*PI3.14159265358979323846);
231
232 int32 *target_bits = (int32*)new_bitmap->Bits();
233 int32 *source_bits = (int32*)original->Bits();
234 int32 source_bpr = original->BytesPerRow()/4;
235 int32 target_bpr = new_bitmap->BytesPerRow()/4;
236
237 // copy the points according to angle
238 float height = new_bitmap->Bounds().Height();
239 float width = new_bitmap->Bounds().Width();
240 float left = original->Bounds().left;
241 float right = original->Bounds().right;
242 float top = original->Bounds().top;
243 float bottom = original->Bounds().bottom;
244 float center_x = center.x;
245 float center_y = center.y;
246 float source_x,source_y;
247 float y_times_sin = (-center_y)*sin_angle;
248 float y_times_cos = (-center_y)*cos_angle;
249
250 BWindow *status_bar_window = status_bar->Window();
251
252 float red,green,blue,alpha; // before optimization was int32
253
254 float floor_x,ceil_x,floor_y,ceil_y; // was int32 before optimization
255
256 uint32 p1,p2,p3,p4;
257
258 union {
259 uint8 bytes[4];
260 uint32 word;
261 } background;
262 // Transparent background.
263 background.bytes[0] = 0xFF;
264 background.bytes[1] = 0xFF;
265 background.bytes[2] = 0xFF;
266 background.bytes[3] = 0x00;
267
268 if (selection->IsEmpty()) {
269 for (float y=0;y<=height;y++) {
270 float x_times_sin = (-center_x)*sin_angle;
271 float x_times_cos = (-center_x)*cos_angle;
272 for (float x=0;x<=width;x++) {
273 // rotate here around the origin
274 source_x = x_times_cos - y_times_sin;
275 source_y = x_times_sin + y_times_cos;
276 // translate back to correct position
277 source_x += center_x;
278 source_y += center_y;
279
280 floor_x = floor(source_x);
281 ceil_x = floor_x + 1;
282 floor_y = floor(source_y);
283 ceil_y = floor_y + 1;
284
285 red = green = blue = alpha = 0;
Although the value stored to 'green' is used in the enclosing expression, the value is never actually read from 'green'
286
287 float u = source_x - floor_x;
288 float v = source_y - floor_y;
289 // Then add the weighted sums of the four pixels.
290 if (( floor_x <= right) && (floor_y <= bottom)
291 && (floor_x>=left) && (floor_y>=top)) {
292 p1 = *(source_bits + (int32)floor_x + (int32)floor_y*source_bpr);
293 }
294 else {
295 p1 = background.word;
296 }
297
298 if (( ceil_x <= right) && (floor_y <= bottom)
299 && (ceil_x>=left) && (floor_y>=top)) {
300 p2 = *(source_bits + (int32)ceil_x + (int32)floor_y*source_bpr);
301 }
302 else {
303 p2 = background.word;
304 }
305
306 if (( floor_x <= right) && (ceil_y <= bottom)
307 && (floor_x>=left) && (ceil_y>=top)) {
308 p3 = *(source_bits + (int32)floor_x + (int32)ceil_y*source_bpr);
309 }
310 else {
311 p3 = background.word;
312 }
313
314 if (( ceil_x <= right) && (ceil_y <= bottom)
315 && (ceil_x>=left) && (ceil_y>=top)) {
316 p4 = *(source_bits + (int32)ceil_x + (int32)ceil_y*source_bpr);
317 }
318 else {
319 p4 = background.word;
320 }
321
322 *target_bits++ = bilinear_interpolation(p1,p2,p3,p4,u,v);
323 x_times_sin += sin_angle;
324 x_times_cos += cos_angle;
325 }
326 y_times_sin += sin_angle;
327 y_times_cos += cos_angle;
328 if ((((int32)y % 20) == 0) && (status_bar != NULL__null) && (status_bar_window != NULL__null)) {
329 status_bar_window->Lock();
330 status_bar->Update(100.0/(float)height*20);
331 status_bar_window->Unlock();
332 }
333 }
334 }
335 else {
336 // This should be done by first rotating the selection and then looking up what pixels
337 // of original image correspond to the pixels in the rotated selection. The only problem
338 // with this approach is if we want to clear the selection first so we must clear it before
339 // rotating the selection.
340// selection->Recalculate();
341 for (int32 y=0;y<=height;y++) {
342 for (int32 x=0;x<=width;x++) {
343 if (selection->ContainsPoint(x,y))
344 *(target_bits + x + y*target_bpr) = background.word;
345 else
346 *(target_bits + x + y*target_bpr) = *(source_bits + x + y*source_bpr);
347 }
348 }
349
350
351 // We must make a copy of the selection in order to be able to rotate it
352// Selection *new_selection = new Selection(selection);
353// new_selection->RotateTo(new_settings->origo,new_settings->angle);
354// new_selection->Recalculate();
355 selection->Recalculate();
356
357 BRect selection_bounds = selection->GetBoundingRect();
358 selection_bounds.PrintToStream();
359 int32 sel_top = (int32)selection_bounds.top;
360 int32 sel_bottom = (int32)selection_bounds.bottom;
361 int32 sel_left = (int32)selection_bounds.left;
362 int32 sel_right = (int32)selection_bounds.right;
363 y_times_sin = (sel_top-center_y)*sin_angle;
364 y_times_cos = (sel_top-center_y)*cos_angle;
365 for (float y=sel_top;y<=sel_bottom;y++) {
366 float x_times_sin = (sel_left-center_x)*sin_angle;
367 float x_times_cos = (sel_left-center_x)*cos_angle;
368 for (float x=sel_left;x<=sel_right;x++) {
369 if (selection->ContainsPoint(int32(x), int32(y))) {
370 // rotate here around the origin
371 source_x = x_times_cos - y_times_sin;
372 source_y = x_times_sin + y_times_cos;
373 // translate back to correct position
374 source_x += center_x;
375 source_y += center_y;
376
377 floor_x = floor(source_x);
378 ceil_x = floor_x + 1;
379 floor_y = floor(source_y);
380 ceil_y = floor_y + 1;
381
382 red = green = blue = alpha = 0;
383
384 float u = source_x - floor_x;
385 float v = source_y - floor_y;
386 // Then add the weighted sums of the four pixels.
387 if (( floor_x <= right) && (floor_y <= bottom)
388 && (floor_x>=left) && (floor_y>=top) ) {
389 p1 = *(source_bits + (int32)floor_x + (int32)floor_y*source_bpr);
390 }
391 else {
392 p1 = background.word;
393 }
394
395 // second
396 if (( ceil_x <= right) && (floor_y <= bottom)
397 && (ceil_x>=left) && (floor_y>=top) ) {
398 p2 = *(source_bits + (int32)ceil_x + (int32)floor_y*source_bpr);
399 }
400 else {
401 p2 = background.word;
402 }
403
404 // third
405 if (( floor_x <= right) && (ceil_y <= bottom)
406 && (floor_x>=left) && (ceil_y>=top) ) {
407 p3 = *(source_bits + (int32)floor_x + (int32)ceil_y*source_bpr);
408 }
409 else {
410 p3 = background.word;
411 }
412
413 // fourth
414 if (( ceil_x <= right) && (ceil_y <= bottom)
415 && (ceil_x>=left) && (ceil_y>=top) ) {
416 p4 = *(source_bits + (int32)ceil_x + (int32)ceil_y*source_bpr);
417 }
418 else {
419 p4 = background.word;
420 }
421
422 *(target_bits + (int32)x + (int32)y*target_bpr) = bilinear_interpolation(p1,p2,p3,p4,u,v);
423
424 }
425 x_times_sin += sin_angle;
426 x_times_cos += cos_angle;
427 }
428 y_times_sin += sin_angle;
429 y_times_cos += cos_angle;
430 if ((status_bar != NULL__null) && (status_bar->Window() != NULL__null)) {
431 BMessage *a_message = new BMessage(B_UPDATE_STATUS_BAR);
432 a_message->AddFloat("delta",100.0/(float)(sel_bottom-sel_top));
433 status_bar->Window()->PostMessage(a_message,status_bar);
434 delete a_message;
435 }
436 }
437 }
438
439 return new_bitmap;
440}
441
442
443int32 RotationManipulator::PreviewBitmap(Selection *selection,bool full_quality,BRegion *updated_region)
444{
445 // First decide the resolution of the bitmap
446 if ((previous_angle == settings->angle) && (full_quality == FALSE0)) {
447 if (last_calculated_resolution <= highest_available_quality) {
448 last_calculated_resolution = 0;
449 if (previous_origo != settings->origo) {
450 previous_origo = settings->origo;
451 return DRAW_ONLY_GUI;
452 }
453 else
454 return 0;
455 }
456 else
457 last_calculated_resolution = last_calculated_resolution / 2;
458 }
459 else if (full_quality == TRUE1) {
460 last_calculated_resolution = 1;
461 }
462 else
463 last_calculated_resolution = lowest_available_quality;
464
465
466 union {
467 uint8 bytes[4];
468 uint32 word;
469 } background;
470 // Transparent background.
471 background.bytes[0] = 0xFF;
472 background.bytes[1] = 0xFF;
473 background.bytes[2] = 0xFF;
474 background.bytes[3] = 0x00;
475
476
477 // Then calculate the preview
478 BPoint center = settings->origo;
479 float the_angle = settings->angle;
480 float sin_angle = sin(-the_angle/360*2*PI3.14159265358979323846);
481 float cos_angle = cos(-the_angle/360*2*PI3.14159265358979323846);
482
483 int32 *target_bits = (int32*)preview_bitmap->Bits();
484 int32 *source_bits = (int32*)copy_of_the_preview_bitmap->Bits();
485 int32 source_bpr = copy_of_the_preview_bitmap->BytesPerRow()/4;
486 int32 target_bpr = preview_bitmap->BytesPerRow()/4;
487
488 // copy the points according to angle
489 float height = preview_bitmap->Bounds().Height();
490 float width = preview_bitmap->Bounds().Width();
491 float left = copy_of_the_preview_bitmap->Bounds().left;
492 float right = copy_of_the_preview_bitmap->Bounds().right;
493 float top = copy_of_the_preview_bitmap->Bounds().top;
494 float bottom = copy_of_the_preview_bitmap->Bounds().bottom;
495 float center_x = center.x;
496 float center_y = center.y;
497 float source_x,source_y;
498 float y_times_sin = (-center_y)*sin_angle;
499 float y_times_cos = (-center_y)*cos_angle;
500 if (selection->IsEmpty()) {
501 for (int32 y=0;y<=height;y += last_calculated_resolution) {
502 float x_times_sin = (-center_x)*sin_angle;
503 float x_times_cos = (-center_x)*cos_angle;
504 for (int32 x=0;x<=width;x += last_calculated_resolution) {
505 // rotete here around the origin
506 source_x = x_times_cos - y_times_sin;
507 source_y = x_times_sin + y_times_cos;
508 // translate back to correct position
509 source_x += center_x;
510 source_y += center_y;
511 if ((source_x <= right) && (source_y <= bottom)
512 && (source_x >= left) && (source_y >= top)) {
513 *(target_bits + x + y*target_bpr) =
514 *(source_bits + (int32)source_x + (int32)source_y*source_bpr);
515 }
516 else
517 *(target_bits + x + y*target_bpr) = background.word; // Transparent.
518
519 x_times_sin += last_calculated_resolution*sin_angle;
520 x_times_cos += last_calculated_resolution*cos_angle;
521 }
522 y_times_sin += last_calculated_resolution*sin_angle;
523 y_times_cos += last_calculated_resolution*cos_angle;
524 }
525 }
526 else {
527 // Rotate the selection also
528 selection->RotateTo(center,the_angle);
529 for (int32 y=0;y<=height;y += last_calculated_resolution) {
530 float x_times_sin = (-center_x)*sin_angle;
531 float x_times_cos = (-center_x)*cos_angle;
532 for (int32 x=0;x<=width;x += last_calculated_resolution) {
533 // rotete here around the origin
534 source_x = x_times_cos - y_times_sin;
535 source_y = x_times_sin + y_times_cos;
536 // translate back to correct position
537 source_x += center_x;
538 source_y += center_y;
539 if ((source_x <= right) && (source_y <= bottom)
540 && (source_x >= left) && (source_y >= top)
541 && selection->ContainsPoint(int32(source_x), int32(source_y))) {
542 *(target_bits + x + y*target_bpr) =
543 *(source_bits + (int32)source_x + (int32)source_y*source_bpr);
544 }
545 else if (selection->ContainsPoint(BPoint(source_x,source_y)))
546 *(target_bits + x + y*target_bpr) = background.word; // Transparent.
547 else if (selection->ContainsPoint(x,y))
548 *(target_bits + x + y*target_bpr) = background.word;
549 else
550 *(target_bits + x + y*target_bpr) = *(source_bits + (int32)x + (int32)y*source_bpr);
551
552 x_times_sin += last_calculated_resolution*sin_angle;
553 x_times_cos += last_calculated_resolution*cos_angle;
554 }
555 y_times_sin += last_calculated_resolution*sin_angle;
556 y_times_cos += last_calculated_resolution*cos_angle;
557 }
558 }
559
560 updated_region->Set(preview_bitmap->Bounds());
561
562 return last_calculated_resolution;
563}
564
565
566void RotationManipulator::Reset(Selection *selection)
567{
568 selection->RotateTo(settings->origo,0);
569 settings->angle = 0;
570 previous_angle = 0;
571
572 if (copy_of_the_preview_bitmap != NULL__null) {
573 // memcpy seems to be about 10-15% faster that copying with loop.
574 uint32 *source = (uint32*)copy_of_the_preview_bitmap->Bits();
575 uint32 *target = (uint32*)preview_bitmap->Bits();
576 uint32 bits_length = preview_bitmap->BitsLength();
577
578 memcpy(target,source,bits_length);
579 }
580}
581
582
583BView*
584RotationManipulator::MakeConfigurationView(const BMessenger& target)
585{
586 //if (config_view)
587 // return config_view;
588
589 config_view =
590 new RotationManipulatorConfigurationView(this, target);
591 config_view->SetAngle(settings->angle);
592 return config_view;
593}
594
595
596void
597RotationManipulator::SetAngle(float angle)
598{
599 previous_angle = settings->angle;
600 settings->angle = angle;
601}
602
603
604const char*
605RotationManipulator::ReturnHelpString()
606{
607 return B_TRANSLATE("Use the primary mouse-button to rotate, other buttons to set the rotation center.")BLocaleRoster::Default()->GetCatalog()->GetString(("Use the primary mouse-button to rotate, other buttons to set the rotation center."
), "Manipulators")
;
608}
609
610
611const char*
612RotationManipulator::ReturnName()
613{
614 return B_TRANSLATE("Rotate" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Rotate"
"\xE2\x80\xA6"), "Manipulators")
;
615}
616
617
618// #pragma mark -- RotationManipulatorConfigurationView
619
620
621RotationManipulatorConfigurationView::RotationManipulatorConfigurationView(
622 RotationManipulator* manipulator, const BMessenger& target)
623 : WindowGUIManipulatorView()
624 , fTarget(target)
625 , fManipulator(manipulator)
626{
627 fTextControl = new BTextControl("rotation", B_TRANSLATE("Angle:")BLocaleRoster::Default()->GetCatalog()->GetString(("Angle:"
), "Manipulators")
, "9999.9˚",
628 new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'));
629 BRect bounds = fTextControl->TextView()->Bounds();
630 fTextControl->TextView()->SetExplicitMaxSize(BSize(StringWidth("-999.99'"), bounds.Height()));
631
632 SetLayout(BLayoutBuilder::Group<>(this, B_VERTICAL)
633 .Add(fTextControl)
634 );
635
636 RotationManipulatorSettings* settings
637 = (RotationManipulatorSettings*)manipulator->ReturnSettings();
638 char text[256];
639 sprintf(text, "%.1f˚", settings->angle);
640 fTextControl->TextView()->SetText(text);
641}
642
643
644void
645RotationManipulatorConfigurationView::AttachedToWindow()
646{
647 fTextControl->SetTarget(this);
648
649 if (BView* parent = Parent()) {
650 SetLowColor(parent->LowColor());
651 SetViewColor(parent->ViewColor());
652 }
653
654 fTextControl->MakeFocus(true);
655
656 WindowGUIManipulatorView::AttachedToWindow();
657}
658
659
660void
661RotationManipulatorConfigurationView::MessageReceived(BMessage* message)
662{
663 switch (message->what) {
664 case HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi': {
665 BTextView *text_view = fTextControl->TextView();
666 char float_text[256];
667 const char *text = text_view->Text();
668 float angle = 0;
669 int decimal_place = 0;
670 float sign = 1;
671
672 for (uint32 i = 0; i < strlen(text); i++) {
673 if (isdigit(text[i])(__ctype_b[(int)((text[i]))] & (unsigned short int)_ISdigit
)
!= 0) {
674 float new_number = text[i] - '0';
675 if (decimal_place <= 0)
676 angle = 10*angle + new_number;
677 else {
678 angle = angle + new_number / pow(10,decimal_place);
679 decimal_place++;
680 }
681 }
682 else if (((text[i] == '.') || (text[i] == ',')) && (decimal_place <= 0)) {
683 decimal_place = 1;
684 }
685 else if ((decimal_place <= 0) && (angle == 0) && (text[i] == '-'))
686 sign = -1;
687 }
688
689 angle = sign*angle;
690
691 while (angle > 360)
692 angle -= 360;
693 if (angle > 180)
694 angle -= 360;
695
696 while (angle < -360)
697 angle += 360;
698 if (angle < -180)
699 angle += 360;
700
701 sprintf(float_text,"%.1f˚",angle);
702 text_view->SetText(float_text);
703 fManipulator->SetAngle(angle);
704 if (fTarget.IsValid())
705 fTarget.SendMessage(message);
706 } break;
707
708 default: {
709 WindowGUIManipulatorView::MessageReceived(message);
710 } break;
711 }
712}
713
714
715void
716RotationManipulatorConfigurationView::SetAngle(float angle)
717{
718 BWindow* window = Window();
719 if (window && window->Lock()) {
720 char text[256];
721 sprintf(text, "%.1f˚", angle);
722 fTextControl->TextView()->SetText(text);
723 window->Unlock();
724 }
725}
726
727
728void
729RotationManipulatorConfigurationView::SetTarget(const BMessenger& target)
730{
731 fTarget = target;
732}