Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/paintwindow/PaintWindow.cpp
Warning:line 1709, column 3
Value stored to 'status' 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 PaintWindow.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/paintwindow/PaintWindow.cpp
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 "PaintWindow.h"
14
15#include "BackgroundView.h"
16#include "BrushStoreWindow.h"
17#include "ColorPalette.h"
18#include "DatatypeSetupWindow.h"
19#include "FileIdentificationStrings.h"
20#include "FilePanels.h"
21#include "GlobalSetupWindow.h"
22#include "Image.h"
23#include "ImageView.h"
24#include "Layer.h"
25#include "LayerWindow.h"
26#include "Manipulator.h"
27#include "ManipulatorServer.h"
28#include "ManipulatorInformer.h"
29#include "MessageConstants.h"
30#include "MessageFilters.h"
31#include "NumberControl.h"
32#include "PaintApplication.h"
33#include "PaintWindowMenuItem.h"
34#include "ProjectFileFunctions.h"
35#include "PopUpList.h"
36#include "ResourceServer.h"
37#include "Selection.h"
38#include "SettingsServer.h"
39#include "StatusView.h"
40#include "ToolSetupWindow.h"
41#include "ToolSelectionWindow.h"
42#include "UtilityClasses.h"
43#include "ViewSetupWindow.h"
44
45
46#include <Alert.h>
47#include <BitmapStream.h>
48#include <Button.h>
49#include <Catalog.h>
50#include <Clipboard.h>
51#include <Entry.h>
52#include <LayoutBuilder.h>
53#include <MenuBar.h>
54#include <NodeInfo.h>
55#include <Path.h>
56#include <Roster.h>
57#include <Screen.h>
58#include <ScrollBar.h>
59#include <SupportDefs.h>
60#include <TranslatorRoster.h>
61#include <private/interface/WindowInfo.h>
62
63
64#include <map>
65#include <new>
66#include <stack>
67#include <stdio.h>
68#include <stdlib.h>
69
70
71#undef B_TRANSLATION_CONTEXT"PaintWindow"
72#define B_TRANSLATION_CONTEXT"PaintWindow" "PaintWindow"
73
74
75using ArtPaint::Interface::NumberControl;
76
77
78// initialize the static variable
79BList PaintWindow::sgPaintWindowList(10);
80int32 PaintWindow::sgPaintWindowCount = 0;
81int32 PaintWindow::sgUntitledWindowNumber = 1;
82
83
84// these constants are for the internal communication of the PaintWindow-class
85#define HS_SHOW_VIEW_SETUP_WINDOW'SvsW' 'SvsW'
86#define HS_SHOW_GLOBAL_SETUP_WINDOW'SgsW' 'SgsW'
87#define HS_RECENT_IMAGE_SIZE'Rsis' 'Rsis'
88
89
90struct menu_item {
91 BString label;
92 uint32 what;
93 char shortcut;
94 uint32 modifiers;
95 BHandler* target;
96 BString help;
97};
98
99
100PaintWindow::PaintWindow(BRect frame, const char* name, uint32 views,
101 const BMessage& settings)
102 : BWindow(frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
103 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ANCHORED_ON_ACTIVATE | B_AUTO_UPDATE_SIZE_LIMITS)
104 , fSettings(settings)
105 , fImageView(NULL__null)
106 , fBackground(NULL__null)
107 , fVerticalScrollbar(NULL__null)
108 , fHorizontalScrollbar(NULL__null)
109 , fMenubar(NULL__null)
110 , fStatusView(NULL__null)
111 , fContainerBox(NULL__null)
112 , fSetSizeButton(NULL__null)
113 , fWidthNumberControl(NULL__null)
114 , fHeightNumberControl(NULL__null)
115 , fImageSavePanel(NULL__null)
116 , fProjectSavePanel(NULL__null)
117 , fCurrentHandler(0)
118 , fImageSizeWindow(NULL__null)
119{
120 sgPaintWindowCount++;
121 SetSizeLimits(500, 10000, 400, 10000);
122
123 // Fit the window to screen.
124 BRect new_frame = FitRectToScreen(frame);
125 if (new_frame != frame) {
126 MoveTo(new_frame.LeftTop());
127 ResizeTo(new_frame.Width(),new_frame.Height());
128 }
129
130 if (views == 0)
131 fSettings.FindUInt32(skViews, &views);
132
133 if ((views & HS_MENU_BAR0x0008) != 0)
134 openMenuBar(); // the menubar should be opened
135
136 // The status-view is not optional. It contains sometimes also buttons that
137 // can cause some actions to be taken.
138 if ((views & HS_STATUS_VIEW0x0004) != 0) {
139 // Create the status-view and make it display nothing
140 fStatusView = new StatusView();
141 }
142
143 // make the background view (the backround for image)
144 fBackground = new BackgroundView(BRect(0, 0, 0, 0));
145
146 fVerticalScrollbar = fBackground->ScrollBar(B_VERTICAL);
147 fVerticalScrollbar->SetSteps(8.0, 32.0);
148 fHorizontalScrollbar = fBackground->ScrollBar(B_HORIZONTAL);
149 fHorizontalScrollbar->SetSteps(8.0, 32.0);
150
151 if ((views & HS_SIZING_VIEW0x0010) != 0x0000) {
152 // we need to show the create canvas area
153 const char* widthLabel = B_TRANSLATE("Width:")BLocaleRoster::Default()->GetCatalog()->GetString(("Width:"
), "PaintWindow")
;
154 const char* heightLabel = B_TRANSLATE("Height:")BLocaleRoster::Default()->GetCatalog()->GetString(("Height:"
), "PaintWindow")
;
155
156 BFont font;
157 const char* tmpLabel = widthLabel;
158 if (font.StringWidth(heightLabel) > font.StringWidth(widthLabel))
159 tmpLabel = heightLabel;
160
161 fWidthNumberControl = new NumberControl(tmpLabel, "", NULL__null);
162 fWidthNumberControl->SetLabel(widthLabel);
163 fWidthNumberControl->TextView()->SetMaxBytes(4);
164
165 fHeightNumberControl = new NumberControl(tmpLabel, "", NULL__null);
166 fHeightNumberControl->SetLabel(heightLabel);
167 fHeightNumberControl->TextView()->SetMaxBytes(4);
168
169 fSetSizeButton = new BButton("set_size_button",
170 B_TRANSLATE("Create canvas")BLocaleRoster::Default()->GetCatalog()->GetString(("Create canvas"
), "PaintWindow")
, new BMessage(HS_IMAGE_SIZE_SET'IsiS'));
171
172 fSetSizeButton->SetTarget(this);
173 fSetSizeButton->MakeDefault(true);
174
175 SettingsServer* settings = SettingsServer::Instance();
176 const ImageSizeList& list = settings->RecentImageSizes();
177
178 BMessage messages;
179 ImageSizeList::const_iterator it;
180 for (it = list.begin(); it != list.end(); ++it) {
181 BString label;
182 label << int32((*it).width) << " x " << int32((*it).height);
183
184 BMessage msg(HS_RECENT_IMAGE_SIZE'Rsis');
185 msg.AddInt32("width", (*it).width);
186 msg.AddInt32("height", (*it).height);
187 msg.AddString("label", label.String());
188
189 messages.AddMessage("list", &msg);
190 }
191
192 float left = fHeightNumberControl->Frame().right + 5.0;
193 float top = (fHeightNumberControl->Frame().bottom -
194 fWidthNumberControl->Frame().top) / 2.0;
195
196 BBitmap* listNormal;
197 BBitmap* listPushed;
198 ResourceServer* server = ResourceServer::Instance();
199 server->GetBitmap(POP_UP_LIST, &listNormal);
200 server->GetBitmap(POP_UP_LIST_PUSHED, &listPushed);
201
202 PopUpList* popUpList = new PopUpList(BRect(left, top, left + 9, top + 19),
203 listPushed, listNormal, messages, list.size(), this);
204
205 BMenu* standardSize = new BMenu(B_TRANSLATE("Standard sizes")BLocaleRoster::Default()->GetCatalog()->GetString(("Standard sizes"
), "PaintWindow")
);
206
207 BMessage* message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
208 message->AddInt32("width", 320);
209 message->AddInt32("height", 256);
210 standardSize->AddItem(new BMenuItem("320 x 256", message));
211
212 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
213 message->AddInt32("width", 640);
214 message->AddInt32("height", 400);
215 standardSize->AddItem(new BMenuItem("640 x 400", message));
216
217 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
218 message->AddInt32("width", 640);
219 message->AddInt32("height", 480);
220 standardSize->AddItem(new BMenuItem("640 x 480", message));
221
222 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
223 message->AddInt32("width", 800);
224 message->AddInt32("height", 600);
225 standardSize->AddItem(new BMenuItem("800 x 600", message));
226
227 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
228 message->AddInt32("width", 1024);
229 message->AddInt32("height", 768);
230 standardSize->AddItem(new BMenuItem("1024 x 768", message));
231
232 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
233 message->AddInt32("width", 1152);
234 message->AddInt32("height", 900);
235 standardSize->AddItem(new BMenuItem("1152 x 900", message));
236
237 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
238 message->AddInt32("width", 1280);
239 message->AddInt32("height", 1024);
240 standardSize->AddItem(new BMenuItem("1280 x 1024", message));
241
242 message = new BMessage(HS_RECENT_IMAGE_SIZE'Rsis');
243 message->AddInt32("width", 1600);
244 message->AddInt32("height", 1200);
245 standardSize->AddItem(new BMenuItem("1600 x 1200", message));
246
247 popUpList->ReturnMenu()->AddItem(standardSize, 0);
248 popUpList->ReturnMenu()->AddItem(new BSeparatorItem(), 1);
249
250 fContainerBox = new BBox("container_for_controls");
251 fContainerBox->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
252
253 fImageSizeWindow = new BWindow(BRect(0, 0, 175, 125), "Canvas Size",
254 B_MODAL_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL, B_NOT_MOVABLE |
255 B_NOT_RESIZABLE | B_NOT_ZOOMABLE);
256
257 fImageSizeWindow->AddToSubset(this);
258
259 BGridLayout* containerLayout = BLayoutBuilder::Grid<>(
260 fImageSizeWindow, 5.0, 5.0)
261 .Add(fWidthNumberControl, 0, 0, 0, 0)
262 .Add(fWidthNumberControl->CreateLabelLayoutItem(), 0, 0)
263 .Add(fWidthNumberControl->CreateTextViewLayoutItem(), 1, 0)
264 .Add(fHeightNumberControl, 0, 1, 0, 0)
265 .Add(fHeightNumberControl->CreateLabelLayoutItem(), 0, 1)
266 .Add(fHeightNumberControl->CreateTextViewLayoutItem(), 1, 1)
267 .Add(fSetSizeButton, 1, 2)
268 .Add(popUpList, 2, 0)
269 .SetInsets(10.0, 2.0, 0.0, 2.0);
270 containerLayout->SetMinColumnWidth(2, 15.0);
271
272 BMessage msg(HS_TOOL_HELP_MESSAGE'TolM');
273 msg.AddString("message", B_TRANSLATE("Set/Select the canvas size.")BLocaleRoster::Default()->GetCatalog()->GetString(("Set/Select the canvas size."
), "PaintWindow")
);
274 PostMessage(&msg, this);
275
276 fImageSizeWindow->ResizeToPreferred();
277 fImageSizeWindow->CenterIn(Frame());
278 fImageSizeWindow->Activate();
279 fImageSizeWindow->Show();
280 }
281
282 BGroupLayout *inner = BLayoutBuilder::Group<>(B_VERTICAL, 0)
283 .Add(fBackground)
284 .SetInsets(-1.0, -2.0, -2.0, -1.0);
285
286 BGroupLayout* outer = BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
287 .Add(inner);
288
289 if (fMenubar)
290 outer->AddView(0, fMenubar);
291
292 if (fStatusView) {
293 outer->AddView(fStatusView);
294 }
295
296 // finally inform the app that new window has been created
297 BMessage message(HS_PAINT_WINDOW_OPENED'PwOp');
298 message.AddPointer("window", (void*)this);
299 be_app->PostMessage(&message, be_app);
300
301 // Add ourselves to the sgPaintWindowList
302 sgPaintWindowList.AddItem(this);
303
304 Lock();
305 // Handle the window-activation with this common filter.
306 BMessageFilter *activation_filter = new BMessageFilter(B_ANY_DELIVERY,
307 B_ANY_SOURCE, B_MOUSE_DOWN, window_activation_filter);
308 AddCommonFilter(activation_filter);
309 AddCommonFilter(new BMessageFilter(B_KEY_DOWN, AppKeyFilterFunction));
310 Unlock();
311
312 fUserFrame = Frame();
313}
314
315
316PaintWindow*
317PaintWindow::CreatePaintWindow(BBitmap* bitmap, const char* fileName,
318 uint32 translatorType, const entry_ref& ref, translator_id outTranslator)
319{
320 BMessage tmpSettings;
321 status_t status = B_ERROR(-1);
322 SettingsServer* server = SettingsServer::Instance();
323 if ((status = server->GetWindowSettings(&tmpSettings)) != B_OK((int)0))
324 status = server->GetDefaultWindowSettings(&tmpSettings);
325
326 if (status == B_OK((int)0)) {
327 uint32 flags = HS_MENU_BAR0x0008 | HS_STATUS_VIEW0x0004 | HS_HELP_VIEW0x0002 ;
328 if (fileName == NULL__null) {
329 flags = flags | HS_SIZING_VIEW0x0010;
330 fileName = B_TRANSLATE("Empty paint window")BLocaleRoster::Default()->GetCatalog()->GetString(("Empty paint window"
), "PaintWindow")
;
331 }
332
333 BRect frame;
334 if (tmpSettings.FindRect(skFrame, &frame) == B_OK((int)0)) {
335 PaintWindow* paintWindow = new (std::nothrow) PaintWindow(frame,
336 fileName, flags, tmpSettings);
337
338 if (paintWindow) {
339 BMessage* settings = paintWindow->Settings();
340 paintWindow->fCurrentHandler = outTranslator;
341
342 if (paintWindow->Lock()) {
343 float zoom;
344 if (settings->FindFloat(skZoom, &zoom) == B_OK((int)0))
345 paintWindow->displayMag(zoom);
346 paintWindow->Unlock();
347 }
348
349 if (bitmap) {
350 BNode node(&ref);
351 BNodeInfo nodeInfo(&node);
352
353 char mime[B_MIME_TYPE_LENGTH(((256) - 1) - 15)];
354 nodeInfo.GetType(mime);
355
356 settings->ReplaceString(skMimeType, mime);
357 settings->ReplaceUInt32(skTranslatorType, translatorType);
358
359 paintWindow->SetImageEntry(BEntry(&ref, true));
360
361 BRect bounds = bitmap->Bounds();
362 paintWindow->OpenImageView(bounds.IntegerWidth() + 1,
363 bounds.IntegerHeight() + 1);
364 paintWindow->ReturnImageView()->ReturnImage()->InsertLayer(bitmap);
365 paintWindow->AddImageView();
366 }
367 }
368 return paintWindow;
369 }
370 }
371 return NULL__null;
372}
373
374
375PaintWindow::~PaintWindow()
376{
377 if (fImageView != NULL__null) {
378 // if we have a BEntry for this image, we should
379 // write some attributes to that file
380 if (fImageEntry.InitCheck() == B_OK((int)0)) {
381 // call a function that writes attributes to a node
382 BNode a_node(&fImageEntry);
383 writeAttributes(a_node);
384 }
385 if (fProjectEntry.InitCheck() == B_OK((int)0)) {
386 BNode a_node(&fProjectEntry);
387 writeAttributes(a_node);
388 }
389
390 fImageView->RemoveSelf();
391 delete fImageView;
392 }
393
394 // Decrement the window-count by 1.
395 sgPaintWindowCount--;
396
397 // Remove ourselves from the sgPaintWindowList.
398 sgPaintWindowList.RemoveItem(this);
399}
400
401
402void
403PaintWindow::FrameResized(float newWidth, float newHeight)
404{
405 fSettings.ReplaceRect(skFrame, Frame());
406 if (fImageSizeWindow && fImageSizeWindow->Lock()) {
407 if (!fImageSizeWindow->IsHidden())
408 fImageSizeWindow->CenterIn(Frame());
409 fImageSizeWindow->Unlock();
410 }
411}
412
413
414void
415PaintWindow::FrameMoved(BPoint newPosition)
416{
417 fSettings.ReplaceRect(skFrame, Frame());
418 if (fImageSizeWindow && fImageSizeWindow->Lock()) {
419 if (!fImageSizeWindow->IsHidden())
420 fImageSizeWindow->CenterIn(Frame());
421 fImageSizeWindow->Unlock();
422 }
423}
424
425
426void
427PaintWindow::Redraw()
428{
429 for (int i = 0; i < sgPaintWindowCount; ++i) {
430 PaintWindow* paintWin = (PaintWindow*)sgPaintWindowList.ItemAt(i);
431
432 ImageView* imgView = paintWin->ReturnImageView();
433 if (imgView != NULL__null) {
434 if (imgView->LockLooper() == true) {
435 imgView->ReturnImage()->Render();
436 imgView->Invalidate();
437 imgView->UnlockLooper();
438 }
439 }
440 }
441}
442
443
444void
445PaintWindow::MenusBeginning()
446{
447 BWindow::MenusBeginning();
448
449 SettingsServer* server = SettingsServer::Instance();
450
451 _AddRecentMenuItems(fRecentImages, &(server->RecentImagePaths()));
452 _AddRecentMenuItems(fRecentProjects, &(server->RecentProjectPaths()));
453
454 BMenuItem *item = fMenubar->FindItem(B_TRANSLATE("Paste as a new layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Paste as a new layer"
), "PaintWindow")
);
455 if (item != NULL__null) {
456 be_clipboard->Lock();
457 if (be_clipboard->Data()->HasMessage("image/bitmap"))
458 item->SetEnabled(true);
459 else
460 item->SetEnabled(false);
461 be_clipboard->Unlock();
462 }
463
464 item = fMenubar->FindItem(B_TRANSLATE("Paste as a new project")BLocaleRoster::Default()->GetCatalog()->GetString(("Paste as a new project"
), "PaintWindow")
);
465 if (item != NULL__null) {
466 be_clipboard->Lock();
467 if (be_clipboard->Data()->HasMessage("image/bitmap"))
468 item->SetEnabled(true);
469 else
470 item->SetEnabled(false);
471 be_clipboard->Unlock();
472 }
473
474 if (fImageView != NULL__null) {
475 item = fMenubar->FindItem(HS_CLEAR_SELECTION'ClSl');
476 if (fImageView->GetSelection()->IsEmpty())
477 item->SetEnabled(false);
478 else
479 item->SetEnabled(true);
480
481 item = fMenubar->FindItem(HS_INVERT_SELECTION'InSl');
482 if (fImageView->GetSelection()->IsEmpty())
483 item->SetEnabled(false);
484 else
485 item->SetEnabled(true);
486
487 item = fMenubar->FindItem(HS_GROW_SELECTION'GrSl');
488 if (fImageView->GetSelection()->IsEmpty())
489 item->SetEnabled(false);
490 else
491 item->SetEnabled(true);
492
493 item = fMenubar->FindItem(HS_SHRINK_SELECTION'SrSL');
494 if (fImageView->GetSelection()->IsEmpty())
495 item->SetEnabled(false);
496 else
497 item->SetEnabled(true);
498 }
499
500 if ((fImageEntry.InitCheck() == B_OK((int)0)) && (fCurrentHandler != 0)) {
501 BMenuItem *item = fMenubar->FindItem(HS_SAVE_IMAGE'Saim');
502 if (item) item->SetEnabled(true);
503 }
504 else {
505 BMenuItem *item = fMenubar->FindItem(HS_SAVE_IMAGE'Saim');
506 if (item) item->SetEnabled(false);
507 }
508
509 if (fProjectEntry.InitCheck() == B_OK((int)0)) {
510 BMenuItem *item = fMenubar->FindItem(HS_SAVE_PROJECT'Sapr');
511 if (item) item->SetEnabled(true);
512 }
513 else {
514 BMenuItem *item = fMenubar->FindItem(HS_SAVE_PROJECT'Sapr');
515 if (item) item->SetEnabled(false);
516 }
517
518 SetHelpString("",HS_TEMPORARY_HELP_MESSAGE'ThlM');
519}
520
521
522void
523PaintWindow::MenusEnded()
524{
525 SetHelpString(NULL__null, HS_TOOL_HELP_MESSAGE'TolM');
526}
527
528
529void
530PaintWindow::MessageReceived(BMessage *message)
531{
532 switch ( message->what ) {
533 case B_SIMPLE_DATA:
534 case B_REFS_RECEIVED: {
535 be_app_messenger.SendMessage(message);
536 } break;
537
538 case HS_RESIZE_WINDOW_TO_FIT'RwTF': {
539 // this comes from fMenubar->"Window"->"Resize to fit" and
540 // informs us that we should fit the window to display exactly the
541 // image use a private function to do resizing
542 _ResizeToImage();
543 } break;
544
545 case HS_RECENT_IMAGE_SIZE'Rsis': {
546 // This comes from the recent image-size pop-up-list.
547 if (fImageSizeWindow && fImageSizeWindow->Lock()) {
548 fWidthNumberControl->SetValue(message->FindInt32("width"));
549 fHeightNumberControl->SetValue(message->FindInt32("height"));
550 fImageSizeWindow->Unlock();
551 }
552 } break;
553
554 case HS_IMAGE_SIZE_SET'IsiS': {
555 // this comes from a button and it informs that the user has
556 // decided the image size and we should create a canvas
557
558 // Here we have to take the measurements from NumberControls.
559 // The units might be something else than pixels. This reading and
560 // conversion should be done in a separate function.
561 int32 width, height;
562 width = atoi(fWidthNumberControl->Text());
563 height = atoi(fHeightNumberControl->Text());
564
565 bool success = false;
566 try {
567 // Open the image view
568 OpenImageView(width, height);
569 // Add a layer to it.
570 fImageView->ReturnImage()->InsertLayer();
571 success = true;
572 }
573 catch (std::bad_alloc) {
574 delete fImageView;
575 fImageView = NULL__null;
576 BAlert* alert = new BAlert("",
577 B_TRANSLATE("Not enough free memory to create the image. Please try again with a smaller image size.")BLocaleRoster::Default()->GetCatalog()->GetString(("Not enough free memory to create the image. Please try again with a smaller image size."
), "PaintWindow")
,
578 B_TRANSLATE("OK")BLocaleRoster::Default()->GetCatalog()->GetString(("OK"
), "PaintWindow")
, NULL__null, NULL__null,
579 B_WIDTH_AS_USUAL,B_WARNING_ALERT);
580 alert->Go();
581 }
582
583 if (success) {
584 BMessage windowSettings;
585 SettingsServer* server = SettingsServer::Instance();
586 if (server->GetWindowSettings(&windowSettings) != B_OK((int)0))
587 server->GetDefaultWindowSettings(&windowSettings);
588
589 // Record the window's frame
590 windowSettings.ReplaceRect(skFrame, Frame());
591 server->SetWindowSettings(windowSettings);
592
593 // record the new size to the recent list
594 server->AddRecentImageSize(BSize(width, height));
595
596 // Add the view to view hierarchy.
597 AddImageView();
598 fImageSizeWindow->Hide();
599 }
600 } break;
601
602 case HS_MOUSE_DOWN_IN_BACKGROUNDVIEW'MdBV': {
603 // this is the case where mouse has been pressed down in the
604 // background-view, we should then put the actual imageview
605 // to follow the mouse
606 if (fImageView && fImageView->Window())
607 fImageView->MouseDown(message->FindPoint("point"));
608 } break;
609
610
611 case HS_SHOW_LAYER_WINDOW'ShLW': {
612 // this comes from fMenubar->"Window"->"Layers" and tells
613 // us to show the layer window
614 LayerWindow::showLayerWindow();
615 if (fImageView) {
616 LayerWindow::ActiveWindowChanged(this,
617 fImageView->ReturnImage()->LayerList(),
618 fImageView->ReturnImage()->ReturnThumbnailImage());
619 } else {
620 LayerWindow::ActiveWindowChanged(this);
621 }
622
623 } break;
624
625 case HS_SHOW_VIEW_SETUP_WINDOW'SvsW': {
626 // his comes from fMenubar->"Window"->"Window Settings…" and tells
627 // us to show the window for setting the parameters of this window
628 // and it's views
629 ViewSetupWindow::showViewSetupWindow(this,fImageView);
630 } break;
631
632 case HS_SHOW_GLOBAL_SETUP_WINDOW'SgsW': {
633 // this comes from fMenubar->"Window"->"Settings…"
634 GlobalSetupWindow::ShowGlobalSetupWindow();
635 } break;
636
637 case HS_SHOW_IMAGE_SAVE_PANEL'SiSp': {
638 if (!fImageSavePanel) {
639 BPath path;
640 if (fImageEntry.InitCheck() != B_OK((int)0)) {
641 BMessage setting;
642 if (SettingsServer* server = SettingsServer::Instance())
643 server->GetApplicationSettings(&setting);
644
645 // Might fail if the user has removed the directory.
646 if (path.SetTo(setting.FindString(skImageSavePath)) != B_OK((int)0))
647 PaintApplication::HomeDirectory(path);
648 } else {
649 fImageEntry.GetPath(&path);
650 path.GetParent(&path);
651 }
652
653 entry_ref ref;
654 get_ref_for_path(path.Path(), &ref);
655
656 uint32 translatorType;
657 fSettings.FindUInt32(skTranslatorType, &translatorType);
658
659 BMessenger panelTarget(this);
660 BMessage message(HS_IMAGE_SAVE_REFS'ImSr');
661 fImageSavePanel = new ImageSavePanel(ref, panelTarget,
662 message, translatorType);
663 //fImageView->ReturnImage()->ReturnThumbnailImage());
664 }
665
666 fImageSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE0);
667 set_filepanel_strings(fImageSavePanel);
668 if (!fImageSavePanel->IsShowing())
669 fImageSavePanel->Show();
670 } break;
671
672 case HS_SHOW_PROJECT_SAVE_PANEL'PrSp': {
673 // This comes from fMenubar->"File"->"Save Project As…"
674 if (!fProjectSavePanel) {
675 BPath path;
676 if (fProjectEntry.InitCheck() != B_OK((int)0)) {
677 BMessage settings;
678 SettingsServer* server = SettingsServer::Instance();
679 if (server->GetApplicationSettings(&settings) == B_OK((int)0)) {
680 BString tmp = settings.FindString(skProjectSavePath);
681 if (path.SetTo(tmp.String()) != B_OK((int)0))
682 PaintApplication::HomeDirectory(path);
683 }
684 } else {
685 fProjectEntry.GetPath(&path);
686 path.GetParent(&path);
687 }
688
689 entry_ref ref;
690 get_ref_for_path(path.Path(), &ref);
691
692 BMessenger window(this);
693 BMessage msg(HS_PROJECT_SAVE_REFS'PrSr');
694 msg.AddInt32("TryAgain", message->GetInt32("TryAgain", false));
695 msg.AddInt32("quitAll", message->GetInt32("quitAll", false));
696 fProjectSavePanel = new BFilePanel(B_SAVE_PANEL, &window, &ref,
697 0, false, &msg);
698 }
699
700 fProjectSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE0);
701 char string[256];
702 sprintf(string, "ArtPaint: %s", B_TRANSLATE("Save project")BLocaleRoster::Default()->GetCatalog()->GetString(("Save project"
), "PaintWindow")
);
703 fProjectSavePanel->Window()->SetTitle(string);
704 set_filepanel_strings(fProjectSavePanel);
705 if (!fProjectSavePanel->IsShowing())
706 fProjectSavePanel->Show();
707 } break;
708
709 case HS_SHOW_COLOR_WINDOW'ShCw': {
710 // This comes from fMenubar->"Window"->"Colors".
711 // We should open the color window.
712 ColorPaletteWindow::showPaletteWindow(); // TODO: was (false)
713 } break;
714
715 case HS_SHOW_TOOL_WINDOW'ShtW': {
716 // This comes from fMenubar->"Window"->"Tools". We should
717 // open the tool window.
718 ToolSelectionWindow::showWindow();
719 } break;
720
721 case HS_SHOW_TOOL_SETUP_WINDOW'StsW': {
722 if (SettingsServer* server = SettingsServer::Instance()) {
723 BMessage settings;
724 server->GetApplicationSettings(&settings);
725 ToolSetupWindow::ShowToolSetupWindow(settings.FindInt32(skTool));
726 }
727 } break;
728
729 case HS_SHOW_BRUSH_STORE_WINDOW'Sbsw': {
730 BrushStoreWindow::showWindow();
731 } break;
732
733 case HS_IMAGE_SAVE_REFS'ImSr': {
734 if (fImageSavePanel)
735 fImageSavePanel->Hide();
736 // Here we call the function that saves the image. We actually call
737 // it in another thread while ensuring that it saves the correct
738 // bitmap. We should also protect the bitmap from being modified
739 // while we save. We should also inform the user about saving.
740 if (fImageView) {
741 thread_id threadId = spawn_thread(PaintWindow::save_image,
742 "save image", B_NORMAL_PRIORITY10, (void*)this);
743 if (threadId >= 0) {
744 BMessage* data = new BMessage(*message);
745 send_data(threadId, 0, (void*)&data, sizeof(BMessage*));
746 resume_thread(threadId);
747 }
748 }
749 } break;
750
751 case HS_PROJECT_SAVE_REFS'PrSr': {
752 printf("Saving refs\n");
753 if (fProjectSavePanel)
754 fProjectSavePanel->Hide();
755 if (fImageView) {
756 // We call the function that saves the project.
757 thread_id threadId = spawn_thread(PaintWindow::save_project,
758 "save project", B_NORMAL_PRIORITY10, (void*)this);
759 if (threadId >= 0) {
760 BMessage* data = new BMessage(*message);
761 send_data(threadId, 0, (void*)&data, sizeof(BMessage*));
762 resume_thread(threadId);
763 }
764 }
765 } break;
766
767 case HS_SAVE_IMAGE'Saim': {
768 // We make a message containing the file name and ref for its dir.
769 BEntry parent;
770 fImageEntry.GetParent(&parent);
771
772 BPath path;
773 parent.GetPath(&path);
774
775 entry_ref ref;
776 get_ref_for_path(path.Path(), &ref);
777
778 char name[B_FILE_NAME_LENGTH(256)];
779 fImageEntry.GetName(name);
780
781 BMessage msg(HS_IMAGE_SAVE_REFS'ImSr');
782 msg.AddString("name", name);
783 msg.AddRef("directory", &ref);
784 PostMessage(&msg, this);
785 } break;
786
787 case HS_SAVE_PROJECT'Sapr': {
788 // Create a message containing file-name and ref for its dir.
789 if (fProjectEntry.InitCheck() == B_OK((int)0)) {
790 BEntry parent;
791 fProjectEntry.GetParent(&parent);
792
793 BPath path;
794 parent.GetPath(&path);
795
796 entry_ref ref;
797 get_ref_for_path(path.Path(), &ref);
798
799 char name[B_FILE_NAME_LENGTH(256)];
800 fProjectEntry.GetName(name);
801
802 BMessage msg(HS_PROJECT_SAVE_REFS'PrSr');
803 msg.AddString("name", name);
804 msg.AddRef("directory", &ref);
805 msg.AddInt32("TryAgain", message->GetInt32("TryAgain", false));
806 msg.AddInt32("quitAll", message->GetInt32("quitAll", false));
807 PostMessage(&msg, this);
808 } else {
809 BMessage msg(HS_SHOW_PROJECT_SAVE_PANEL'PrSp');
810 msg.AddInt32("TryAgain", message->GetInt32("TryAgain", false));
811 msg.AddInt32("quitAll", message->GetInt32("quitAll", false));
812 PostMessage(&msg, this);
813 }
814 } break;
815
816 case HS_SAVE_FORMAT_CHANGED'SFCh': {
817 // this comes from the image save panel's format menu and informs
818 // that the wanted save format has changed
819 fCurrentHandler = message->FindInt32("be:translator");
820 DatatypeSetupWindow::ChangeHandler(fCurrentHandler);
821
822 uint32 translatorType = message->FindInt32("be:type");
823 fSettings.ReplaceUInt32(skTranslatorType, translatorType);
824
825 int32 count;
826 const translation_format* formats = NULL__null;
827 BTranslatorRoster* roster = BTranslatorRoster::Default();
828 if (roster->GetOutputFormats(fCurrentHandler, &formats, &count) == B_OK((int)0)) {
829 for (int32 i = 0; i < count; ++i) {
830 if (formats[i].type == translatorType)
831 fSettings.ReplaceString(skMimeType, BString(formats[i].MIME));
832 }
833 }
834 } break;
835
836 case HS_SHOW_DATATYPE_SETTINGS'SdtS': {
837 // This comes from image-save-panel's setting-button and tells us to
838 // show the datatype-setup-window.
839 DatatypeSetupWindow::ShowWindow(fCurrentHandler);
840 } break;
841
842 case B_CANCEL: {
843 if (fImageSavePanel && fImageSavePanel->IsShowing())
844 fImageSavePanel->Hide();
845
846 if (fProjectSavePanel && fProjectSavePanel->IsShowing())
847 fProjectSavePanel->Hide();
848 } break;
849
850 case HS_TOOL_HELP_MESSAGE'TolM': {
851 case HS_TEMPORARY_HELP_MESSAGE'ThlM':
852 // This might come from many places and it informs us to display a
853 // message in the help view.
854 static BString helpMessage;
855 message->FindString("message", &helpMessage);
856 SetHelpString(helpMessage.String(), message->what);
857 } break;
858
859 default: {
860 BWindow::MessageReceived(message);
861 } break;
862 }
863}
864
865
866bool
867PaintWindow::QuitRequested()
868{
869 // here we should ask the user if changes to picture should be saved we also
870 // tell the application that the number of paint windows has decreased by one
871 if (fImageView) {
872 if (fImageView->Quit() == false) {
873 if (Lock()) {
874 fImageView->ReturnImage()->Render();
875 fImageView->Invalidate();
876 Unlock();
877 }
878
879 return false;
880 }
881
882 if (fImageSavePanel)
883 delete fImageSavePanel;
884
885 if (fProjectSavePanel)
886 delete fProjectSavePanel;
887 }
888
889 LayerWindow::ActiveWindowChanged(NULL__null);
890
891 if (sgPaintWindowCount <= 1)
892 be_app->PostMessage(B_QUIT_REQUESTED);
893
894 return true;
895}
896
897
898void
899PaintWindow::WindowActivated(bool active)
900{
901 if (active == true) {
902 if (fImageView != NULL__null) {
903 LayerWindow::ActiveWindowChanged(this,
904 fImageView->ReturnImage()->LayerList(),
905 fImageView->ReturnImage()->ReturnThumbnailImage());
906 } else {
907 LayerWindow::ActiveWindowChanged(this);
908 }
909 }
910}
911
912
913void
914PaintWindow::WorkspaceActivated(int32, bool active)
915{
916 if (active) {
917 if (fImageView != NULL__null) {
918 if (BScreen(this).ColorSpace() == B_CMAP8) {
919// printf("B_CMAP8\n");
920 fImageView->SetDisplayMode(DITHERED_8_BIT_DISPLAY_MODE);
921 } else {
922// printf("not B_CMAP8\n");
923 fImageView->SetDisplayMode(FULL_RGB_DISPLAY_MODE);
924 }
925 }
926 }
927}
928
929
930void
931PaintWindow::Zoom(BPoint leftTop, float width, float height)
932{
933 if (fImageView) {
934 if (Image* image = fImageView->ReturnImage()) {
935 if (Frame() == _PreferredSize(image)) {
936 MoveTo(fUserFrame.LeftTop());
937 printf("here: %f x %f\n", fUserFrame.Width(), fUserFrame.Height());
938 ResizeTo(fUserFrame.Width(), fUserFrame.Height());
939 } else {
940 _ResizeToImage();
941 }
942 return;
943 }
944 }
945
946 BWindow::Zoom(leftTop, width, height);
947}
948
949
950void
951PaintWindow::DisplayCoordinates(BPoint point, BPoint reference, bool useReference)
952{
953 // here we set the proper view to display the coordinates
954
955 // set the coords string with sprintf
956// sprintf(coords,"X: %.0f Y: %.0f",point.x,point.y);
957
958 fStatusView->SetCoordinates(point, reference, useReference);
959
960 if (fSetSizeButton != NULL__null) {
961 // if the window is in resize mode display dimensions here too
962 if (fImageSizeWindow && fImageSizeWindow->Lock()) {
963 fWidthNumberControl->SetValue(int32(point.x));
964 fHeightNumberControl->SetValue(int32(point.y));
965 fImageSizeWindow->Unlock();
966 }
967 }
968}
969
970
971void
972PaintWindow::displayMag(float mag)
973{
974 fStatusView->SetMagnifyingScale(mag);
975}
976
977
978void
979PaintWindow::SetHelpString(const char *string,int32 type)
980{
981 static char tool_help_string[256];
982 if ((type == HS_TOOL_HELP_MESSAGE'TolM') && (string != NULL__null))
983 strncpy(tool_help_string, string, 255);
984
985 if (fStatusView != NULL__null) {
986 if (string != NULL__null)
987 fStatusView->SetHelpMessage(string);
988 else if (type == HS_TOOL_HELP_MESSAGE'TolM')
989 fStatusView->SetHelpMessage(tool_help_string);
990 }
991}
992
993
994/*!
995 Some of the items have the image as their target, the targets for those
996 items are set in openImageView. Remember to change image-view as target
997 for added items in openImageView.
998*/
999bool
1000PaintWindow::openMenuBar()
1001{
1002 fMenubar = new BMenuBar("menu_bar");
1003
1004 // the ArtPaint menu
1005 BMenu* menu = new BMenu(B_TRANSLATE_SYSTEM_NAME("ArtPaint")(BLocaleRoster::Default()->IsFilesystemTranslationPreferred
() ? BLocaleRoster::Default()->GetCatalog()->GetString(
("ArtPaint"), "System name") : ("ArtPaint"))
);
1006 fMenubar->AddItem(menu);
1007
1008 BMenuItem* item = new PaintWindowMenuItem(B_TRANSLATE("New project" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("New project"
"\xE2\x80\xA6"), "PaintWindow")
,
1009 new BMessage(HS_NEW_PAINT_WINDOW'NPtW'), 'N', 0, this,
1010 B_TRANSLATE("Creates a new empty canvas.")BLocaleRoster::Default()->GetCatalog()->GetString(("Creates a new empty canvas."
), "PaintWindow")
);
1011 item->SetTarget(be_app);
1012 menu->AddItem(item);
1013
1014 item = new PaintWindowMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Settings"
"\xE2\x80\xA6"), "PaintWindow")
,
1015 new BMessage(HS_SHOW_GLOBAL_SETUP_WINDOW'SgsW'), ',', 0, this,
1016 B_TRANSLATE("Opens the settings window.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the settings window."
), "PaintWindow")
);
1017 menu->AddItem(item);
1018
1019 menu->AddSeparatorItem();
1020
1021 BMessage* message = new BMessage(HS_SHOW_USER_DOCUMENTATION'Sudc');
1022 message->AddString("document", "index.html");
1023 item = new PaintWindowMenuItem(B_TRANSLATE("User manual" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("User manual"
"\xE2\x80\xA6"), "PaintWindow")
,
1024 message, 0, 0, this,
1025 B_TRANSLATE("Opens the main documentation for ArtPaint.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the main documentation for ArtPaint."
), "PaintWindow")
);
1026 item->SetTarget(be_app);
1027 menu->AddItem(item);
1028
1029 message = new BMessage(B_ABOUT_REQUESTED);
1030 item = new PaintWindowMenuItem(B_TRANSLATE("About ArtPaint")BLocaleRoster::Default()->GetCatalog()->GetString(("About ArtPaint"
), "PaintWindow")
,
1031 message, 0, 0, this,
1032 B_TRANSLATE("Opens a window with information about ArtPaint.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens a window with information about ArtPaint."
), "PaintWindow")
);
1033 item->SetTarget(be_app);
1034 menu->AddItem(item);
1035
1036 menu->AddSeparatorItem();
1037
1038 message = new BMessage(B_QUIT_REQUESTED);
1039 item = new PaintWindowMenuItem(B_TRANSLATE("Close")BLocaleRoster::Default()->GetCatalog()->GetString(("Close"
), "PaintWindow")
,
1040 message, 'W', 0, this,
1041 B_TRANSLATE("Closes the current window.")BLocaleRoster::Default()->GetCatalog()->GetString(("Closes the current window."
), "PaintWindow")
);
1042 menu->AddItem(item);
1043
1044 message = new BMessage(B_QUIT_REQUESTED);
1045 item = new PaintWindowMenuItem(B_TRANSLATE("Quit")BLocaleRoster::Default()->GetCatalog()->GetString(("Quit"
), "PaintWindow")
,
1046 message, 'Q', 0, this,
1047 B_TRANSLATE("Quits ArtPaint.")BLocaleRoster::Default()->GetCatalog()->GetString(("Quits ArtPaint."
), "PaintWindow")
);
1048 item->SetTarget(be_app);
1049 menu->AddItem(item);
1050
1051 // the File menu
1052 menu = new BMenu(B_TRANSLATE("File")BLocaleRoster::Default()->GetCatalog()->GetString(("File"
), "PaintWindow")
);
1053 fMenubar->AddItem(menu);
1054
1055 menu_item fileMenu[] = {
1056 { B_TRANSLATE("Open image" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Open image"
"\xE2\x80\xA6"), "PaintWindow")
, HS_SHOW_IMAGE_OPEN_PANEL'SiOp',
1057 'O', 0, be_app,
1058 B_TRANSLATE("Opens an image from disk.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens an image from disk."
), "PaintWindow")
},
1059 { B_TRANSLATE("Save image")BLocaleRoster::Default()->GetCatalog()->GetString(("Save image"
), "PaintWindow")
, HS_SAVE_IMAGE'Saim',
1060 'S', 0, this,
1061 B_TRANSLATE("Saves the image under its current name.")BLocaleRoster::Default()->GetCatalog()->GetString(("Saves the image under its current name."
), "PaintWindow")
},
1062 { B_TRANSLATE("Save image as" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Save image as"
"\xE2\x80\xA6"), "PaintWindow")
, HS_SHOW_IMAGE_SAVE_PANEL'SiSp',
1063 0, 0, this,
1064 B_TRANSLATE("Saves the image to disk.")BLocaleRoster::Default()->GetCatalog()->GetString(("Saves the image to disk."
), "PaintWindow")
},
1065 { "SEPARATOR", 0, 0, 0, NULL__null, "SEPARATOR" }, // separator
1066 { B_TRANSLATE("New project" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("New project"
"\xE2\x80\xA6"), "PaintWindow")
, HS_NEW_PAINT_WINDOW'NPtW',
1067 'N', 0, be_app,
1068 B_TRANSLATE("Creates a new empty canvas.")BLocaleRoster::Default()->GetCatalog()->GetString(("Creates a new empty canvas."
), "PaintWindow")
},
1069 { B_TRANSLATE("Open project" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Open project"
"\xE2\x80\xA6"), "PaintWindow")
, HS_SHOW_PROJECT_OPEN_PANEL'PrOp',
1070 'O', B_SHIFT_KEY, be_app,
1071 B_TRANSLATE("Opens a project from disk.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens a project from disk."
), "PaintWindow")
},
1072 { B_TRANSLATE("Save project")BLocaleRoster::Default()->GetCatalog()->GetString(("Save project"
), "PaintWindow")
, HS_SAVE_PROJECT'Sapr',
1073 'S', B_SHIFT_KEY, this,
1074 B_TRANSLATE("Saves the project under its current name.")BLocaleRoster::Default()->GetCatalog()->GetString(("Saves the project under its current name."
), "PaintWindow")
},
1075 { B_TRANSLATE("Save project as" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Save project as"
"\xE2\x80\xA6"), "PaintWindow")
, HS_SHOW_PROJECT_SAVE_PANEL'PrSp',
1076 0, 0, this,
1077 B_TRANSLATE("Saves the project to disk.")BLocaleRoster::Default()->GetCatalog()->GetString(("Saves the project to disk."
), "PaintWindow")
},
1078 { "SEPARATOR", 0, 0, 0, NULL__null, "SEPARATOR" } // separator
1079 };
1080
1081 for (uint32 i = 0; i < (sizeof(fileMenu) / sizeof(menu_item)); ++i) {
1082 _AddMenuItems(menu, fileMenu[i].label, fileMenu[i].what,
1083 fileMenu[i].shortcut, fileMenu[i].modifiers, fileMenu[i].target,
1084 fileMenu[i].help);
1085 }
1086
1087 fRecentImages = new BMenu(B_TRANSLATE("Recent images")BLocaleRoster::Default()->GetCatalog()->GetString(("Recent images"
), "PaintWindow")
);
1088 menu->AddItem(fRecentImages);
1089
1090 fRecentProjects = new BMenu(B_TRANSLATE("Recent projects")BLocaleRoster::Default()->GetCatalog()->GetString(("Recent projects"
), "PaintWindow")
);
1091 menu->AddItem(fRecentProjects);
1092
1093 // the Edit menu
1094 menu = new BMenu(B_TRANSLATE("Edit")BLocaleRoster::Default()->GetCatalog()->GetString(("Edit"
), "PaintWindow")
);
1095 fMenubar->AddItem(menu);
1096
1097 menu_item editMenu[] = {
1098 { B_TRANSLATE("Undo not available")BLocaleRoster::Default()->GetCatalog()->GetString(("Undo not available"
), "PaintWindow")
, HS_UNDO'unDo',
1099 'Z', 0, this,
1100 B_TRANSLATE("Undos the previous action.")BLocaleRoster::Default()->GetCatalog()->GetString(("Undos the previous action."
), "PaintWindow")
},
1101 { B_TRANSLATE("Redo not available")BLocaleRoster::Default()->GetCatalog()->GetString(("Redo not available"
), "PaintWindow")
, HS_REDO'reDo',
1102 'Z', B_SHIFT_KEY, this,
1103 B_TRANSLATE("Redos the action that was last undone.")BLocaleRoster::Default()->GetCatalog()->GetString(("Redos the action that was last undone."
), "PaintWindow")
},
1104 { "SEPARATOR", 0, 0, 0, NULL__null, "SEPARATOR" } // separator
1105 };
1106
1107 for (uint32 i = 0; i < (sizeof(editMenu) / sizeof(menu_item)); ++i) {
1108 _AddMenuItems(menu, editMenu[i].label, editMenu[i].what,
1109 editMenu[i].shortcut, editMenu[i].modifiers, editMenu[i].target,
1110 editMenu[i].help);
1111 }
1112
1113 BMenu* subMenu = new BMenu(B_TRANSLATE("Cut")BLocaleRoster::Default()->GetCatalog()->GetString(("Cut"
), "PaintWindow")
);
1114 menu->AddItem(subMenu);
1115
1116 BMessage *a_message = new BMessage(B_CUT);
1117 a_message->AddInt32("layers", HS_MANIPULATE_CURRENT_LAYER'Mncl');
1118 subMenu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Active layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Active layer"
), "PaintWindow")
,
1119 a_message, 'X', 0, this,
1120 B_TRANSLATE("Cuts the selection to the clipboard.")BLocaleRoster::Default()->GetCatalog()->GetString(("Cuts the selection to the clipboard."
), "PaintWindow")
));
1121
1122 a_message = new BMessage(B_CUT);
1123 a_message->AddInt32("layers", HS_MANIPULATE_ALL_LAYERS'Mnal');
1124 subMenu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("All layers")BLocaleRoster::Default()->GetCatalog()->GetString(("All layers"
), "PaintWindow")
,
1125 a_message, 'X', B_SHIFT_KEY, this,
1126 B_TRANSLATE("Cuts the selection from all layers to the clipboard.")BLocaleRoster::Default()->GetCatalog()->GetString(("Cuts the selection from all layers to the clipboard."
), "PaintWindow")
));
1127
1128 subMenu = new BMenu(B_TRANSLATE("Copy")BLocaleRoster::Default()->GetCatalog()->GetString(("Copy"
), "PaintWindow")
);
1129 menu->AddItem(subMenu);
1130 a_message = new BMessage(B_COPY);
1131 a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER'Mncl');
1132 subMenu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Active layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Active layer"
), "PaintWindow")
,
1133 a_message, 'C', 0, this,
1134 B_TRANSLATE("Copies the selection.")BLocaleRoster::Default()->GetCatalog()->GetString(("Copies the selection."
), "PaintWindow")
));
1135
1136 a_message = new BMessage(B_COPY);
1137 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1138 subMenu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("All layers")BLocaleRoster::Default()->GetCatalog()->GetString(("All layers"
), "PaintWindow")
,
1139 a_message, 'C', B_SHIFT_KEY, this,
1140 B_TRANSLATE("Copies the selection of all layers.")BLocaleRoster::Default()->GetCatalog()->GetString(("Copies the selection of all layers."
), "PaintWindow")
));
1141 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Paste as a new layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Paste as a new layer"
), "PaintWindow")
,
1142 new BMessage(B_PASTE), 'V', 0, this,
1143 B_TRANSLATE("Pastes previously copied selection as a new layer.")BLocaleRoster::Default()->GetCatalog()->GetString(("Pastes previously copied selection as a new layer."
), "PaintWindow")
));
1144 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Paste as a new project")BLocaleRoster::Default()->GetCatalog()->GetString(("Paste as a new project"
), "PaintWindow")
,
1145 new BMessage(B_PASTE), 'V', B_SHIFT_KEY, this,
1146 B_TRANSLATE("Pastes previously copied selection as a new project.")BLocaleRoster::Default()->GetCatalog()->GetString(("Pastes previously copied selection as a new project."
), "PaintWindow")
));
1147
1148 menu->AddItem(new BSeparatorItem());
1149
1150 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Grow selection")BLocaleRoster::Default()->GetCatalog()->GetString(("Grow selection"
), "PaintWindow")
,
1151 new BMessage(HS_GROW_SELECTION'GrSl'), 'G', 0, this,
1152 B_TRANSLATE("Grows the selection in all directions.")BLocaleRoster::Default()->GetCatalog()->GetString(("Grows the selection in all directions."
), "PaintWindow")
));
1153 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Shrink selection")BLocaleRoster::Default()->GetCatalog()->GetString(("Shrink selection"
), "PaintWindow")
,
1154 new BMessage(HS_SHRINK_SELECTION'SrSL'), 'H', 0, this,
1155 B_TRANSLATE("Shrinks the selection in all directions.")BLocaleRoster::Default()->GetCatalog()->GetString(("Shrinks the selection in all directions."
), "PaintWindow")
));
1156 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Invert selection")BLocaleRoster::Default()->GetCatalog()->GetString(("Invert selection"
), "PaintWindow")
,
1157 new BMessage(HS_INVERT_SELECTION'InSl'), 0, 0, this,
1158 B_TRANSLATE("Inverts the selection")BLocaleRoster::Default()->GetCatalog()->GetString(("Inverts the selection"
), "PaintWindow")
));
1159 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Clear selection")BLocaleRoster::Default()->GetCatalog()->GetString(("Clear selection"
), "PaintWindow")
,
1160 new BMessage(HS_CLEAR_SELECTION'ClSl'), 'D', 0, this,
1161 B_TRANSLATE("Un-selects all")BLocaleRoster::Default()->GetCatalog()->GetString(("Un-selects all"
), "PaintWindow")
));
1162
1163 // The Layer menu.
1164 menu = new BMenu(B_TRANSLATE("Layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Layer"
), "PaintWindow")
);
1165 fMenubar->AddItem(menu);
1166
1167 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1168 a_message->AddInt32("manipulator_type",ROTATION_MANIPULATOR);
1169 a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER'Mncl');
1170 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Rotate" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Rotate"
"\xE2\x80\xA6"), "PaintWindow")
,
1171 a_message, 'R', 0, this,
1172 B_TRANSLATE("Rotates the active layer.")BLocaleRoster::Default()->GetCatalog()->GetString(("Rotates the active layer."
), "PaintWindow")
));
1173
1174 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1175 a_message->AddInt32("manipulator_type",TRANSLATION_MANIPULATOR);
1176 a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER'Mncl');
1177 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Translate" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Translate"
"\xE2\x80\xA6"), "PaintWindow")
,
1178 a_message, 'T', 0, this,
1179 B_TRANSLATE("Moves the active layer.")BLocaleRoster::Default()->GetCatalog()->GetString(("Moves the active layer."
), "PaintWindow")
));
1180
1181// a_message = new BMessage(HS_START_MANIPULATOR);
1182// a_message->AddInt32("manipulator_type",FREE_TRANSFORM_MANIPULATOR);
1183// a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER);
1184// menu->AddItem(new PaintWindowMenuItem("Free transform test",a_message,0,0,this,"Use left shift and control to rotate and scale."));
1185
1186 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1187 a_message->AddInt32("manipulator_type",HORIZ_FLIP_MANIPULATOR);
1188 a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER'Mncl');
1189 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Flip horizontally")BLocaleRoster::Default()->GetCatalog()->GetString(("Flip horizontally"
), "PaintWindow")
,
1190 a_message, B_LEFT_ARROW, 0, this,
1191 B_TRANSLATE("Flips the active layer horizontally.")BLocaleRoster::Default()->GetCatalog()->GetString(("Flips the active layer horizontally."
), "PaintWindow")
));
1192
1193 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1194 a_message->AddInt32("manipulator_type",VERT_FLIP_MANIPULATOR);
1195 a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER'Mncl');
1196 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Flip vertically")BLocaleRoster::Default()->GetCatalog()->GetString(("Flip vertically"
), "PaintWindow")
,
1197 a_message, B_UP_ARROW, 0, this,
1198 B_TRANSLATE("Flips the active layer vertically.")BLocaleRoster::Default()->GetCatalog()->GetString(("Flips the active layer vertically."
), "PaintWindow")
));
1199
1200 menu->AddSeparatorItem();
1201
1202 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1203 a_message->AddInt32("manipulator_type",TRANSPARENCY_MANIPULATOR);
1204 a_message->AddInt32("layers",HS_MANIPULATE_CURRENT_LAYER'Mncl');
1205 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Change transparency" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Change transparency"
"\xE2\x80\xA6"), "PaintWindow")
,
1206 a_message, 0, 0, this,
1207 B_TRANSLATE("Changes the transparency of active layer.")BLocaleRoster::Default()->GetCatalog()->GetString(("Changes the transparency of active layer."
), "PaintWindow")
));
1208 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Clear layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Clear layer"
), "PaintWindow")
,
1209 new BMessage(HS_CLEAR_LAYER'Clla'), 0, 0, this,
1210 B_TRANSLATE("Clears the active layer.")BLocaleRoster::Default()->GetCatalog()->GetString(("Clears the active layer."
), "PaintWindow")
));
1211
1212 menu->AddSeparatorItem();
1213
1214 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Add layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Add layer"
), "PaintWindow")
,
1215 new BMessage(HS_ADD_LAYER_FRONT'AdLf'), '.', 0, this,
1216 B_TRANSLATE("Adds a layer to the top of this image.")BLocaleRoster::Default()->GetCatalog()->GetString(("Adds a layer to the top of this image."
), "PaintWindow")
));
1217
1218 // The Canvas menu.
1219 menu = new BMenu(B_TRANSLATE("Canvas")BLocaleRoster::Default()->GetCatalog()->GetString(("Canvas"
), "PaintWindow")
);
1220 fMenubar->AddItem(menu);
1221
1222 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1223 a_message->AddInt32("manipulator_type",ROTATION_MANIPULATOR);
1224 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1225 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Rotate" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Rotate"
"\xE2\x80\xA6"), "PaintWindow")
,
1226 a_message, 'R', B_SHIFT_KEY, this,
1227 B_TRANSLATE("Rotates all layers.")BLocaleRoster::Default()->GetCatalog()->GetString(("Rotates all layers."
), "PaintWindow")
));
1228
1229 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1230 a_message->AddInt32("manipulator_type",ROTATE_CW_MANIPULATOR);
1231 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1232 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Rotate +90°")BLocaleRoster::Default()->GetCatalog()->GetString(("Rotate +90°"
), "PaintWindow")
,
1233 a_message, 0, 0, this,
1234 B_TRANSLATE("Rotates all layers 90° clockwise.")BLocaleRoster::Default()->GetCatalog()->GetString(("Rotates all layers 90° clockwise."
), "PaintWindow")
));
1235
1236 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1237 a_message->AddInt32("manipulator_type",ROTATE_CCW_MANIPULATOR);
1238 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1239 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Rotate -90°")BLocaleRoster::Default()->GetCatalog()->GetString(("Rotate -90°"
), "PaintWindow")
,
1240 a_message, 0, 0, this,
1241 B_TRANSLATE("Rotates all layers 90° counter-clockwise.")BLocaleRoster::Default()->GetCatalog()->GetString(("Rotates all layers 90° counter-clockwise."
), "PaintWindow")
));
1242
1243 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1244 a_message->AddInt32("manipulator_type",TRANSLATION_MANIPULATOR);
1245 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1246 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Translate" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Translate"
"\xE2\x80\xA6"), "PaintWindow")
,
1247 a_message, 'T', B_SHIFT_KEY, this,
1248 B_TRANSLATE("Moves all layers.")BLocaleRoster::Default()->GetCatalog()->GetString(("Moves all layers."
), "PaintWindow")
));
1249
1250 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1251 a_message->AddInt32("manipulator_type",HORIZ_FLIP_MANIPULATOR);
1252 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1253 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Flip horizontally")BLocaleRoster::Default()->GetCatalog()->GetString(("Flip horizontally"
), "PaintWindow")
,
1254 a_message, B_LEFT_ARROW, B_SHIFT_KEY, this,
1255 B_TRANSLATE("Flips all layers horizontally.")BLocaleRoster::Default()->GetCatalog()->GetString(("Flips all layers horizontally."
), "PaintWindow")
));
1256
1257 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1258 a_message->AddInt32("manipulator_type",VERT_FLIP_MANIPULATOR);
1259 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1260 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Flip vertically")BLocaleRoster::Default()->GetCatalog()->GetString(("Flip vertically"
), "PaintWindow")
,
1261 a_message, B_UP_ARROW, B_SHIFT_KEY, this,
1262 B_TRANSLATE("Flips all layers vertically.")BLocaleRoster::Default()->GetCatalog()->GetString(("Flips all layers vertically."
), "PaintWindow")
));
1263
1264 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1265 a_message->AddInt32("manipulator_type",CROP_MANIPULATOR);
1266 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1267 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Crop" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Crop"
"\xE2\x80\xA6"), "PaintWindow")
,
1268 a_message, 'C', B_CONTROL_KEY, this,
1269 B_TRANSLATE("Crops the image.")BLocaleRoster::Default()->GetCatalog()->GetString(("Crops the image."
), "PaintWindow")
));
1270
1271 a_message = new BMessage(HS_START_MANIPULATOR'Stmi');
1272 a_message->AddInt32("manipulator_type",SCALE_MANIPULATOR);
1273 a_message->AddInt32("layers",HS_MANIPULATE_ALL_LAYERS'Mnal');
1274 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Scale" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Scale"
"\xE2\x80\xA6"), "PaintWindow")
,
1275 a_message, 'S', B_CONTROL_KEY, this,
1276 B_TRANSLATE("Scales the image.")BLocaleRoster::Default()->GetCatalog()->GetString(("Scales the image."
), "PaintWindow")
));
1277
1278 menu->AddItem(new BSeparatorItem());
1279 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Clear canvas")BLocaleRoster::Default()->GetCatalog()->GetString(("Clear canvas"
), "PaintWindow")
,
1280 new BMessage(HS_CLEAR_CANVAS'Clcv'), 0, 0, this,
1281 B_TRANSLATE("Clears all layers.")BLocaleRoster::Default()->GetCatalog()->GetString(("Clears all layers."
), "PaintWindow")
));
1282
1283 // The Window menu,
1284 menu = new BMenu(B_TRANSLATE("Window")BLocaleRoster::Default()->GetCatalog()->GetString(("Window"
), "PaintWindow")
);
1285 fMenubar->AddItem(menu);
1286
1287 // use + and - as shorcuts for zooming
1288 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Zoom in")BLocaleRoster::Default()->GetCatalog()->GetString(("Zoom in"
), "PaintWindow")
,
1289 new BMessage(HS_ZOOM_IMAGE_IN'ZImI'), '+', 0, this,
1290 B_TRANSLATE("Zooms into the image.")BLocaleRoster::Default()->GetCatalog()->GetString(("Zooms into the image."
), "PaintWindow")
));
1291 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Zoom out")BLocaleRoster::Default()->GetCatalog()->GetString(("Zoom out"
), "PaintWindow")
,
1292 new BMessage(HS_ZOOM_IMAGE_OUT'ZImO'), '-', 0, this,
1293 B_TRANSLATE("Zooms out from the image.")BLocaleRoster::Default()->GetCatalog()->GetString(("Zooms out from the image."
), "PaintWindow")
));
1294
1295 subMenu = new BMenu(B_TRANSLATE("Set zoom level")BLocaleRoster::Default()->GetCatalog()->GetString(("Set zoom level"
), "PaintWindow")
);
1296 menu->AddItem(subMenu);
1297 a_message = new BMessage(HS_SET_MAGNIFYING_SCALE'SmgS');
1298 a_message->AddFloat("magnifying_scale",0.25);
1299 subMenu->AddItem(new PaintWindowMenuItem("25%",
1300 a_message, 0, 0, this,
1301 B_TRANSLATE("Sets the zoom level to 25%.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the zoom level to 25%."
), "PaintWindow")
));
1302 a_message = new BMessage(HS_SET_MAGNIFYING_SCALE'SmgS');
1303 a_message->AddFloat("magnifying_scale",0.50);
1304 subMenu->AddItem(new PaintWindowMenuItem("50%",
1305 a_message, 0, 0, this,
1306 B_TRANSLATE("Sets the zoom level to 50%.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the zoom level to 50%."
), "PaintWindow")
));
1307 a_message = new BMessage(HS_SET_MAGNIFYING_SCALE'SmgS');
1308 a_message->AddFloat("magnifying_scale",1.0);
1309 subMenu->AddItem(new PaintWindowMenuItem("100%",
1310 a_message, 0, 0, this,
1311 B_TRANSLATE("Sets the zoom level to 100%.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the zoom level to 100%."
), "PaintWindow")
));
1312 a_message = new BMessage(HS_SET_MAGNIFYING_SCALE'SmgS');
1313 a_message->AddFloat("magnifying_scale",2.0);
1314 subMenu->AddItem(new PaintWindowMenuItem("200%",
1315 a_message, 0, 0, this,
1316 B_TRANSLATE("Sets the zoom level to 200%.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the zoom level to 200%."
), "PaintWindow")
));
1317 a_message = new BMessage(HS_SET_MAGNIFYING_SCALE'SmgS');
1318 a_message->AddFloat("magnifying_scale",4.0);
1319 subMenu->AddItem(new PaintWindowMenuItem("400%",
1320 a_message, 0, 0, this,
1321 B_TRANSLATE("Sets the zoom level to 400%.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the zoom level to 400%."
), "PaintWindow")
));
1322 a_message = new BMessage(HS_SET_MAGNIFYING_SCALE'SmgS');
1323 a_message->AddFloat("magnifying_scale",8.0);
1324 subMenu->AddItem(new PaintWindowMenuItem("800%",
1325 a_message, 0, 0, this,
1326 B_TRANSLATE("Sets the zoom level to 800%.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the zoom level to 800%."
), "PaintWindow")
));
1327
1328 subMenu = new BMenu(B_TRANSLATE("Set grid")BLocaleRoster::Default()->GetCatalog()->GetString(("Set grid"
), "PaintWindow")
);
1329 menu->AddItem(subMenu);
1330 a_message = new BMessage(HS_GRID_ADJUSTED'Grdj');
1331 a_message->AddPoint("origin",BPoint(0,0));
1332 a_message->AddInt32("unit",1);
1333 subMenu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Off")BLocaleRoster::Default()->GetCatalog()->GetString(("Off"
), "PaintWindow")
,
1334 a_message, 0, 0, this,
1335 B_TRANSLATE("Turns the grid off.")BLocaleRoster::Default()->GetCatalog()->GetString(("Turns the grid off."
), "PaintWindow")
));
1336 a_message = new BMessage(HS_GRID_ADJUSTED'Grdj');
1337 a_message->AddPoint("origin",BPoint(0,0));
1338 a_message->AddInt32("unit",2);
1339 subMenu->AddItem(new PaintWindowMenuItem("2x2",
1340 a_message, 0, 0, this,
1341 B_TRANSLATE("Sets the grid to 2 by 2 pixels.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the grid to 2 by 2 pixels."
), "PaintWindow")
));
1342 a_message = new BMessage(HS_GRID_ADJUSTED'Grdj');
1343 a_message->AddPoint("origin",BPoint(0,0));
1344 a_message->AddInt32("unit",4);
1345 subMenu->AddItem(new PaintWindowMenuItem("4x4",
1346 a_message, 0, 0, this,
1347 B_TRANSLATE("Sets the grid to 4 by 4 pixels.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the grid to 4 by 4 pixels."
), "PaintWindow")
));
1348 a_message = new BMessage(HS_GRID_ADJUSTED'Grdj');
1349 a_message->AddPoint("origin",BPoint(0,0));
1350 a_message->AddInt32("unit",8);
1351 subMenu->AddItem(new PaintWindowMenuItem("8x8",
1352 a_message, 0, 0, this,
1353 B_TRANSLATE("Sets the grid to 8 by 8 pixels.")BLocaleRoster::Default()->GetCatalog()->GetString(("Sets the grid to 8 by 8 pixels."
), "PaintWindow")
));
1354 subMenu->SetRadioMode(true);
1355 subMenu->ItemAt(0)->SetMarked(true);
1356
1357 // use here the same shortcut as the tracker uses == Y
1358 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Resize to fit")BLocaleRoster::Default()->GetCatalog()->GetString(("Resize to fit"
), "PaintWindow")
,
1359 new BMessage(HS_RESIZE_WINDOW_TO_FIT'RwTF'), 'Y', 0, this,
1360 B_TRANSLATE("Resizes the window to fit image and screen.")BLocaleRoster::Default()->GetCatalog()->GetString(("Resizes the window to fit image and screen."
), "PaintWindow")
));
1361 menu->AddSeparatorItem();
1362 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Colors" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Colors"
"\xE2\x80\xA6"), "PaintWindow")
,
1363 new BMessage(HS_SHOW_COLOR_WINDOW'ShCw'), 'P', 0, this,
1364 B_TRANSLATE("Opens the colors window.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the colors window."
), "PaintWindow")
));
1365 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Layers" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Layers"
"\xE2\x80\xA6"), "PaintWindow")
,
1366 new BMessage(HS_SHOW_LAYER_WINDOW'ShLW'), 'L', 0, this,
1367 B_TRANSLATE("Opens the layers window.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the layers window."
), "PaintWindow")
));
1368 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Tools" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Tools"
"\xE2\x80\xA6"), "PaintWindow")
,
1369 new BMessage(HS_SHOW_TOOL_WINDOW'ShtW'), 'K', 0, this,
1370 B_TRANSLATE("Opens the tool selection window.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the tool selection window."
), "PaintWindow")
));
1371 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Tool setup" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Tool setup"
"\xE2\x80\xA6"), "PaintWindow")
,
1372 new BMessage(HS_SHOW_TOOL_SETUP_WINDOW'StsW'), 'M', 0, this,
1373 B_TRANSLATE("Opens the tool setup window.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the tool setup window."
), "PaintWindow")
));
1374 menu->AddItem(new PaintWindowMenuItem(B_TRANSLATE("Brushes" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Brushes"
"\xE2\x80\xA6"), "PaintWindow")
,
1375 new BMessage(HS_SHOW_BRUSH_STORE_WINDOW'Sbsw'), 'B', 0, this,
1376 B_TRANSLATE("Opens the window of stored brushes.")BLocaleRoster::Default()->GetCatalog()->GetString(("Opens the window of stored brushes."
), "PaintWindow")
));
1377
1378// menu->AddItem(new PaintWindowMenuItem(_StringForId(NEW_PAINT_WINDOW_STRING),new BMessage(HS_NEW_PAINT_WINDOW),'N',0,this,_StringForId(NEW_PROJECT_HELP_STRING)));
1379// menu->AddSeparatorItem();
1380// menu->AddItem(new BMenuItem(B_TRANSLATE("Window settings" B_UTF8_ELLIPSIS), new BMessage(HS_SHOW_VIEW_SETUP_WINDOW)));
1381
1382 // This will be only temporary place for add-ons. Later they will be spread
1383 // in the menu hierarchy according to their types.
1384 menu = new BMenu(B_TRANSLATE("Add-ons")BLocaleRoster::Default()->GetCatalog()->GetString(("Add-ons"
), "PaintWindow")
);
1385 thread_id add_on_adder_thread = spawn_thread(_AddAddOnsToMenu,
1386 "add_on_adder_thread", B_NORMAL_PRIORITY10, this);
1387 resume_thread(add_on_adder_thread);
1388 fMenubar->AddItem(menu);
1389
1390 _ChangeMenuMode(NO_IMAGE_MENU);
1391
1392 return true;
1393}
1394
1395
1396int32
1397PaintWindow::_AddAddOnsToMenu(void* data)
1398{
1399 PaintWindow* paintWindow = static_cast<PaintWindow*> (data);
1400 if (!paintWindow)
1401 return B_ERROR(-1);
1402
1403 ManipulatorServer* server = ManipulatorServer::Instance();
1404 if (!server)
1405 return B_ERROR(-1);
1406
1407 while (!server->AddOnsLoaded() || !paintWindow->KeyMenuBar())
1408 snooze(50000);
1409
1410 if (BMenuBar* menuBar = paintWindow->KeyMenuBar()) {
1411 BMenuItem* item = menuBar->FindItem(B_TRANSLATE("Add-ons")BLocaleRoster::Default()->GetCatalog()->GetString(("Add-ons"
), "PaintWindow")
);
1412 if (BMenu* addOnMenu = item->Submenu()) {
1413 if (paintWindow->Lock()) {
1414 ImageList::const_iterator it;
1415 const ImageList& imageList = server->AddOnImageList();
1416 std::map<BString, int32> manip_map;
1417
1418 for (it = imageList.begin(); it != imageList.end(); ++it) {
1419 int32* add_on_version;
1420 status_t status = get_image_symbol(*it, "add_on_api_version",
1421 B_SYMBOL_TYPE_DATA0x1, (void**)&add_on_version);
1422
1423 if (status != B_OK((int)0))
1424 continue;
1425
1426 if (*add_on_version == ADD_ON_API_VERSION) {
1427 Manipulator* (*Instantiate)(BBitmap*, ManipulatorInformer*);
1428 status_t status = get_image_symbol(*it, "instantiate_add_on",
1429 B_SYMBOL_TYPE_TEXT0x2, (void**)&Instantiate);
1430 if (status == B_OK((int)0)) {
1431 Manipulator *manipulator = Instantiate(NULL__null, NULL__null);
1432
1433 if (manipulator != NULL__null) {
1434 manip_map.insert(std::pair<BString, int32>(BString(manipulator->ReturnName()), *it));
1435
1436 delete manipulator;
1437 manipulator = NULL__null;
1438 }
1439 }
1440 }
1441 }
1442
1443 for (auto it = manip_map.begin(); it != manip_map.end(); ++it) {
1444 int32 id = it->second;
1445 Manipulator* (*Instantiate)(BBitmap*, ManipulatorInformer*);
1446 status_t status = get_image_symbol(id, "instantiate_add_on",
1447 B_SYMBOL_TYPE_TEXT0x2, (void**)&Instantiate);
1448 if (status == B_OK((int)0)) {
1449 Manipulator *manipulator = Instantiate(NULL__null, NULL__null);
1450
1451 if (manipulator != NULL__null) {
1452 BMessage* message = new BMessage(HS_START_MANIPULATOR'Stmi');
1453 message->AddInt32("image_id", id);
1454 message->AddInt32("layers", HS_MANIPULATE_CURRENT_LAYER'Mncl');
1455 message->AddInt32("manipulator_type", ADD_ON_MANIPULATOR);
1456
1457 addOnMenu->AddItem(new PaintWindowMenuItem(
1458 manipulator->ReturnName(),
1459 message, 0, 0, paintWindow,
1460 manipulator->ReturnHelpString()));
1461
1462 delete manipulator;
1463 manipulator = NULL__null;
1464 }
1465 }
1466 }
1467 addOnMenu->SetTargetForItems(paintWindow);
1468 paintWindow->Unlock();
1469 }
1470
1471 if (paintWindow->fImageView)
1472 addOnMenu->SetTargetForItems(paintWindow->fImageView);
1473 return B_OK((int)0);
1474 }
1475 }
1476 return B_ERROR(-1);
1477}
1478
1479
1480status_t
1481PaintWindow::OpenImageView(int32 width, int32 height)
1482{
1483 // The image-view should be at most as large as backgroundview
1484 // but not larger than image width and height.
1485 Lock(); // Lock while we take background's bounds.
1486 fImageView = new ImageView(fBackground->Bounds(),width,height);
1487 Unlock();
1488
1489 // return true because we were successfull
1490 return true;
1491}
1492
1493
1494status_t
1495PaintWindow::AddImageView()
1496{
1497 // We have to lock as this functionmight be
1498 // called from outside the window's thread.
1499 Lock();
1500
1501 // put the view as target for scrollbars
1502 fBackground->SetTarget(fImageView);
1503 // Change the regular help-view's message.
1504// BMessage *help_message = new BMessage(HS_REGULAR_HELP_MESSAGE);
1505// help_message->AddString("message",HS_DRAW_MODE_HELP_MESSAGE);
1506// PostMessage(help_message,this);
1507// delete help_message;
1508
1509 // Change the menu-mode to enable all items.
1510 _ChangeMenuMode(FULL_MENU);
1511
1512 // Adjust image's position and size.
1513 fImageView->adjustSize();
1514 fImageView->adjustPosition();
1515 // Update the image's scroll-bars.
1516 fImageView->adjustScrollBars();
1517
1518 // Change image for target for certain menu-items. These cannot be changed
1519 // before image is added as a child to this window.
1520 fMenubar->FindItem(B_TRANSLATE("Edit")BLocaleRoster::Default()->GetCatalog()->GetString(("Edit"
), "PaintWindow")
)->Submenu()->SetTargetForItems(fImageView);
1521 fMenubar->FindItem(B_TRANSLATE("Paste as a new project")BLocaleRoster::Default()->GetCatalog()->GetString(("Paste as a new project"
), "PaintWindow")
)->SetTarget(be_app);
1522
1523 BMenu *menu = fMenubar->FindItem(B_TRANSLATE("Edit")BLocaleRoster::Default()->GetCatalog()->GetString(("Edit"
), "PaintWindow")
)->Submenu();
1524 if (menu != NULL__null) {
1525 BMenu *sub_menu;
1526 for (int32 i=0;i<menu->CountItems();i++) {
1527 sub_menu = menu->SubmenuAt(i);
1528 if (sub_menu != NULL__null)
1529 sub_menu->SetTargetForItems(fImageView);
1530 }
1531 }
1532
1533 fMenubar->FindItem(B_TRANSLATE("Add-ons")BLocaleRoster::Default()->GetCatalog()->GetString(("Add-ons"
), "PaintWindow")
)->Submenu()->SetTargetForItems(fImageView);
1534 fMenubar->FindItem(HS_ADD_LAYER_FRONT'AdLf')->SetTarget(fImageView);
1535 fMenubar->FindItem(B_TRANSLATE("Crop" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Crop"
"\xE2\x80\xA6"), "PaintWindow")
)->SetTarget(fImageView);
1536 fMenubar->FindItem(HS_CLEAR_CANVAS'Clcv')->SetTarget(fImageView);
1537 fMenubar->FindItem(HS_CLEAR_LAYER'Clla')->SetTarget(fImageView);
1538 fMenubar->FindItem(HS_ZOOM_IMAGE_IN'ZImI')->SetTarget(fImageView);
1539 fMenubar->FindItem(HS_ZOOM_IMAGE_OUT'ZImO')->SetTarget(fImageView);
1540 fMenubar->FindItem(B_TRANSLATE("Set zoom level")BLocaleRoster::Default()->GetCatalog()->GetString(("Set zoom level"
), "PaintWindow")
)->Submenu()->SetTargetForItems(fImageView);
1541 fMenubar->FindItem(B_TRANSLATE("Set grid")BLocaleRoster::Default()->GetCatalog()->GetString(("Set grid"
), "PaintWindow")
)->Submenu()->SetTargetForItems(fImageView);
1542
1543 std::stack<BMenu*> menus;
1544 menus.push(static_cast<BMenu*> (NULL__null));
1545 for (int32 i = 0; i < fMenubar->CountItems(); ++i) {
1546 if (BMenu* subMenu = fMenubar->ItemAt(i)->Submenu())
1547 menus.push(subMenu);
1548 }
1549
1550 // Change the image as target for all menu-items that have HS_START_MANIPULATOR
1551 // as their message's what constant.
1552 menu = menus.top();
1553 menus.pop();
1554 while (menu != NULL__null) {
1555 for (int32 i = 0; i < menu->CountItems(); ++i) {
1556 if (menu->ItemAt(i)->Command() == HS_START_MANIPULATOR'Stmi')
1557 menu->ItemAt(i)->SetTarget(fImageView);
1558
1559 if (menu->ItemAt(i)->Submenu() != NULL__null)
1560 menus.push(menu->ItemAt(i)->Submenu());
1561 }
1562 menu = menus.top();
1563 menus.pop();
1564 }
1565
1566 // This allows Alt-+ next to the backspace key to work (the menu item shortcut only works
1567 // with the + key on the numeric keypad)
1568 AddShortcut('=', B_COMMAND_KEY, new BMessage(HS_ZOOM_IMAGE_IN'ZImI'), fImageView);
1569
1570 // change the name of the image and the project in the image-view
1571 if (fProjectEntry.InitCheck() == B_OK((int)0)) {
1572 char name[B_PATH_NAME_LENGTH(1024)];
1573 fProjectEntry.GetName(name);
1574 fImageView->SetProjectName(name);
1575 }
1576 else {
1577 BString format("%s - %ld");
1578 BString title;
1579 title.SetToFormat(format, B_TRANSLATE("Untitled")BLocaleRoster::Default()->GetCatalog()->GetString(("Untitled"
), "PaintWindow")
,
1580 sgUntitledWindowNumber++);
1581 fImageView->SetProjectName(title);
1582 }
1583 if (fImageEntry.InitCheck() == B_OK((int)0)) {
1584 char name[B_PATH_NAME_LENGTH(1024)];
1585 fImageEntry.GetName(name);
1586 fImageView->SetImageName(name);
1587 }
1588 fStatusView->DisplayToolsAndColors();
1589 // Finally unlock the window.
1590 _ResizeToImage();
1591 Unlock();
1592
1593 // We can update ourselves to the layer-window.
1594 LayerWindow::ActiveWindowChanged(this, fImageView->ReturnImage()->LayerList(),
1595 fImageView->ReturnImage()->ReturnThumbnailImage());
1596
1597 return B_OK((int)0);
1598}
1599
1600
1601void
1602PaintWindow::_ResizeToImage()
1603{
1604 if (!fImageView)
1605 return;
1606
1607 if (Image* image = fImageView->ReturnImage()) {
1608 BRect frame = _PreferredSize(image);
1609
1610 if (Frame() != frame)
1611 fUserFrame = Frame();
1612
1613 MoveTo(frame.LeftTop());
1614 ResizeTo(frame.Width(), frame.Height());
1615 }
1616}
1617
1618
1619BRect
1620PaintWindow::_PreferredSize(Image* image) const
1621{
1622 int32* tokens = 0;
1623 int32 tokenCount = 0;
1624 status_t status = BPrivate::get_window_order(current_workspace(), &tokens,
1625 &tokenCount);
1626
1627 float tabHeight = 21.0;
1628 float borderSize = 5.0;
1629 if (status == B_OK((int)0) && tokens && tokenCount > 0) {
1630 for (int32 i = 0; i < tokenCount; ++i) {
1631 if (client_window_info* windowInfo = get_window_info(tokens[i])) {
1632 if (!windowInfo->is_mini && !windowInfo->show_hide_level > 0) {
1633 tabHeight = windowInfo->tab_height;
1634 borderSize = windowInfo->border_size;
1635 free(windowInfo);
1636 break;
1637 }
1638 free(windowInfo);
1639 }
1640 }
1641 free(tokens);
1642 }
1643
1644 BRect screenFrame = BScreen().Frame().OffsetToCopy(B_ORIGIN);
1645 screenFrame.top += tabHeight;
1646 screenFrame.InsetBy(borderSize, borderSize);
1647
1648 BRect rect = Frame();
1649 const float scale = fImageView->getMagScale();
1650 const float width = (scale * image->Width());
1651 if (screenFrame.Width() < width) {
1652 rect.left = borderSize;
1653 rect.right = rect.left + screenFrame.Width();
1654 } else {
1655 rect.right = rect.left + width;
1656 }
1657
1658 const float height = (scale * image->Height());
1659 if (screenFrame.Height() < height) {
1660 rect.top = tabHeight + borderSize;
1661 rect.bottom = rect.top + screenFrame.Height();
1662 } else {
1663 rect.bottom = rect.top + height;
1664 }
1665
1666 return rect;
1667}
1668
1669
1670int32
1671PaintWindow::save_image(void* data)
1672{
1673 int32 status = B_ERROR(-1);
1674 printf("Error: %s\n", strerror(status));
1675 if (PaintWindow *window = static_cast<PaintWindow*>(data)) {
1676 thread_id sender;
1677 BMessage *message = NULL__null;
1678 receive_data(&sender, (void*)&message, sizeof(BMessage*));
1679
1680 status = window->_SaveImage(message);
1681
1682 if (status == B_OK((int)0)) {
1683 if (message->GetInt32("TryAgain", false)) {
1684 if (message->GetInt32("quitAll", false))
1685 be_app_messenger.SendMessage(B_QUIT_REQUESTED);
1686 else
1687 BMessenger(window).SendMessage(B_QUIT_REQUESTED);
1688 }
1689 }
1690 delete message;
1691 }
1692 return status;
1693}
1694
1695
1696status_t
1697PaintWindow::_SaveImage(BMessage *message)
1698{
1699 status_t status = B_ERROR(-1);
1700 if (fImageView->Freeze() == B_OK((int)0)) {
1701 BString name;
1702 entry_ref ref;
1703 if (message->FindString("name", &name) != B_OK((int)0)
1704 || message->FindRef("directory", &ref) != B_OK((int)0))
1705 return status;
1706
1707 BDirectory directory(&ref);
1708 // store the entry-ref
1709 status = fImageEntry.SetTo(&directory, name.String(), true);
Value stored to 'status' is never read
1710
1711 // Only one save ref is received so we do not need to loop.
1712 BFile file;
1713 if ((status = file.SetTo(&directory, name.String(), B_WRITE_ONLY0x0001 |
1714 B_CREATE_FILE0x0200 | B_ERASE_FILE0x0400)) != B_OK((int)0)) {
1715 fImageView->UnFreeze();
1716 return status;
1717 }
1718
1719 // Create a BNodeInfo for this file and set the MIME-type and preferred
1720 // app. Get and set the app signature, not sure why it's commented out.
1721 BNodeInfo nodeInfo(&file);
1722 nodeInfo.SetType(fSettings.FindString(skMimeType));
1723
1724 // app_info info;
1725 // be_app->GetAppInfo(&info);
1726 // nodeinfo.SetPreferredApp(info.signature);
1727
1728 // here we should save some attributes with the file
1729 BNode node(&directory, message->FindString("name"));
1730 writeAttributes(node);
1731
1732 if (Lock()) {
1733 // re-render with white alpha bg for saving
1734 fImageView->ReturnImage()->Render(false);
1735 Unlock();
1736 }
1737 // here translate the data using a BitmapStream-object
1738 BBitmap* bitmap = fImageView->ReturnImage()->ReturnRenderedImage();
1739 printf("Bitmap at 0,0: 0x%8lx\n",*((uint32*)(bitmap->Bits())));
1740
1741 // TODO: check if we leak here
1742 BBitmapStream* bitmapStream = new BBitmapStream(bitmap);
1743 BTranslatorRoster* roster = BTranslatorRoster::Default();
1744
1745 uint32 translatorType;
1746 fSettings.FindUInt32(skTranslatorType, &translatorType);
1747 status = roster->Translate(bitmapStream, (const translator_info*)NULL__null,
1748 (BMessage*)NULL__null, &file, translatorType, B_TRANSLATOR_BITMAP);
1749 fImageView->UnFreeze();
1750
1751 if (status == B_OK((int)0)) {
1752 char title[B_FILE_NAME_LENGTH(256)];
1753 fImageEntry.GetName(title);
1754 if (Lock()) {
1755 fImageView->ResetChangeStatistics(false, true);
1756 fImageView->SetImageName(title);
1757
1758 // BMenuItem *item = fMenubar->FindItem(HS_SAVE_IMAGE);
1759 // if (item) item->SetEnabled(true);
1760
1761 Unlock();
1762 }
1763
1764 BPath path;
1765 fImageEntry.GetPath(&path);
1766
1767 // Also change this new path into the settings.
1768 SettingsServer* server = SettingsServer::Instance();
1769 server->AddRecentImagePath(path.Path());
1770
1771 path.GetParent(&path);
1772 if (path.Path() != NULL__null) {
1773 server->SetValue(SettingsServer::Application, skImageSavePath,
1774 path.Path());
1775 }
1776 } else {
1777 printf("Error while saving: %s\n", strerror(status));
1778 }
1779 }
1780
1781 if (Lock()) {
1782 fImageView->ReturnImage()->Render();
1783 fImageView->Invalidate();
1784 Unlock();
1785 }
1786
1787 return status;
1788}
1789
1790
1791int32
1792PaintWindow::save_project(void* data)
1793{
1794 status_t status = B_ERROR(-1);
1795 if (PaintWindow* window = static_cast<PaintWindow*>(data)) {
1796 thread_id sender;
1797 BMessage* message = NULL__null;
1798 receive_data(&sender, (void*)&message, sizeof(BMessage*));
1799
1800 status = window->_SaveProject(message);
1801
1802 if (status == B_OK((int)0)) {
1803 if (message->GetInt32("TryAgain", 0)) {
1804 if (message->GetInt32("quitAll", 0))
1805 be_app_messenger.SendMessage(B_QUIT_REQUESTED);
1806 else
1807 BMessenger(window).SendMessage(B_QUIT_REQUESTED);
1808 }
1809 }
1810 delete message;
1811 }
1812 return status;
1813}
1814
1815
1816status_t
1817PaintWindow::_SaveProject(BMessage *message)
1818{
1819 if (fImageView->Freeze() == B_OK((int)0)) {
1820 BString name;
1821 entry_ref ref;
1822 if (message->FindString("name", &name) != B_OK((int)0)
1823 || message->FindRef("directory", &ref) != B_OK((int)0))
1824 return B_ERROR(-1);
1825
1826 BDirectory directory(&ref);
1827 // store the entry-ref
1828 fProjectEntry.SetTo(&directory, name.String(), true);
1829
1830 // Only one save ref is received so we do not need to loop.
1831 BFile file;
1832 if (file.SetTo(&directory, name.String(), B_WRITE_ONLY0x0001 |
1833 B_CREATE_FILE0x0200 | B_ERASE_FILE0x0400) != B_OK((int)0)) {
1834 fImageView->UnFreeze();
1835 return B_ERROR(-1);
1836 }
1837
1838 // Create a BNodeInfo for this file and set the MIME-type and preferred
1839 // app. Get and set the app signature, not sure why it's commented out.
1840 BNodeInfo nodeInfo(&file);
1841 nodeInfo.SetType(HS_PROJECT_MIME_STRING"application/x-vnd.artpaint-project-file");
1842
1843 // app_info info;
1844 // be_app->GetAppInfo(&info);
1845 // nodeinfo.SetPreferredApp(info.signature);
1846
1847 // The project-file will be written in the endianness of the host.
1848 // First word of the file will mark the endianness. If its 0xFFFFFFFF
1849 // the file is little-endian if it is 0x00000000, the file is big-endian.
1850 int32 endianness = 0xFFFFFFFF;
1851 if (B_HOST_IS_BENDIAN0 == 1)
1852 endianness = 0x00000000;
1853
1854 // Write the endianness
1855 if (file.Write(&endianness, sizeof(int32)) != sizeof(int32)) {
1856 fImageView->UnFreeze();
1857 return B_ERROR(-1);
1858 }
1859
1860 // Write the file-id.
1861 int32 id = PROJECT_FILE_ID0x01010101;
1862 if (file.Write(&id, sizeof(int32)) != sizeof(int32)) {
1863 fImageView->UnFreeze();
1864 return B_ERROR(-1);
1865 }
1866
1867 // Write the number of sections that the file contains. Currently there
1868 // are only two sections.
1869 int32 sectionCount = 2;
1870 if (file.Write(&sectionCount, sizeof(int32)) != sizeof(int32)) {
1871 fImageView->UnFreeze();
1872 return B_ERROR(-1);
1873 }
1874
1875 // First write the dimensions section. The real dimensions of the image
1876 // are written to the file.
1877 int32 marker = PROJECT_FILE_SECTION_START0x02020202;
1878 if (file.Write(&marker, sizeof(int32)) != sizeof(int32)) {
1879 fImageView->UnFreeze();
1880 return B_ERROR(-1);
1881 }
1882
1883 // Here write the section type.
1884 int32 type = PROJECT_FILE_DIMENSION_SECTION_ID0x11001100;
1885 if (file.Write(&type, sizeof(int32)) != sizeof(int32)) {
1886 fImageView->UnFreeze();
1887 return B_ERROR(-1);
1888 }
1889
1890 // Leave room for the section-length
1891 file.Seek(sizeof(int64), SEEK_CUR1);
1892
1893 // Here write the width and height.
1894 int32 width = int32(fImageView->ReturnImage()->Width());
1895 int32 height = int32(fImageView->ReturnImage()->Height());
1896
1897 int64 bytesWritten = 0;
1898 bytesWritten = file.Write(&width, sizeof(int32));
1899 bytesWritten += file.Write(&height, sizeof(int32));
1900
1901 if (bytesWritten != 2 * sizeof(int32)) {
1902 fImageView->UnFreeze();
1903 return B_ERROR(-1);
1904 }
1905
1906 file.Seek(-bytesWritten - sizeof(int64), SEEK_CUR1);
1907 if (file.Write(&bytesWritten, sizeof(int64)) != sizeof(int64)) {
1908 fImageView->UnFreeze();
1909 return B_ERROR(-1);
1910 }
1911 file.Seek(bytesWritten, SEEK_CUR1);
1912
1913 marker = PROJECT_FILE_SECTION_END0x02020203;
1914 if (file.Write(&marker, sizeof(int32)) != sizeof(int32)) {
1915 fImageView->UnFreeze();
1916 return B_ERROR(-1);
1917 }
1918
1919 // Here starts the layer-section.
1920 marker = PROJECT_FILE_SECTION_START0x02020202;
1921 if (file.Write(&marker, sizeof(int32)) != sizeof(int32)) {
1922 fImageView->UnFreeze();
1923 return B_ERROR(-1);
1924 }
1925
1926 id = PROJECT_FILE_LAYER_SECTION_ID0x22002200;
1927 if (file.Write(&id, sizeof(int32)) != sizeof(int32)) {
1928 fImageView->UnFreeze();
1929 return B_ERROR(-1);
1930 }
1931
1932 // Leave some room for the length.
1933 file.Seek(sizeof(int64),SEEK_CUR1);
1934
1935 // Here tell the image to write layers.
1936 bytesWritten = fImageView->ReturnImage()->WriteLayers(file);
1937
1938 file.Seek(-bytesWritten - sizeof(int64), SEEK_CUR1);
1939 if (file.Write(&bytesWritten, sizeof(int64)) != sizeof(int64)) {
1940 fImageView->UnFreeze();
1941 return B_ERROR(-1);
1942 }
1943 file.Seek(bytesWritten, SEEK_CUR1);
1944
1945 // Write the end-marker for the layer-section.
1946 marker = PROJECT_FILE_SECTION_END0x02020203;
1947 if (file.Write(&marker, sizeof(int32)) != sizeof(int32)) {
1948 fImageView->UnFreeze();
1949 return B_ERROR(-1);
1950 }
1951
1952 // Now we are happily at the end of writing.
1953 fImageView->ResetChangeStatistics(true, false);
1954 fImageView->UnFreeze();
1955
1956 char title[256];
1957 fProjectEntry.GetName(title);
1958 if (Lock()) {
1959 fImageView->SetProjectName(title);
1960
1961 // This must come after the project's name has been set.
1962 LayerWindow::ActiveWindowChanged(this,
1963 fImageView->ReturnImage()->LayerList(),
1964 fImageView->ReturnImage()->ReturnThumbnailImage());
1965
1966 // BMenuItem *item = fMenubar->FindItem(HS_SAVE_PROJECT);
1967 // if (item) item->SetEnabled(true);
1968
1969 Unlock();
1970 }
1971
1972 BPath path;
1973 fProjectEntry.GetPath(&path);
1974
1975 // Also change this new path into the settings.
1976 SettingsServer* server = SettingsServer::Instance();
1977 server->AddRecentProjectPath(path.Path());
1978
1979 path.GetParent(&path);
1980 if (path.Path() != NULL__null) {
1981 server->SetValue(SettingsServer::Application, skProjectSavePath,
1982 path.Path());
1983 }
1984 return B_OK((int)0);
1985 }
1986 return B_ERROR(-1);
1987}
1988
1989
1990void
1991PaintWindow::writeAttributes(BNode& node)
1992{
1993 float zoom = 1;
1994 BPoint point(0.0, 0.0);
1995
1996 if (fImageView && fImageView->LockLooper()) {
1997 point = fImageView->LeftTop();
1998 zoom = fImageView->getMagScale();
1999 fImageView->UnlockLooper();
2000 }
2001
2002 fSettings.ReplaceFloat(skZoom, zoom);
2003 fSettings.ReplacePoint(skPosition, point);
2004
2005 BRect frame = Frame();
2006 node.WriteAttr("ArtP:zoom_level", B_FLOAT_TYPE, 0, &zoom, sizeof(float));
2007 node.WriteAttr("ArtP:frame_rect", B_RECT_TYPE, 0, &frame, sizeof(BRect));
2008 node.WriteAttr("ArtP:view_position", B_POINT_TYPE, 0, &point, sizeof(BPoint));
2009}
2010
2011
2012void
2013PaintWindow::ReadAttributes(const BNode& node)
2014{
2015 if (Lock()) {
2016 float zoom;
2017 if (node.ReadAttr("ArtP:zoom_level", B_FLOAT_TYPE, 0, &zoom,
2018 sizeof(float)) == sizeof(float)) {
2019 if (fImageView)
2020 fImageView->setMagScale(zoom);
2021 fSettings.ReplaceFloat(skZoom, zoom);
2022 }
2023
2024 BPoint position;
2025 if (node.ReadAttr("ArtP:view_position" ,B_POINT_TYPE, 0, &position,
2026 sizeof(BPoint)) == sizeof(BPoint)) {
2027 if (fImageView)
2028 fImageView->ScrollTo(position);
2029 fSettings.ReplacePoint(skPosition, position);
2030 }
2031
2032 BRect frame;
2033 if (node.ReadAttr("ArtP:frame_rect", B_RECT_TYPE, 0, &frame,
2034 sizeof(BRect)) == sizeof(BRect)) {
2035 frame = FitRectToScreen(frame);
2036 MoveTo(frame.left, frame.top);
2037 fSettings.ReplaceRect(skFrame, frame);
2038 ResizeTo(frame.Width(), frame.Height());
2039 }
2040
2041 Unlock();
2042 }
2043}
2044
2045
2046void
2047PaintWindow::_AddMenuItems(BMenu* menu, BString label, uint32 what,
2048 char shortcut, uint32 modifiers, BHandler* target, BString help)
2049{
2050 if (label != "SEPARATOR" && help != "SEPARATOR") {
2051 BMenuItem* item = new PaintWindowMenuItem(label,
2052 new BMessage(what), shortcut, modifiers, this, help);
2053 menu->AddItem(item);
2054 item->SetTarget(target);
2055 } else {
2056 menu->AddSeparatorItem();
2057 }
2058}
2059
2060
2061void
2062PaintWindow::_AddRecentMenuItems(BMenu* menu, const StringList* list)
2063{
2064 menu->RemoveItems(0, menu->CountItems(), true);
2065
2066 BPath path;
2067 StringList::const_iterator it;
2068 for (it = list->begin(); it != list->end(); ++it) {
2069 entry_ref ref;
2070 path.SetTo((*it).String(), NULL__null, true);
2071 if (get_ref_for_path(path.Path(), &ref) == B_OK((int)0)) {
2072 BMessage* message = new BMessage(B_REFS_RECEIVED);
2073 message->AddRef("refs", &ref);
2074
2075 PaintWindowMenuItem* item = new PaintWindowMenuItem(path.Leaf(),
2076 message, 0, 0, this, path.Path());
2077 menu->AddItem(item);
2078 item->SetTarget(be_app);
2079 }
2080 }
2081}
2082
2083
2084/*!
2085 This function changes the enability of some menu-items. The
2086 parameter is used as a guide to what should be enabled and not.
2087*/
2088void
2089PaintWindow::_ChangeMenuMode(menu_modes newMode)
2090{
2091 int32 count = fMenubar->CountItems();
2092 for (int32 i = 0; i < count; ++i) {
2093 if (BMenuItem* currentItem = fMenubar->ItemAt(i)) {
2094 currentItem->SetEnabled(true);
2095 if (BMenu* subMenu = currentItem->Submenu())
2096 _EnableMenuItems(subMenu);
2097 }
2098 }
2099
2100 switch (newMode) {
2101 case NO_IMAGE_MENU: {
2102 // In this case we disable some additional items and then let fall
2103 // through to the next case that disables most of the other items.
2104 _DisableMenuItem(B_TRANSLATE("Resize to fit")BLocaleRoster::Default()->GetCatalog()->GetString(("Resize to fit"
), "PaintWindow")
);
2105 _DisableMenuItem(B_TRANSLATE("Zoom in")BLocaleRoster::Default()->GetCatalog()->GetString(("Zoom in"
), "PaintWindow")
);
2106 _DisableMenuItem(B_TRANSLATE("Zoom out")BLocaleRoster::Default()->GetCatalog()->GetString(("Zoom out"
), "PaintWindow")
);
2107 _DisableMenuItem(B_TRANSLATE("Set zoom level")BLocaleRoster::Default()->GetCatalog()->GetString(("Set zoom level"
), "PaintWindow")
);
2108 _DisableMenuItem(B_TRANSLATE("Set grid")BLocaleRoster::Default()->GetCatalog()->GetString(("Set grid"
), "PaintWindow")
);
2109 } // fall through
2110
2111 case MINIMAL_MENU: {
2112 // In this case most of the items should be disabled.
2113 _DisableMenuItem(B_TRANSLATE("Canvas")BLocaleRoster::Default()->GetCatalog()->GetString(("Canvas"
), "PaintWindow")
);
2114 _DisableMenuItem(B_TRANSLATE("Layer")BLocaleRoster::Default()->GetCatalog()->GetString(("Layer"
), "PaintWindow")
);
2115 _DisableMenuItem(B_TRANSLATE("Save image as" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Save image as"
"\xE2\x80\xA6"), "PaintWindow")
);
2116 _DisableMenuItem(B_TRANSLATE("Save project as" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Save project as"
"\xE2\x80\xA6"), "PaintWindow")
);
2117 _DisableMenuItem(B_TRANSLATE("Edit")BLocaleRoster::Default()->GetCatalog()->GetString(("Edit"
), "PaintWindow")
);
2118 _DisableMenuItem(B_TRANSLATE("Add-ons")BLocaleRoster::Default()->GetCatalog()->GetString(("Add-ons"
), "PaintWindow")
);
2119 } // fall through
2120
2121 case FULL_MENU: {
2122 // In this case we should not disable any menu-items.
2123 if ((newMode == FULL_MENU && fImageEntry.InitCheck() != B_OK((int)0))
2124 || newMode != FULL_MENU) {
2125 if (BMenuItem* item = fMenubar->FindItem(HS_SAVE_IMAGE'Saim'))
2126 item->SetEnabled(false);
2127 }
2128
2129 if ((newMode == FULL_MENU && fProjectEntry.InitCheck() != B_OK((int)0))
2130 || newMode != FULL_MENU) {
2131 if (BMenuItem* item = fMenubar->FindItem(HS_SAVE_PROJECT'Sapr'))
2132 item->SetEnabled(false);
2133 }
2134 } break;
2135 }
2136}
2137
2138
2139void
2140PaintWindow::_EnableMenuItems(BMenu* menu)
2141{
2142 int32 count = menu->CountItems();
2143 for (int32 i = 0; i < count; ++i) {
2144 if (BMenuItem* currentItem = menu->ItemAt(i)) {
2145 currentItem->SetEnabled(true);
2146 if (BMenu* subMenu = currentItem->Submenu())
2147 _EnableMenuItems(subMenu);
2148 }
2149 }
2150}
2151
2152
2153void
2154PaintWindow::_DisableMenuItem(const char* label)
2155{
2156 BMenuItem* item = fMenubar->FindItem(label);
2157 if (item)
2158 item->SetEnabled(false);
2159}