Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/viewmanipulators/RotationManipulator.cpp
Warning:line 382, column 6
Value stored to 'red' is never read

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-07-02-122529-1240-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;
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;
Value stored to 'red' is never read
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 delete settings;
643}
644
645
646void
647RotationManipulatorConfigurationView::AttachedToWindow()
648{
649 fTextControl->SetTarget(this);
650
651 if (BView* parent = Parent()) {
652 SetLowColor(parent->LowColor());
653 SetViewColor(parent->ViewColor());
654 }
655
656 fTextControl->MakeFocus(true);
657
658 WindowGUIManipulatorView::AttachedToWindow();
659}
660
661
662void
663RotationManipulatorConfigurationView::MessageReceived(BMessage* message)
664{
665 switch (message->what) {
666 case HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi': {
667 BTextView *text_view = fTextControl->TextView();
668 char float_text[256];
669 const char *text = text_view->Text();
670 float angle = 0;
671 int decimal_place = 0;
672 float sign = 1;
673
674 for (uint32 i = 0; i < strlen(text); i++) {
675 if (isdigit(text[i])(__ctype_b[(int)((text[i]))] & (unsigned short int)_ISdigit
)
!= 0) {
676 float new_number = text[i] - '0';
677 if (decimal_place <= 0)
678 angle = 10*angle + new_number;
679 else {
680 angle = angle + new_number / pow(10,decimal_place);
681 decimal_place++;
682 }
683 }
684 else if (((text[i] == '.') || (text[i] == ',')) && (decimal_place <= 0)) {
685 decimal_place = 1;
686 }
687 else if ((decimal_place <= 0) && (angle == 0) && (text[i] == '-'))
688 sign = -1;
689 }
690
691 angle = sign*angle;
692
693 while (angle > 360)
694 angle -= 360;
695 if (angle > 180)
696 angle -= 360;
697
698 while (angle < -360)
699 angle += 360;
700 if (angle < -180)
701 angle += 360;
702
703 sprintf(float_text,"%.1f˚",angle);
704 text_view->SetText(float_text);
705 fManipulator->SetAngle(angle);
706 if (fTarget.IsValid())
707 fTarget.SendMessage(message);
708 } break;
709
710 default: {
711 WindowGUIManipulatorView::MessageReceived(message);
712 } break;
713 }
714}
715
716
717void
718RotationManipulatorConfigurationView::SetAngle(float angle)
719{
720 BWindow* window = Window();
721 if (window && window->Lock()) {
722 char text[256];
723 sprintf(text, "%.1f˚", angle);
724 fTextControl->TextView()->SetText(text);
725 window->Unlock();
726 }
727}
728
729
730void
731RotationManipulatorConfigurationView::SetTarget(const BMessenger& target)
732{
733 fTarget = target;
734}