File: | home/HaikuArchives/ArtPaint/artpaint/controls/ColorPalette.cpp |
Warning: | line 461, column 2 Value stored to 'left' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 "ColorPalette.h" |
12 | |
13 | #include "CMYControl.h" |
14 | #include "FileIdentificationStrings.h" |
15 | #include "FilePanels.h" |
16 | #include "FloaterManager.h" |
17 | #include "HSVControl.h" |
18 | #include "MessageConstants.h" |
19 | #include "MessageFilters.h" |
20 | #include "Patterns.h" |
21 | #include "PaintApplication.h" |
22 | #include "PaletteWindowClient.h" |
23 | #include "ResourceServer.h" |
24 | #include "RGBControl.h" |
25 | #include "SettingsServer.h" |
26 | #include "StatusView.h" |
27 | #include "UtilityClasses.h" |
28 | #include "YIQControl.h" |
29 | #include "YUVControl.h" |
30 | |
31 | |
32 | #include <Alert.h> |
33 | #include <Bitmap.h> |
34 | #include <Catalog.h> |
35 | #include <FilePanel.h> |
36 | #include <MenuBar.h> |
37 | #include <MenuItem.h> |
38 | #include <NodeInfo.h> |
39 | #include <Path.h> |
40 | #include <PictureButton.h> |
41 | #include <Resources.h> |
42 | #include <Roster.h> |
43 | #include <TextControl.h> |
44 | |
45 | |
46 | #include <stdlib.h> |
47 | #include <string.h> |
48 | |
49 | |
50 | #undef B_TRANSLATION_CONTEXT"ColorPalette" |
51 | #define B_TRANSLATION_CONTEXT"ColorPalette" "ColorPalette" |
52 | |
53 | |
54 | // Initialize the static variable to NULL. |
55 | ColorPaletteWindow* ColorPaletteWindow::palette_window = NULL__null; |
56 | BList* ColorPaletteWindow::master_window_list = new BList(); |
57 | BList* ColorPaletteWindow::palette_window_clients = new BList(); |
58 | |
59 | |
60 | ColorPaletteWindow::ColorPaletteWindow(BRect frame, int32 mode) |
61 | : BWindow(frame, B_TRANSLATE("Colors")BLocaleRoster::Default()->GetCatalog()->GetString(("Colors" ), "ColorPalette"), |
62 | B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_RESIZABLE | |
63 | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_AVOID_FRONT) |
64 | , open_panel(NULL__null) |
65 | , save_panel(NULL__null) |
66 | { |
67 | // here we just record the mode that user has requested |
68 | // for displaying the controls (eg. RGBA, HSV, something else) |
69 | selector_mode = mode; |
70 | |
71 | color_control = NULL__null; |
72 | color_slider = NULL__null; |
73 | |
74 | window_feel feel = B_NORMAL_WINDOW_FEEL; |
75 | if (SettingsServer* server = SettingsServer::Instance()) { |
76 | server->SetValue(SettingsServer::Application, skPaletteWindowVisible, |
77 | true); |
78 | |
79 | BMessage settings; |
80 | if (server->GetApplicationSettings(&settings) == B_OK((int)0)) |
81 | settings.FindInt32(skPaletteWindowFeel, (int32*)&feel); |
82 | } |
83 | SetFeel(feel); |
84 | |
85 | window_look look = B_FLOATING_WINDOW_LOOK; |
86 | if (feel == B_NORMAL_WINDOW_FEEL) |
87 | look = B_TITLED_WINDOW_LOOK; |
88 | SetLook(look); |
89 | |
90 | openMenuBar(); |
91 | // call some function that initializes the views depending on the mode |
92 | if (!openControlViews(mode)) { |
93 | // if for some reason view opening did not succeed we delete all of them |
94 | // that were created |
95 | deleteControlViews(mode); |
96 | } else { |
97 | // we can assume that everything went OK show ourselves on screen |
98 | Show(); |
99 | } |
100 | |
101 | if (Lock()) { |
102 | AddCommonFilter(new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, |
103 | B_MOUSE_DOWN, window_activation_filter)); |
104 | AddCommonFilter(new BMessageFilter(B_KEY_DOWN,AppKeyFilterFunction)); |
105 | Unlock(); |
106 | } |
107 | |
108 | palette_window = this; |
109 | FloaterManager::AddFloater(this); |
110 | } |
111 | |
112 | |
113 | ColorPaletteWindow::~ColorPaletteWindow() |
114 | { |
115 | delete open_panel; |
116 | delete save_panel; |
117 | |
118 | if (SettingsServer* server = SettingsServer::Instance()) { |
119 | server->SetValue(SettingsServer::Application, skPaletteWindowFrame, |
120 | Frame()); |
121 | server->SetValue(SettingsServer::Application, skPaletteWindowVisible, |
122 | false); |
123 | server->SetValue(SettingsServer::Application, skPaletteColorMode, |
124 | selector_mode); |
125 | } |
126 | |
127 | FloaterManager::RemoveFloater(this); |
128 | palette_window = NULL__null; |
129 | } |
130 | |
131 | |
132 | void ColorPaletteWindow::MessageReceived(BMessage *message) |
133 | { |
134 | // this path is used when getting the applications path to save |
135 | // the palettes. It must be defined here instead of inside the |
136 | // switch-clause |
137 | BPath path; |
138 | BMessage *color_message; |
139 | rgb_color color; |
140 | int32 buttons; |
141 | |
142 | switch (message->what) { |
143 | |
144 | // this comes from the HSColorControl object and indicates that it's value has changed |
145 | case HS_COLOR_CONTROL_INVOKED'CCIn': |
146 | // send message to each container |
147 | // message should contain the index of that color in color-set |
148 | // this should only be done if the color_container is in edit-mode |
149 | // and set the current color in the set for that color too |
150 | color_message = new BMessage(HS_COLOR_CHANGED'CoCH'); |
151 | color_message->AddInt32("index",ColorSet::currentSet()->currentColorIndex()); |
152 | // For some reason the alpha channel needs to be forced to 255 |
153 | color = color_control->ValueAsColor(); |
154 | color.alpha = 255; |
155 | ColorSet::currentSet()->setCurrentColor(color); |
156 | ColorContainer::sendMessageToAllContainers(color_message); |
157 | SelectedColorsView::sendMessageToAll(color_message); |
158 | |
159 | // also change the color for mousebutton that was used |
160 | message->FindInt32("buttons",&buttons); |
161 | if (buttons & B_PRIMARY_MOUSE_BUTTON) |
162 | ((PaintApplication*)be_app)->SetColor(color, TRUE1); |
163 | else |
164 | ((PaintApplication*)be_app)->SetColor(color, FALSE0); |
165 | |
166 | InformClients(ColorSet::currentSet()->currentColor()); |
167 | break; |
168 | |
169 | // This comes from the RGBControl-object and indicates that it's value has changed. |
170 | // This might also come from CMYControl, YIQControl ... |
171 | case HS_RGB_CONTROL_INVOKED'RGIn': |
172 | // send message to each container |
173 | // message should contain the index of that color in color-set |
174 | // this should only be done if the color_container is in edit-mode |
175 | // and set the current color in the set for that color too |
176 | color_message = new BMessage(HS_COLOR_CHANGED'CoCH'); |
177 | color_message->AddInt32("index",ColorSet::currentSet()->currentColorIndex()); |
178 | ColorSet::currentSet()->setCurrentColor(color_slider->ValueAsColor()); |
179 | ColorContainer::sendMessageToAllContainers(color_message); |
180 | SelectedColorsView::sendMessageToAll(color_message); |
181 | |
182 | // also change the color for mousebutton that was used |
183 | message->FindInt32("buttons",&buttons); |
184 | if (buttons & B_PRIMARY_MOUSE_BUTTON) |
185 | ((PaintApplication*)be_app)->SetColor(color_slider->ValueAsColor(),TRUE1); |
186 | else |
187 | ((PaintApplication*)be_app)->SetColor(color_slider->ValueAsColor(),FALSE0); |
188 | |
189 | InformClients(ColorSet::currentSet()->currentColor()); |
190 | break; |
191 | |
192 | // this comes from the menubar->"Set"->"New Palette"->"N" and indicates that a new |
193 | // palette-set should be created, the "colors"-parameter tells us how many colors the |
194 | // new set has |
195 | case HS_NEW_PALETTE_CREATED'NPaC': |
196 | new ColorSet(message->FindInt32("colors")); |
197 | // inform the color-containers about change |
198 | ColorContainer::sendMessageToAllContainers(new BMessage(HS_PALETTE_CHANGED'PaCh')); |
199 | // here change the name view to display sets name |
200 | if (ColorSet::numberOfSets() > 1) { |
201 | menu_bar->FindItem(HS_DELETE_PALETTE'DePa')->SetEnabled(TRUE1); |
202 | } |
203 | break; |
204 | |
205 | // this comes from the menubar->"Set"->"Delete Current Set" and indicates that the current |
206 | // set should be deleted |
207 | case HS_DELETE_PALETTE'DePa': |
208 | // check if there are any more sets left |
209 | if (ColorSet::numberOfSets() >= 2) { |
210 | // first delete ourselves |
211 | delete ColorSet::currentSet(); |
212 | // inform the color-containers about change |
213 | ColorContainer::sendMessageToAllContainers(new BMessage(HS_PALETTE_CHANGED'PaCh')); |
214 | // here change the name view to display sets name |
215 | if (ColorSet::numberOfSets() <= 1) { |
216 | menu_bar->FindItem(HS_DELETE_PALETTE'DePa')->SetEnabled(FALSE0); |
217 | } |
218 | } |
219 | else { |
220 | (new BAlert("", B_TRANSLATE("Cannot delete the only color set.")BLocaleRoster::Default()->GetCatalog()->GetString(("Cannot delete the only color set." ), "ColorPalette"), |
221 | B_TRANSLATE("OK")BLocaleRoster::Default()->GetCatalog()->GetString(("OK" ), "ColorPalette")))->Go(); |
222 | } |
223 | break; |
224 | |
225 | // this comes from a button that is named "next set button", the button is in this window |
226 | // the message indicates that we should change the colorcontainers to display next color set |
227 | case HS_NEXT_PALETTE'NxPl': |
228 | // change the entry in palette list |
229 | ColorSet::moveToNextSet(); |
230 | // inform all color-containers about palette-change |
231 | ColorContainer::sendMessageToAllContainers(new BMessage(HS_PALETTE_CHANGED'PaCh')); |
232 | break; |
233 | |
234 | // this comes from a button that is named "previous set button", the button is in this window |
235 | // the message indicates that we should change the colorcontainers to display previous color set |
236 | case HS_PREVIOUS_PALETTE'PrPl': |
237 | // change the entry in palette list |
238 | ColorSet::moveToPrevSet(); |
239 | // inform all color-containers about palette-change |
240 | ColorContainer::sendMessageToAllContainers(new BMessage(HS_PALETTE_CHANGED'PaCh')); |
241 | break; |
242 | |
243 | // this is sent from ColorContainer::MouseDown and it's purpose is to |
244 | // let us change the corresponding color to the color-controller also |
245 | case HS_PALETTE_SELECTION_CHANGED'PslC': |
246 | // update the color controller to display this new color |
247 | // only should do it if container is in edit mode |
248 | if (color_control != NULL__null) |
249 | color_control->SetValue(ColorSet::currentSet()->currentColor()); |
250 | if (color_slider != NULL__null) |
251 | color_slider->SetValue(ColorSet::currentSet()->currentColor()); |
252 | InformClients(ColorSet::currentSet()->currentColor()); |
253 | break; |
254 | |
255 | // this comes from the menubar->"Set"->"Open Set" and indicates that |
256 | // a file panel should be opened for the purpose of loading new set |
257 | case HS_SHOW_PALETTE_OPEN_PANEL'SpOp': |
258 | // here we must open the file-panel for loading |
259 | // here get the path for palette-files, should be made relative to apps directory |
260 | // or maybe remember the directory from last use |
261 | |
262 | if (open_panel == NULL__null) { |
263 | // here we get the home directory of the application |
264 | PaintApplication::HomeDirectory(path); |
265 | |
266 | // force normalization of the path to check validity |
267 | if (path.Append("Palette sets/",TRUE1) != B_OK((int)0)) { |
268 | PaintApplication::HomeDirectory(path); |
269 | } |
270 | |
271 | entry_ref ref; |
272 | get_ref_for_path(path.Path(), &ref); |
273 | |
274 | BMessenger target(this); |
275 | BMessage message(HS_PALETTE_OPEN_REFS'PaOr'); |
276 | open_panel = new BFilePanel(B_OPEN_PANEL, &target, &ref, |
277 | B_FILE_NODE, true, &message); |
278 | } |
279 | open_panel->Window()->SetTitle(B_TRANSLATE("ArtPaint: Open color set" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("ArtPaint: Open color set" "\xE2\x80\xA6"), "ColorPalette")); |
280 | set_filepanel_strings(open_panel); |
281 | open_panel->Show(); |
282 | break; |
283 | |
284 | // this comes from the menubar->"Set"->"Save Set" and indicates that |
285 | // a file panel should be opened for the purpose of saving current set |
286 | case HS_SHOW_PALETTE_SAVE_PANEL'SpSp': |
287 | // here we must open the file-panel for saving |
288 | if (save_panel == NULL__null) { |
289 | // get the home directory of the app |
290 | PaintApplication::HomeDirectory(path); |
291 | |
292 | // force normalization of the path to check validity |
293 | if (path.Append("Palette sets/",TRUE1) != B_OK((int)0)) { |
294 | PaintApplication::HomeDirectory(path); |
295 | } |
296 | // convert it to entry_ref |
297 | entry_ref ref; |
298 | get_ref_for_path(path.Path(), &ref); |
299 | |
300 | BMessenger target(this); |
301 | BMessage message(HS_PALETTE_SAVE_REFS'PaSr'); |
302 | save_panel = new BFilePanel(B_SAVE_PANEL, &target, &ref, 0, false, |
303 | &message); |
304 | } |
305 | save_panel->SetSaveText(ColorSet::currentSet()->getName()); |
306 | save_panel->Window()->SetTitle(B_TRANSLATE("ArtPaint: Open color set" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("ArtPaint: Open color set" "\xE2\x80\xA6"), "ColorPalette")); |
307 | set_filepanel_strings(save_panel); |
308 | save_panel->Show(); |
309 | break; |
310 | |
311 | // this comes from the open_panel or the applocation-object and includes refs for |
312 | // the palette-files that should be loaded |
313 | case HS_PALETTE_OPEN_REFS'PaOr': |
314 | handlePaletteLoad(message); |
315 | |
316 | // inform all color containers that palette has changed |
317 | ColorContainer::sendMessageToAllContainers(new BMessage(HS_PALETTE_CHANGED'PaCh')); |
318 | if (ColorSet::numberOfSets() > 1) { |
319 | menu_bar->FindItem(HS_DELETE_PALETTE'DePa')->SetEnabled(TRUE1); |
320 | } |
321 | break; |
322 | |
323 | // this comes from the save_panel and indicates that current set should be saved |
324 | // to the file that the "refs" indicate |
325 | case HS_PALETTE_SAVE_REFS'PaSr': |
326 | handlePaletteSave(message); |
327 | break; |
328 | |
329 | // this comes from the menubar->"Mode"->"RGB-Mode" and indicates that |
330 | // the color selector should be changed to a RGBControl, this is used |
331 | // also for other purposes than just a message-constant |
332 | case HS_RGB_COLOR_MODE: |
333 | if (selector_mode != HS_RGB_COLOR_MODE) { |
334 | deleteControlViews(selector_mode); |
335 | selector_mode = HS_RGB_COLOR_MODE; |
336 | openControlViews(HS_RGB_COLOR_MODE); |
337 | } |
338 | break; |
339 | |
340 | // this comes from the menubar->"Mode"->"CMY-Mode" and indicates that |
341 | // the color selector should be changed to a RGBControl, this is used |
342 | // also for other purposes than just a message-constant |
343 | case HS_CMY_COLOR_MODE: |
344 | if (selector_mode != HS_CMY_COLOR_MODE) { |
345 | deleteControlViews(selector_mode); |
346 | selector_mode = HS_CMY_COLOR_MODE; |
347 | openControlViews(HS_CMY_COLOR_MODE); |
348 | } |
349 | break; |
350 | |
351 | // this comes from the menubar->"Mode"->"YIQ-Mode" and indicates that |
352 | // the color selector should be changed to a RGBControl, this is used |
353 | // also for other purposes than just a message-constant |
354 | case HS_YIQ_COLOR_MODE: |
355 | if (selector_mode != HS_YIQ_COLOR_MODE) { |
356 | deleteControlViews(selector_mode); |
357 | selector_mode = HS_YIQ_COLOR_MODE; |
358 | openControlViews(HS_YIQ_COLOR_MODE); |
359 | } |
360 | break; |
361 | |
362 | // this comes from the menubar->"Mode"->"YUV-Mode" and indicates that |
363 | // the color selector should be changed to a RGBControl, this is used |
364 | // also for other purposes than just a message-constant |
365 | case HS_YUV_COLOR_MODE: |
366 | if (selector_mode != HS_YUV_COLOR_MODE) { |
367 | deleteControlViews(selector_mode); |
368 | selector_mode = HS_YUV_COLOR_MODE; |
369 | openControlViews(HS_YUV_COLOR_MODE); |
370 | } |
371 | break; |
372 | |
373 | case HS_HSV_COLOR_MODE: |
374 | if (selector_mode != HS_HSV_COLOR_MODE) { |
375 | deleteControlViews(selector_mode); |
376 | selector_mode = HS_HSV_COLOR_MODE; |
377 | openControlViews(HS_HSV_COLOR_MODE); |
378 | } |
379 | break; |
380 | |
381 | |
382 | // this comes from the menubar->"Mode"->"Simple-Mode" and indicates that |
383 | // the color selector should be changed to a HSColorControl, this is used |
384 | // also for other purposes than just a message-constant |
385 | case HS_SIMPLE_COLOR_MODE: |
386 | if (selector_mode != HS_SIMPLE_COLOR_MODE) { |
387 | deleteControlViews(selector_mode); |
388 | selector_mode = HS_SIMPLE_COLOR_MODE; |
389 | openControlViews(HS_SIMPLE_COLOR_MODE); |
390 | } |
391 | break; |
392 | |
393 | default: |
394 | BWindow::MessageReceived(message); |
395 | break; |
396 | } |
397 | } |
398 | |
399 | bool ColorPaletteWindow::QuitRequested() |
400 | { |
401 | // We might do something useful here. |
402 | return TRUE1; |
403 | } |
404 | |
405 | bool ColorPaletteWindow::openControlViews(int32 mode) |
406 | { |
407 | // first we open the views that are common to all modes of color palette |
408 | // at least the menubar and the color-set container and controls that can change |
409 | // the color-set or its name |
410 | |
411 | // these variables are used to position the views correctly |
412 | float top , left; |
413 | |
414 | // update the top to be under menu_bar |
415 | top = menu_bar->Frame().Height() + 1; |
416 | |
417 | box1 = new BBox(BRect(0,top,0,top)); |
418 | box1->SetBorder(B_PLAIN_BORDER); |
419 | // here open the color_container |
420 | color_container = new ColorContainer(BRect(0,3,63,66),ColorSet::currentSet()->sizeOfSet()); |
421 | color_container->SetDraggingEnabled(TRUE1); |
422 | box1->AddChild(color_container); |
423 | |
424 | // update the top to be under container in the box1 coordinates that is |
425 | top = color_container->Frame().bottom + 4; |
426 | |
427 | // Here add the buttons that control the color-set. |
428 | ResourceServer* server = ResourceServer::Instance(); |
429 | if (server) { |
430 | BPicture arrow_pushed; |
431 | BPicture arrow_not_pushed; |
432 | |
433 | server->GetPicture(LEFT_ARROW, &arrow_not_pushed); |
434 | server->GetPicture(LEFT_ARROW_PUSHED, &arrow_pushed); |
435 | |
436 | previous_set = new BPictureButton(BRect(3, top, 11, top + 12), |
437 | "left_arrow", &arrow_not_pushed, &arrow_pushed, |
438 | new BMessage(HS_PREVIOUS_PALETTE'PrPl')); |
439 | box1->AddChild(previous_set); |
440 | previous_set->SetTarget(this); |
441 | previous_set->ResizeToPreferred(); |
442 | |
443 | server->GetPicture(RIGHT_ARROW, &arrow_not_pushed); |
444 | server->GetPicture(RIGHT_ARROW_PUSHED, &arrow_pushed); |
445 | |
446 | next_set = new BPictureButton(previous_set->Frame(), "right arrow", |
447 | &arrow_not_pushed, &arrow_pushed, new BMessage(HS_NEXT_PALETTE'NxPl')); |
448 | box1->AddChild(next_set); |
449 | next_set->SetTarget(this); |
450 | next_set->ResizeToPreferred(); |
451 | next_set->MoveBy(next_set->Frame().Width() + 3,0); |
452 | } |
453 | |
454 | // here resize the box1 to appropriate size |
455 | box1->ResizeTo(max_c(next_set->Frame().right + 20,color_container->Frame().Width()+6)((next_set->Frame().right + 20)>(color_container->Frame ().Width()+6)?(next_set->Frame().right + 20):(color_container ->Frame().Width()+6)),next_set->Frame().bottom+3); |
456 | |
457 | // here center the views horizontally |
458 | color_container->MoveBy((box1->Frame().Width() - color_container->Frame().Width())/2,0); |
459 | |
460 | AddChild(box1); |
461 | left = box1->Frame().right + 1; |
Value stored to 'left' is never read | |
462 | top = menu_bar->Frame().Height() + 1; |
463 | |
464 | // this will be assigned to RGBControl or similar object |
465 | BMessage *invocation_message; |
466 | // here we open the views that show color controls e.g. RGB- or HSV-controls |
467 | switch (mode) { |
468 | |
469 | // in this case just open a HSColorControl and color-set container |
470 | case HS_SIMPLE_COLOR_MODE: |
471 | box2 = new BBox(BRect(box1->Frame().right+1,top,box1->Frame().right+10,box1->Frame().bottom)); |
472 | color_control = new HSColorControl(BPoint(5,0),B_CELLS_32x8,8,""); |
473 | color_control->SetTarget(this); |
474 | box2->ResizeTo(color_control->Frame().Width()+10,box2->Frame().Height()); |
475 | |
476 | ResizeTo(box2->Frame().right,max_c(box1->Frame().Height() + top-1,color_control->Frame().Height() + top)((box1->Frame().Height() + top-1)>(color_control->Frame ().Height() + top)?(box1->Frame().Height() + top-1):(color_control ->Frame().Height() + top))); |
477 | box2->AddChild(color_control); |
478 | AddChild(box2); |
479 | // here center the color control vertically |
480 | color_control->MoveBy(0,(box2->Frame().Height() - color_control->Frame().Height())/2); |
481 | break; |
482 | |
483 | // in this case open an RGBControl |
484 | case HS_RGB_COLOR_MODE: case HS_CMY_COLOR_MODE: case HS_YIQ_COLOR_MODE: case HS_YUV_COLOR_MODE: |
485 | case HS_HSV_COLOR_MODE: |
486 | box2 = new BBox(BRect(box1->Frame().right+1,top,box1->Frame().right+10,box1->Frame().bottom)); |
487 | |
488 | if (mode == HS_RGB_COLOR_MODE) { |
489 | rgb_color c = {0,0,0,255}; |
490 | color_slider = new RGBControl(BPoint(5,0),c); |
491 | } |
492 | else if (mode == HS_CMY_COLOR_MODE) { |
493 | rgb_color c = {255,255,255,255}; |
494 | color_slider = new CMYControl(BPoint(5,0),c); |
495 | } |
496 | else if (mode == HS_YIQ_COLOR_MODE) { |
497 | rgb_color c = {255,255,255,255}; |
498 | color_slider = new YIQControl(BPoint(5,0),c); |
499 | } |
500 | else if (mode == HS_YUV_COLOR_MODE) { |
501 | rgb_color c = {255,255,255,255}; |
502 | color_slider = new YUVControl(BPoint(5,0),c); |
503 | } |
504 | else if (mode == HS_HSV_COLOR_MODE) { |
505 | rgb_color c = {255,255,255,255}; |
506 | color_slider = new HSVControl(BPoint(5,0),c); |
507 | } |
508 | box2->AddChild(color_slider); |
509 | AddChild(box2); |
510 | |
511 | color_slider->SetTarget(this); |
512 | box2->ResizeTo(color_slider->Frame().Width()+10,box2->Frame().Height()); |
513 | ResizeTo(box2->Frame().right,max_c(box1->Frame().Height() +((box1->Frame().Height() + top-1)>(color_slider->Frame ().Height() + top)?(box1->Frame().Height() + top-1):(color_slider ->Frame().Height() + top)) |
514 | top-1,color_slider->Frame().Height() + top)((box1->Frame().Height() + top-1)>(color_slider->Frame ().Height() + top)?(box1->Frame().Height() + top-1):(color_slider ->Frame().Height() + top))); |
515 | |
516 | // here center the color control vertically |
517 | color_slider->MoveBy(0,(box2->Frame().Height() - |
518 | color_slider->Frame().Height())/2); |
519 | invocation_message = new BMessage(HS_RGB_CONTROL_INVOKED'RGIn'); |
520 | invocation_message->AddInt32("buttons",0); |
521 | color_slider->SetMessage(invocation_message); |
522 | break; |
523 | |
524 | default: |
525 | return TRUE1; |
526 | } |
527 | box2->SetBorder(B_PLAIN_BORDER); |
528 | |
529 | // Update the color-controllers and slider's values |
530 | if (color_control != NULL__null) |
531 | color_control->SetValue(ColorSet::currentSet()->currentColor()); |
532 | if (color_slider != NULL__null) |
533 | color_slider->SetValue(ColorSet::currentSet()->currentColor()); |
534 | |
535 | return TRUE1; |
536 | } |
537 | |
538 | |
539 | |
540 | void ColorPaletteWindow::deleteControlViews(int32) |
541 | { |
542 | // here we delete all views that are not NULL |
543 | box1->RemoveSelf(); |
544 | delete box1; |
545 | |
546 | box2->RemoveSelf(); |
547 | delete box2; |
548 | |
549 | // NULL all the controls |
550 | color_control = NULL__null; |
551 | color_slider = NULL__null; |
552 | } |
553 | |
554 | |
555 | void ColorPaletteWindow::openMenuBar() |
556 | { |
557 | BMenu *menu; |
558 | BMenu *sub_menu; |
559 | BMenuItem *menu_item; |
560 | |
561 | menu_bar = new BMenuBar(BRect(0,0,0,0),"menu bar"); |
562 | menu = new BMenu(B_TRANSLATE("Color set")BLocaleRoster::Default()->GetCatalog()->GetString(("Color set" ), "ColorPalette")); |
563 | menu_bar->AddItem(menu); |
564 | |
565 | sub_menu = new BMenu(B_TRANSLATE("New color set")BLocaleRoster::Default()->GetCatalog()->GetString(("New color set" ), "ColorPalette")); |
566 | |
567 | // in this loop we add possible palette sizes to menu |
568 | BMessage *msg; |
569 | char item_title[20] = ""; |
570 | for (int32 i = 3; i <= 6; i++) { |
571 | sprintf(item_title, "%ld %s",((int32)pow(2, i)), |
572 | B_TRANSLATE("Colors")BLocaleRoster::Default()->GetCatalog()->GetString(("Colors" ), "ColorPalette")); |
573 | msg = new BMessage(HS_NEW_PALETTE_CREATED'NPaC'); |
574 | msg->AddInt32("colors", ((int32)pow(2, i))); |
575 | menu_item = new BMenuItem(item_title, msg); |
576 | sub_menu->AddItem(menu_item); |
577 | } |
578 | // the palette window will handle all things that concern making |
579 | // or loading new palette |
580 | sub_menu->SetTargetForItems(this); |
581 | menu->AddItem(sub_menu); |
582 | |
583 | menu_item = new BMenuItem(B_TRANSLATE("Delete current set")BLocaleRoster::Default()->GetCatalog()->GetString(("Delete current set" ), "ColorPalette"), |
584 | new BMessage(HS_DELETE_PALETTE'DePa')); |
585 | menu_item->SetTarget(this); |
586 | menu->AddItem(menu_item); |
587 | if (ColorSet::numberOfSets() <= 1) { |
588 | menu_item->SetEnabled(FALSE0); |
589 | } |
590 | |
591 | menu->AddItem(new BSeparatorItem()); |
592 | menu_item = new BMenuItem(B_TRANSLATE("Open color set" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Open color set" "\xE2\x80\xA6"), "ColorPalette"), |
593 | new BMessage(HS_SHOW_PALETTE_OPEN_PANEL'SpOp')); |
594 | menu_item->SetTarget(this); |
595 | menu->AddItem(menu_item); |
596 | menu_item = new BMenuItem(B_TRANSLATE("Save color set")BLocaleRoster::Default()->GetCatalog()->GetString(("Save color set" ), "ColorPalette"), |
597 | new BMessage(HS_SHOW_PALETTE_SAVE_PANEL'SpSp')); |
598 | menu_item->SetTarget(this); |
599 | menu->AddItem(menu_item); |
600 | |
601 | menu = new BMenu(B_TRANSLATE("Color model")BLocaleRoster::Default()->GetCatalog()->GetString(("Color model" ), "ColorPalette")); |
602 | menu_bar->AddItem(menu); |
603 | |
604 | char string[256]; |
605 | sprintf(string,"RGB"); |
606 | menu_item = new BMenuItem(string,new BMessage(HS_RGB_COLOR_MODE)); |
607 | menu_item->SetTarget(this); |
608 | menu->AddItem(menu_item); |
609 | sprintf(string,"CMY"); |
610 | menu_item = new BMenuItem(string,new BMessage(HS_CMY_COLOR_MODE)); |
611 | menu_item->SetTarget(this); |
612 | menu->AddItem(menu_item); |
613 | sprintf(string,"HSV"); |
614 | menu_item = new BMenuItem(string,new BMessage(HS_HSV_COLOR_MODE)); |
615 | menu_item->SetTarget(this); |
616 | menu->AddItem(menu_item); |
617 | sprintf(string,"YIQ"); |
618 | menu_item = new BMenuItem(string,new BMessage(HS_YIQ_COLOR_MODE)); |
619 | menu_item->SetTarget(this); |
620 | menu->AddItem(menu_item); |
621 | sprintf(string,"YUV"); |
622 | menu_item = new BMenuItem(string,new BMessage(HS_YUV_COLOR_MODE)); |
623 | menu_item->SetTarget(this); |
624 | menu->AddItem(menu_item); |
625 | sprintf(string,"BeOS"); |
626 | menu_item = new BMenuItem(string,new BMessage(HS_SIMPLE_COLOR_MODE)); |
627 | menu_item->SetTarget(this); |
628 | menu->AddItem(menu_item); |
629 | menu->SetRadioMode(TRUE1); |
630 | menu->FindItem(selector_mode)->SetMarked(TRUE1); |
631 | |
632 | AddChild(menu_bar); |
633 | } |
634 | |
635 | void ColorPaletteWindow::handlePaletteLoad(BMessage *message) |
636 | { |
637 | // here check for file type and possibly load it to memory |
638 | uint32 type; |
639 | int32 count; |
640 | entry_ref ref; |
641 | |
642 | // this holds the bytes that were read |
643 | ssize_t bytes_read; |
644 | |
645 | // this will hold the identification string, they are not longer than 256 chars |
646 | char file_type[256]; |
647 | |
648 | |
649 | // we can probably assume that the ref is actually a file |
650 | message->GetInfo("refs", &type, &count); |
651 | if ( type != B_REF_TYPE ) |
652 | return; |
653 | |
654 | for ( long i = --count; i >= 0; i-- ) { |
655 | if ( message->FindRef("refs", i, &ref) == B_OK((int)0) ) { |
656 | BFile file; |
657 | if ( file.SetTo(&ref, B_READ_ONLY0x0000) == B_OK((int)0) ) { |
658 | // the file was succesfully opened |
659 | // here we check that it is actually a palette file |
660 | // and read it if it is and also generate a new palette to |
661 | // list of palettes |
662 | if ((bytes_read = file.Read(file_type,strlen(HS_PALETTE_ID_STRING"ArtPaint color set"))) < 0) { |
663 | // here some error reading file has happened |
664 | (new BAlert("",B_TRANSLATE("Error reading file")BLocaleRoster::Default()->GetCatalog()->GetString(("Error reading file" ), "ColorPalette"),B_TRANSLATE("OK")BLocaleRoster::Default()->GetCatalog()->GetString(("OK" ), "ColorPalette")))->Go(); |
665 | } |
666 | else { |
667 | // the read was succesfull, terminate the id string and compare |
668 | file_type[bytes_read] = '\0'; |
669 | if (strcmp(file_type,HS_PALETTE_ID_STRING"ArtPaint color set") != 0) { |
670 | // this was not a palette file |
671 | (new BAlert("",B_TRANSLATE("Not a color set file")BLocaleRoster::Default()->GetCatalog()->GetString(("Not a color set file" ), "ColorPalette"),B_TRANSLATE("OK")BLocaleRoster::Default()->GetCatalog()->GetString(("OK" ), "ColorPalette")))->Go(); |
672 | } |
673 | else { |
674 | // this was palette file, read the rest of it |
675 | int32 palette_size; |
676 | if ((bytes_read = file.Read(&palette_size,sizeof(int32))) != sizeof(int32)) { |
677 | // here some error reading file has happened |
678 | (new BAlert("",B_TRANSLATE("File structure corrupted")BLocaleRoster::Default()->GetCatalog()->GetString(("File structure corrupted" ), "ColorPalette"), |
679 | B_TRANSLATE("OK")BLocaleRoster::Default()->GetCatalog()->GetString(("OK" ), "ColorPalette")))->Go(); |
680 | } |
681 | else { |
682 | // create the palette and read the palette colors |
683 | ColorSet *loaded_set = new ColorSet(palette_size); |
684 | rgb_color loaded_color; |
685 | |
686 | // here is the loop that reads palette entries from file |
687 | for (int32 i = 0; i < palette_size; i++) { |
688 | file.Read(&loaded_color,sizeof(rgb_color)); |
689 | loaded_set->setColor(i,loaded_color); |
690 | } |
691 | // this array holds the palette-name |
692 | char palette_name[256]; |
693 | // read as many bytes as there is left to be the palette name |
694 | bytes_read = file.Read(palette_name,255); |
695 | palette_name[bytes_read] = '\0'; |
696 | loaded_set->setName(palette_name); |
697 | } |
698 | |
699 | } |
700 | } |
701 | } |
702 | } |
703 | } |
704 | } |
705 | |
706 | |
707 | void ColorPaletteWindow::handlePaletteSave(BMessage *message) |
708 | { |
709 | uint32 type; |
710 | int32 count; |
711 | entry_ref ref; |
712 | |
713 | // we can probably assume that the ref is actually a file |
714 | message->GetInfo("directory", &type, &count); |
715 | if ( type != B_REF_TYPE ) { |
716 | return; |
717 | } |
718 | // here take a pointer to current color-set, so that if current set is changed |
719 | // this will still save the same set |
720 | ColorSet *color_set = ColorSet::currentSet(); |
721 | |
722 | for ( long i = --count; i >= 0; i-- ) { |
723 | if ( message->FindRef("directory", i, &ref) == B_OK((int)0) ) { |
724 | BFile file; |
725 | BDirectory directory = BDirectory(&ref); |
726 | if ( file.SetTo(&directory,message->FindString("name",i), |
727 | B_READ_WRITE0x0002 | B_CREATE_FILE0x0200 | B_ERASE_FILE0x0400) == B_OK((int)0) ) { |
728 | // here we write the current color-set to file |
729 | // first set the file's type and other metadata |
730 | // get the applications signature |
731 | app_info info; |
732 | be_app->GetAppInfo(&info); |
733 | |
734 | BNodeInfo node(&file); |
735 | node.SetType(HS_PALETTE_MIME_STRING"application/x-vnd.artpaint-palette-file"); |
736 | node.SetPreferredApp(info.signature); |
737 | |
738 | if (file.Write(HS_PALETTE_ID_STRING"ArtPaint color set",strlen(HS_PALETTE_ID_STRING"ArtPaint color set")) < 0) { |
739 | // error happened |
740 | (new BAlert("",B_TRANSLATE("Cannot write to file")BLocaleRoster::Default()->GetCatalog()->GetString(("Cannot write to file" ), "ColorPalette"),B_TRANSLATE("OK")BLocaleRoster::Default()->GetCatalog()->GetString(("OK" ), "ColorPalette")))->Go(); |
741 | } |
742 | else { |
743 | // write the rest of the file |
744 | int32 size = color_set->sizeOfSet(); |
745 | file.Write(&size,sizeof(int32)); |
746 | |
747 | // this loop writes the color entries |
748 | for (int32 i=0;i<size;i++) { |
749 | rgb_color c = color_set->colorAt(i); |
750 | file.Write(&c,sizeof(rgb_color)); |
751 | } |
752 | |
753 | // finally write the name of set |
754 | file.Write(color_set->getName(),strlen(color_set->getName())); |
755 | } |
756 | } |
757 | } |
758 | } |
759 | } |
760 | |
761 | |
762 | void |
763 | ColorPaletteWindow::showPaletteWindow(BMessage *msg) |
764 | { |
765 | if (palette_window == NULL__null) { |
766 | BRect frame(300, 100, 400, 200); |
767 | color_window_modes mode = HS_RGB_COLOR_MODE; |
768 | |
769 | if (SettingsServer* server = SettingsServer::Instance()) { |
770 | BMessage settings; |
771 | server->GetApplicationSettings(&settings); |
772 | settings.FindRect(skPaletteWindowFrame, &frame); |
773 | settings.FindInt32(skPaletteColorMode, (int32*)&mode); |
774 | } |
775 | |
776 | ColorPaletteWindow* window = new ColorPaletteWindow(frame, mode); |
777 | for (int32 i = 0; i < master_window_list->CountItems(); ++i) |
778 | ((BWindow*)master_window_list->ItemAt(i))->AddToSubset(window); |
779 | } else { |
780 | if (palette_window->Lock()) { |
781 | palette_window->SetWorkspaces(B_CURRENT_WORKSPACE0); |
782 | if (palette_window->IsHidden()) |
783 | palette_window->Show(); |
784 | |
785 | if (!palette_window->IsActive()) |
786 | palette_window->Activate(TRUE1); |
787 | |
788 | palette_window->Unlock(); |
789 | } |
790 | } |
791 | |
792 | if (palette_window->Lock()) { |
793 | BRect palette_window_frame = palette_window->Frame(); |
794 | palette_window_frame = FitRectToScreen(palette_window_frame); |
795 | palette_window->MoveTo(palette_window_frame.LeftTop()); |
796 | palette_window->Unlock(); |
797 | } |
798 | |
799 | // If we got a message we should try to use it for loading a palette. |
800 | if (msg) |
801 | palette_window->handlePaletteLoad(msg); |
802 | } |
803 | |
804 | |
805 | void |
806 | ColorPaletteWindow::ChangePaletteColor(rgb_color& c) |
807 | { |
808 | if (palette_window != NULL__null) { |
809 | palette_window->Lock(); |
810 | |
811 | if (palette_window->color_control != NULL__null) |
812 | palette_window->color_control->SetValue(c); |
813 | if (palette_window->color_slider != NULL__null) |
814 | palette_window->color_slider->SetValue(c); |
815 | |
816 | palette_window->Unlock(); |
817 | } |
818 | } |
819 | |
820 | |
821 | void |
822 | ColorPaletteWindow::setFeel(window_feel feel) |
823 | { |
824 | if (SettingsServer* server = SettingsServer::Instance()) { |
825 | server->SetValue(SettingsServer::Application, skPaletteWindowFeel, |
826 | int32(feel)); |
827 | } |
828 | |
829 | if (palette_window) { |
830 | window_look look = B_FLOATING_WINDOW_LOOK; |
831 | if (feel == B_NORMAL_WINDOW_FEEL) |
832 | look = B_TITLED_WINDOW_LOOK; |
833 | |
834 | palette_window->SetFeel(feel); |
835 | palette_window->SetLook(look); |
836 | } |
837 | } |
838 | |
839 | |
840 | void |
841 | ColorPaletteWindow::AddMasterWindow(BWindow *window) |
842 | { |
843 | master_window_list->AddItem(window); |
844 | if (palette_window) |
845 | window->AddToSubset(palette_window); |
846 | } |
847 | |
848 | |
849 | void |
850 | ColorPaletteWindow::RemoveMasterWindow(BWindow *window) |
851 | { |
852 | master_window_list->RemoveItem(window); |
853 | } |
854 | |
855 | |
856 | |
857 | void |
858 | ColorPaletteWindow::AddPaletteWindowClient(PaletteWindowClient *client) |
859 | { |
860 | if (!palette_window_clients->HasItem(client)) |
861 | palette_window_clients->AddItem(client); |
862 | } |
863 | |
864 | |
865 | void |
866 | ColorPaletteWindow::RemovePaletteWindowClient(PaletteWindowClient *client) |
867 | { |
868 | palette_window_clients->RemoveItem(client); |
869 | } |
870 | |
871 | |
872 | void |
873 | ColorPaletteWindow::InformClients(const rgb_color& c) |
874 | { |
875 | for (int32 i = 0; i < palette_window_clients->CountItems(); ++i) { |
876 | PaletteWindowClient* client = |
877 | static_cast<PaletteWindowClient*>(palette_window_clients->ItemAt(i)); |
878 | if (client) |
879 | client->PaletteColorChanged(c); |
880 | } |
881 | } |
882 | |
883 | |
884 | // here is the definition of HSColorControl-class |
885 | HSColorControl::HSColorControl(BPoint location, color_control_layout matrix, |
886 | float cellSide, const char *name) |
887 | : BColorControl(location, matrix, cellSide, name) |
888 | { |
889 | // Set the message here so that using the text boxes before the sliders will work |
890 | BMessage *message = new BMessage(HS_COLOR_CONTROL_INVOKED'CCIn'); |
891 | message->AddInt32("buttons", B_PRIMARY_MOUSE_BUTTON); |
892 | SetMessage(message); |
893 | } |
894 | |
895 | void HSColorControl::MouseDown(BPoint location) |
896 | { |
897 | // here we take the button that was pressed |
898 | int32 buttons = 0; |
899 | Window()->CurrentMessage()->FindInt32("buttons", &buttons); |
900 | |
901 | // set the invokers message to contain the mouse-button that was last pressed |
902 | BMessage *message = new BMessage(HS_COLOR_CONTROL_INVOKED'CCIn'); |
903 | message->AddInt32("buttons",buttons); |
904 | SetMessage(message); |
905 | |
906 | // call the inherited MouseDown-function |
907 | BColorControl::MouseDown(location); |
908 | } |
909 | |
910 | |
911 | |
912 | |
913 | // here starts the definitions for ColorContainer class |
914 | |
915 | // here define the variable that points to list of color containers |
916 | BList* ColorContainer::container_list = new BList(); |
917 | |
918 | |
919 | ColorContainer::ColorContainer(BRect frame, int32 amount_of_colors, uint32 resizingMode, bool highlight,bool add_arrows) |
920 | : BView(frame,"color container",resizingMode,B_WILL_DRAW) |
921 | { |
922 | // here initialize the important variables |
923 | |
924 | highlight_selected = highlight; |
925 | left_arrow = NULL__null; |
926 | right_arrow = NULL__null; |
927 | contains_arrows = FALSE0; |
928 | |
929 | setUpContainer(frame,amount_of_colors,add_arrows); |
930 | |
931 | // add this container to the list |
932 | container_list->AddItem(this); |
933 | |
934 | dragging_enabled = FALSE0; |
935 | } |
936 | |
937 | |
938 | |
939 | ColorContainer::~ColorContainer() |
940 | { |
941 | // here remove ourselves from container list |
942 | container_list->RemoveItem(this); |
943 | } |
944 | |
945 | |
946 | void ColorContainer::AttachedToWindow() |
947 | { |
948 | BView::AttachedToWindow(); |
949 | if (Parent() != NULL__null) |
950 | SetViewColor(Parent()->ViewColor()); |
951 | |
952 | if (left_arrow != NULL__null) |
953 | left_arrow->SetTarget(this); |
954 | if (right_arrow != NULL__null) |
955 | right_arrow->SetTarget(this); |
956 | } |
957 | |
958 | void ColorContainer::Draw(BRect) |
959 | { |
960 | // here we draw the colors with FillRect |
961 | // we get the colors from palette that is held somewhere |
962 | // every instance of this class should also draw whenever |
963 | // a palette entry changes, how should we achieve that ???? |
964 | |
965 | BRect rect; |
966 | |
967 | for (int32 i=0;i<color_count;i++) { |
968 | |
969 | rect = colorBounds(i); |
970 | SetHighAndLowColors(ColorSet::currentSet()->colorAt(i)); |
971 | FillRect(rect,HS_2X2_BLOCKS); |
972 | } |
973 | |
974 | if (highlight_selected) { |
975 | // also draw the rectangle around selected color if required |
976 | SetHighColor(255,255,255,255); |
977 | StrokeRect(colorBounds(ColorSet::currentSet()->currentColorIndex())); |
978 | } |
979 | } |
980 | |
981 | |
982 | |
983 | void ColorContainer::MouseDown(BPoint point) |
984 | { |
985 | // here we highlight the color that is under the cursor |
986 | // and when we have selected the color we inform some |
987 | // third parties about that |
988 | uint32 buttons = 0; |
989 | uint32 original_button; |
990 | |
991 | GetMouse(&point, &buttons, true); |
992 | int32 index,prev_index = ColorSet::currentSet()->currentColorIndex(); |
993 | |
994 | // first draw the rectangle around the newly selected color |
995 | index = pointIndex(point); |
996 | if (index != -1) { |
997 | // only of course if some color was actually selected |
998 | SetHighColor(255,255,255); |
999 | StrokeRect(colorBounds(index)); |
1000 | } |
1001 | |
1002 | original_button = buttons; |
1003 | |
1004 | if (dragging_enabled == FALSE0) { |
1005 | while ( buttons ) { |
1006 | index = pointIndex(point); |
1007 | if ((index != -1) && (index != prev_index)) { |
1008 | // point is over some new color-entry |
1009 | if (prev_index != -1) { |
1010 | // re-draw the previous rectangle |
1011 | SetHighAndLowColors(ColorSet::currentSet()->colorAt(prev_index)); |
1012 | FillRect(colorBounds(prev_index),HS_2X2_BLOCKS); |
1013 | } |
1014 | // then draw rect around new color |
1015 | SetHighColor(255,255,255); |
1016 | StrokeRect(colorBounds(index)); |
1017 | } |
1018 | else if ((index == -1) && (prev_index != -1)) { |
1019 | // we fill the previous rectangle |
1020 | SetHighColor(ColorSet::currentSet()->colorAt(prev_index)); |
1021 | FillRect(colorBounds(prev_index)); |
1022 | } |
1023 | |
1024 | prev_index = index; |
1025 | snooze(20 * 1000); |
1026 | GetMouse(&point, &buttons, true); |
1027 | } |
1028 | } |
1029 | else if (index >= 0) { |
1030 | float distance = 0; |
1031 | BPoint original_point = point; |
1032 | while ((distance < 6) && (buttons)) { |
1033 | GetMouse(&point,&buttons); |
1034 | snooze(20 * 1000); |
1035 | distance = fabs(original_point.x-point.x) + fabs(original_point.y-point.y); |
1036 | } |
1037 | |
1038 | if ((distance >= 6) && buttons) { |
1039 | // Start a drag'n'drop session. |
1040 | BBitmap *dragged_map = new BBitmap(BRect(0,0,15,15),B_RGB32,TRUE1); |
1041 | BView *dragger_view = new BView(BRect(0,0,15,15),"dragger_view",B_FOLLOW_NONE0,B_WILL_DRAW); |
1042 | rgb_color c = ColorSet::currentSet()->colorAt(index); |
1043 | dragged_map->AddChild(dragger_view); |
1044 | dragged_map->Lock(); |
1045 | float alpha = c.alpha; |
1046 | c.alpha = 127; |
1047 | dragger_view->SetHighColor(c); |
1048 | c.alpha = (uint8)alpha; |
1049 | dragger_view->FillRect(dragger_view->Bounds()); |
1050 | dragger_view->Sync(); |
1051 | dragged_map->Unlock(); |
1052 | BMessage dragger_message(B_PASTE); |
1053 | dragger_message.AddData("RGBColor",B_RGB_COLOR_TYPE,&c,sizeof(rgb_color)); |
1054 | DragMessage(&dragger_message,dragged_map,B_OP_ALPHA,BPoint(7,7)); |
1055 | // dragged = TRUE; |
1056 | index = ColorSet::currentSet()->currentColorIndex(); // The active color did not change. |
1057 | } |
1058 | } |
1059 | |
1060 | if (index != -1) { |
1061 | // here we should make the current_color_index in active set to be index |
1062 | ColorSet::currentSet()->setCurrentColorIndex(index); |
1063 | |
1064 | // here we should inform the app that a color has been changed |
1065 | if (original_button & B_PRIMARY_MOUSE_BUTTON) |
1066 | ((PaintApplication*)be_app)->SetColor(ColorSet::currentSet()->currentColor(),TRUE1); |
1067 | else |
1068 | ((PaintApplication*)be_app)->SetColor(ColorSet::currentSet()->currentColor(),FALSE0); |
1069 | |
1070 | // we must also inform all other containers that the selection changed |
1071 | // so that they can highlight the proper rectangle, this will be done |
1072 | // with messages |
1073 | sendMessageToAllContainers(new BMessage(HS_PALETTE_SELECTION_CHANGED'PslC')); |
1074 | |
1075 | // also inform the selected colors' views |
1076 | SelectedColorsView::sendMessageToAll(new BMessage(HS_COLOR_CHANGED'CoCH')); |
1077 | |
1078 | |
1079 | |
1080 | // give the window the information that selection has changed |
1081 | rgb_color c = ColorSet::currentSet()->currentColor(); |
1082 | ColorPaletteWindow::ChangePaletteColor(c); |
1083 | Window()->PostMessage(HS_PALETTE_SELECTION_CHANGED'PslC',Window()); |
1084 | } |
1085 | else { |
1086 | SetHighColor(255,255,255); |
1087 | StrokeRect(colorBounds(ColorSet::currentSet()->currentColorIndex())); |
1088 | } |
1089 | |
1090 | if (!highlight_selected) { |
1091 | // clear the highlight from selected color |
1092 | SetHighAndLowColors(ColorSet::currentSet()->currentColor()); |
1093 | FillRect(colorBounds(ColorSet::currentSet()->currentColorIndex()), |
1094 | HS_2X2_BLOCKS); |
1095 | } |
1096 | |
1097 | } |
1098 | |
1099 | |
1100 | void ColorContainer::MouseMoved(BPoint,uint32 transit,const BMessage*) |
1101 | { |
1102 | // These are posted to the window in case that the window contains |
1103 | // a help view. |
1104 | if ((transit == B_ENTERED_VIEW) && (Window()->IsActive())) { |
1105 | BMessage *help_message = new BMessage(HS_TEMPORARY_HELP_MESSAGE'ThlM'); |
1106 | help_message->AddString("message", |
1107 | B_TRANSLATE("Click to select a painting color.")BLocaleRoster::Default()->GetCatalog()->GetString(("Click to select a painting color." ), "ColorPalette")); |
1108 | Window()->PostMessage(help_message); |
1109 | delete help_message; |
1110 | } |
1111 | if (transit == B_EXITED_VIEW) { |
1112 | Window()->PostMessage(HS_TOOL_HELP_MESSAGE'TolM'); |
1113 | } |
1114 | } |
1115 | |
1116 | |
1117 | void ColorContainer::MessageReceived(BMessage *message) |
1118 | { |
1119 | switch (message->what) { |
1120 | |
1121 | // this message comes from ColorContainer::sendMessageToAllContainers and that function |
1122 | // is called in ColorWindow's MessageReceived, it's purpose is to inform |
1123 | case HS_PALETTE_CHANGED'PaCh': |
1124 | // here call the function that fits the view to |
1125 | // accommodate the new palette. 0 colors instructs the function |
1126 | // to look the amount from ColorSet. |
1127 | setUpContainer(Bounds(),0,FALSE0); |
1128 | Draw(Bounds()); |
1129 | break; |
1130 | |
1131 | case HS_NEXT_PALETTE'NxPl': { |
1132 | ColorSet::moveToNextSet(); |
1133 | BMessage paletteChanged(HS_PALETTE_CHANGED'PaCh'); |
1134 | ColorContainer::sendMessageToAllContainers(&paletteChanged); |
1135 | } break; |
1136 | case HS_PREVIOUS_PALETTE'PrPl': { |
1137 | ColorSet::moveToPrevSet(); |
1138 | BMessage paletteChanged(HS_PALETTE_CHANGED'PaCh'); |
1139 | ColorContainer::sendMessageToAllContainers(&paletteChanged); |
1140 | } break; |
1141 | |
1142 | // this message comes from ColorContainer::sendMessageToAllContainers and that function |
1143 | // is called in ColorWindow's MessageReceived, it informs us that one of the colors in the |
1144 | // set has been changed, this constant is used for the same purpose in a slight different context |
1145 | // the changed color is at "index" int32 data member in the message |
1146 | case HS_COLOR_CHANGED'CoCH': { |
1147 | // the colorset has been updated, we will draw using colorChanged-function |
1148 | colorChanged(message->FindInt32("index")); |
1149 | } break; |
1150 | |
1151 | case B_PASTE: { |
1152 | if (message->WasDropped()) { |
1153 | // Here we see on to which button it was dropped and then |
1154 | // try to extract a color from the message |
1155 | rgb_color *color; |
1156 | ssize_t color_size; |
1157 | if (message->FindData("RGBColor",B_RGB_COLOR_TYPE,(const void**)&color,&color_size) == B_OK((int)0)) { |
1158 | BPoint drop_point = message->DropPoint(); |
1159 | drop_point = ConvertFromScreen(drop_point); |
1160 | int32 index = pointIndex(drop_point); |
1161 | if (index >= 0) { |
1162 | ColorSet::currentSet()->setCurrentColorIndex(index); |
1163 | ColorSet::currentSet()->setCurrentColor(*color); |
1164 | BMessage a_message(HS_COLOR_CHANGED'CoCH'); |
1165 | a_message.AddInt32("index",index); |
1166 | ColorContainer::sendMessageToAllContainers(&a_message); |
1167 | a_message.what = HS_PALETTE_SELECTION_CHANGED'PslC'; |
1168 | ColorContainer::sendMessageToAllContainers(&a_message); |
1169 | Window()->PostMessage(HS_PALETTE_SELECTION_CHANGED'PslC',Window()); |
1170 | } |
1171 | } |
1172 | } |
1173 | } break; |
1174 | // this message comes from ColorContainer::sendMessageToAllContainers and that function |
1175 | // is called in ColorContainer::MouseDown, it informs us that the selected color in the |
1176 | // set has changed |
1177 | case HS_PALETTE_SELECTION_CHANGED'PslC': { |
1178 | // the selected color of palette has changed |
1179 | // if we highlight it then draw completely |
1180 | // because we don't know what was the previous color |
1181 | if (highlight_selected) |
1182 | Draw(Bounds()); |
1183 | } break; |
1184 | default: |
1185 | BView::MessageReceived(message); |
1186 | break; |
1187 | } |
1188 | } |
1189 | |
1190 | void ColorContainer::setUpContainer(BRect frame, int32 number_of_colors,bool add_arrows) |
1191 | { |
1192 | // This gets stuck in an infinite loop if the height of the frame |
1193 | // is negative. |
1194 | horiz_c_size = 3; |
1195 | vert_c_size = 3; |
1196 | horiz_gutter = 1; |
1197 | vert_gutter = 1; |
1198 | color_count = number_of_colors; |
1199 | row_count = 1; |
1200 | |
1201 | if (color_count == 0) { |
1202 | // here we take the new color-count from current color-set |
1203 | color_count = ColorSet::currentSet()->sizeOfSet(); |
1204 | } |
1205 | |
1206 | // first count how many rows are to be used |
1207 | while ((row_count<=color_count/row_count) && (row_count*vert_c_size<=frame.Height())) |
1208 | row_count *= 2; |
1209 | row_count /= 2; |
1210 | |
1211 | if (row_count < 1) |
1212 | row_count = 1; |
1213 | |
1214 | // then increase the row height to maximum |
1215 | while ((row_count*(vert_c_size + vert_gutter) - vert_gutter)<=frame.Height()) |
1216 | vert_c_size++; |
1217 | vert_c_size--; |
1218 | |
1219 | // then increase the width to maximum |
1220 | float maximum_width = frame.Width(); |
1221 | if (left_arrow != NULL__null) { |
1222 | maximum_width -= (left_arrow->Frame().right + 2); |
1223 | } |
1224 | while ((color_count/row_count*(horiz_c_size+horiz_gutter) - horiz_gutter) <= maximum_width) |
1225 | horiz_c_size++; |
1226 | horiz_c_size--; |
1227 | |
1228 | ResourceServer* server = ResourceServer::Instance(); |
1229 | if (add_arrows && server) { |
1230 | BPicture arrow_pushed; |
1231 | BPicture arrow_not_pushed; |
1232 | |
1233 | server->GetPicture(LEFT_ARROW, &arrow_not_pushed); |
1234 | server->GetPicture(LEFT_ARROW_PUSHED, &arrow_pushed); |
1235 | |
1236 | left_arrow = new BPictureButton(BRect(0, 0, 8, 12), "left_arrow", |
1237 | &arrow_not_pushed, &arrow_pushed, new BMessage(HS_PREVIOUS_PALETTE'PrPl')); |
1238 | AddChild(left_arrow); |
1239 | left_arrow->ResizeToPreferred(); |
1240 | left_arrow->MoveTo(BPoint(2, 2)); |
1241 | |
1242 | server->GetPicture(RIGHT_ARROW, &arrow_not_pushed); |
1243 | server->GetPicture(RIGHT_ARROW_PUSHED, &arrow_pushed); |
1244 | |
1245 | right_arrow = new BPictureButton(BRect(0, 0, 8, 12), "right_arrow", |
1246 | &arrow_not_pushed, &arrow_pushed, new BMessage(HS_NEXT_PALETTE'NxPl')); |
1247 | AddChild(right_arrow); |
1248 | right_arrow->ResizeToPreferred(); |
1249 | right_arrow->MoveTo(BPoint(2, left_arrow->Frame().bottom + 3)); |
1250 | |
1251 | contains_arrows = true; |
1252 | } |
1253 | |
1254 | // here resize the view to just fit the colors |
1255 | ResizeTo((color_count/row_count*(horiz_c_size+horiz_gutter) - horiz_gutter),(row_count*(vert_c_size + vert_gutter) - vert_gutter)); |
1256 | |
1257 | if (contains_arrows) { |
1258 | ResizeBy(left_arrow->Frame().right+2,0); |
1259 | } |
1260 | } |
1261 | |
1262 | |
1263 | void ColorContainer::SetHighAndLowColors(const rgb_color &c) |
1264 | { |
1265 | rgb_color low = c; |
1266 | rgb_color high = c; |
1267 | |
1268 | float coeff = c.alpha / 255.0; |
1269 | low.red = (uint8)(coeff*c.red); |
1270 | low.green = (uint8)(coeff*c.green); |
1271 | low.blue = (uint8)(coeff*c.blue); |
1272 | low.alpha = 255; |
1273 | |
1274 | high.red = (uint8)(coeff*c.red + (1-coeff)*255); |
1275 | high.green = (uint8)(coeff*c.green + (1-coeff)*255); |
1276 | high.blue = (uint8)(coeff*c.blue + (1-coeff)*255); |
1277 | high.alpha = 255; |
1278 | |
1279 | SetHighColor(high); |
1280 | SetLowColor(low); |
1281 | } |
1282 | |
1283 | BRect ColorContainer::colorBounds(int32 index) |
1284 | { |
1285 | // this function calculates the rectangle for the |
1286 | // palette entry at index that is to be drawn on screen |
1287 | BRect rect; |
1288 | int32 row=1,column=1; |
1289 | for (int32 i=0;i<index;i++) { |
1290 | if (column >= color_count/row_count) { |
1291 | column = 1; |
1292 | row++; |
1293 | } |
1294 | else |
1295 | column++; |
1296 | } |
1297 | rect = BRect((column-1)*(horiz_c_size + horiz_gutter),(row-1)*(vert_c_size + vert_gutter),column*(horiz_c_size + horiz_gutter) - horiz_gutter,row*(vert_c_size + vert_gutter) - vert_gutter); |
1298 | if ((contains_arrows == TRUE1) && (left_arrow != NULL__null)) { |
1299 | rect.OffsetBy(left_arrow->Frame().right + 2,0); |
1300 | } |
1301 | return rect; |
1302 | } |
1303 | |
1304 | |
1305 | int32 ColorContainer::pointIndex(BPoint point) |
1306 | { |
1307 | // this function returns which palette entry is at point in the view |
1308 | // or -1 if no entry is to found there |
1309 | // at the moment just calculate usin rect Contains-function |
1310 | // later should be implemented more elegantly |
1311 | |
1312 | for (int32 i=0;i<color_count;i++) { |
1313 | if (colorBounds(i).Contains(point)) |
1314 | return i; |
1315 | } |
1316 | |
1317 | // none of the rectangles contained point |
1318 | return -1; |
1319 | } |
1320 | |
1321 | void ColorContainer::colorChanged(int32 color_index) |
1322 | { |
1323 | // draw the new color |
1324 | rgb_color c = ColorSet::currentSet()->colorAt(color_index); |
1325 | rgb_color low = c; |
1326 | float coeff = c.alpha / 255.0; |
1327 | low.red = (uint8)(c.red*coeff); |
1328 | low.green = (uint8)(c.green*coeff); |
1329 | low.blue = (uint8)(c.blue*coeff); |
1330 | low.alpha = 255; |
1331 | |
1332 | c.red = (uint8)(c.red * coeff + (1-coeff)*255); |
1333 | c.green = (uint8)(c.green * coeff + (1-coeff)*255); |
1334 | c.blue = (uint8)(c.blue * coeff + (1-coeff)*255); |
1335 | c.alpha = 255; |
1336 | |
1337 | SetHighColor(c); |
1338 | SetLowColor(low); |
1339 | FillRect(colorBounds(color_index),HS_2X2_BLOCKS); |
1340 | |
1341 | // also draw the white rect around the color that is currently selected |
1342 | // could be some other that was changed |
1343 | if (highlight_selected) { |
1344 | SetHighColor(255,255,255); |
1345 | StrokeRect(colorBounds(ColorSet::currentSet()->currentColorIndex())); |
1346 | } |
1347 | // and we will Sync() |
1348 | Sync(); |
1349 | } |
1350 | |
1351 | |
1352 | void ColorContainer::sendMessageToAllContainers(BMessage *message) |
1353 | { |
1354 | // here go through the list of color containers |
1355 | // and post message to each of them |
1356 | |
1357 | for (int32 i=0;i<container_list->CountItems();i++) { |
1358 | ((ColorContainer*)container_list->ItemAt(i))->Window()->PostMessage(message,(ColorContainer*)container_list->ItemAt(i)); |
1359 | } |
1360 | } |
1361 | |
1362 | |
1363 | // here begins the definition of ColorSet-class |
1364 | // first initialize the static variables |
1365 | BList* ColorSet::color_set_list = new BList(); |
1366 | int32 ColorSet::current_set_index = 0; |
1367 | |
1368 | |
1369 | ColorSet::ColorSet(int32 amount_of_colors, ColorSet *copy_this_palette) |
1370 | { |
1371 | // first check that the amount of colors is reasonable |
1372 | amount_of_colors = min_c(amount_of_colors,256)((amount_of_colors)>(256)?(256):(amount_of_colors)); |
1373 | amount_of_colors = max_c(amount_of_colors,1)((amount_of_colors)>(1)?(amount_of_colors):(1)); |
1374 | |
1375 | // first allocate memory for the new palette |
1376 | palette = new rgb_color[amount_of_colors]; |
1377 | |
1378 | // allocate memory for name, 100 chars should be long enough |
1379 | name = new char[100]; |
1380 | |
1381 | if (copy_this_palette == NULL__null) { |
1382 | // if no palette was given to copy from make a default palette |
1383 | for (int32 i=0;i<amount_of_colors;i++) { |
1384 | palette[i].red = i*256/amount_of_colors; |
1385 | palette[i].green = i*256/amount_of_colors; |
1386 | palette[i].blue = i*256/amount_of_colors; |
1387 | palette[i].alpha = 255; |
1388 | } |
1389 | } |
1390 | else { |
1391 | // here we copy that palette |
1392 | int32 source_size = copy_this_palette->sizeOfSet(); |
1393 | for (int i=0;i<amount_of_colors;i++) { |
1394 | palette[i] = copy_this_palette->colorAt(i % source_size); |
1395 | } |
1396 | } |
1397 | // store the color count |
1398 | color_count = amount_of_colors; |
1399 | |
1400 | // create a default name |
1401 | strcpy(name,"default palette"); |
1402 | |
1403 | // put the current color to 0 |
1404 | current_color_index = 0; |
1405 | |
1406 | color_set_list->AddItem(this); |
1407 | } |
1408 | |
1409 | ColorSet::~ColorSet() |
1410 | { |
1411 | // remove ourselves from the color_set_list |
1412 | color_set_list->RemoveItem(this); |
1413 | current_set_index = min_c(current_set_index,color_set_list->CountItems()-1)((current_set_index)>(color_set_list->CountItems()-1)?( color_set_list->CountItems()-1):(current_set_index)); |
1414 | } |
1415 | |
1416 | |
1417 | rgb_color ColorSet::colorAt(int32 index) |
1418 | { |
1419 | // check that the index is correct |
1420 | if ((index>=0)&&(index<color_count)) { |
1421 | return palette[index]; |
1422 | } |
1423 | else { |
1424 | // otherwise return the first color |
1425 | return palette[0]; |
1426 | } |
1427 | } |
1428 | |
1429 | |
1430 | void ColorSet::setColor(int32 index, rgb_color color) |
1431 | { |
1432 | // check that the index is correct |
1433 | if ((index>=0)&&(index<color_count)) { |
1434 | palette[index] = color; |
1435 | } |
1436 | |
1437 | } |
1438 | |
1439 | |
1440 | void ColorSet::setName(const char *set_name) |
1441 | { |
1442 | strcpy(name,set_name); |
1443 | } |
1444 | |
1445 | |
1446 | char* ColorSet::getName() |
1447 | { |
1448 | return name; |
1449 | } |
1450 | |
1451 | |
1452 | status_t ColorSet::readSets(BFile &file) |
1453 | { |
1454 | int32 number_of_sets; |
1455 | |
1456 | if (file.Read(&number_of_sets,sizeof(int32)) != sizeof(int32)) |
1457 | return B_ERROR(-1); |
1458 | |
1459 | for (int32 i=0;i<number_of_sets;i++) { |
1460 | int32 size_of_set; |
1461 | if (file.Read(&size_of_set,sizeof(int32)) != sizeof(int32)) |
1462 | return B_ERROR(-1); |
1463 | |
1464 | ColorSet *new_set = new ColorSet(size_of_set); |
1465 | |
1466 | int32 name_length; |
1467 | char name[255]; |
1468 | file.Read(&name_length,sizeof(int32)); |
1469 | file.Read(name,name_length); |
1470 | name[name_length] = '\0'; |
1471 | |
1472 | new_set->setName(name); |
1473 | |
1474 | for (int32 b=0;b<size_of_set;b++) { |
1475 | rgb_color c; |
1476 | if (file.Read(&c,sizeof(rgb_color)) != sizeof(rgb_color)) |
1477 | return B_ERROR(-1); |
1478 | |
1479 | new_set->palette[b] = c; |
1480 | } |
1481 | } |
1482 | |
1483 | return B_OK((int)0); |
1484 | } |
1485 | |
1486 | |
1487 | status_t ColorSet::writeSets(BFile &file) |
1488 | { |
1489 | int32 written_value = color_set_list->CountItems(); |
1490 | |
1491 | if (file.Write(&written_value,sizeof(int32)) != sizeof(int32)) |
1492 | return B_ERROR(-1); |
1493 | |
1494 | for (int32 i=0;i<color_set_list->CountItems();i++) { |
1495 | written_value = ((ColorSet*)color_set_list->ItemAt(i))->sizeOfSet(); |
1496 | if (file.Write(&written_value,sizeof(int32)) != sizeof(int32)) |
1497 | return B_ERROR(-1); |
1498 | |
1499 | written_value = strlen(((ColorSet*)color_set_list->ItemAt(i))->getName()); |
1500 | if (file.Write(&written_value,sizeof(int32)) != sizeof(int32)) |
1501 | return B_ERROR(-1); |
1502 | |
1503 | written_value = file.Write(((ColorSet*)color_set_list->ItemAt(i))->getName(), |
1504 | strlen(((ColorSet*)color_set_list->ItemAt(i))->getName())); |
1505 | if (uint32(written_value) != strlen(((ColorSet*)color_set_list->ItemAt(i))->getName())) |
1506 | return B_ERROR(-1); |
1507 | |
1508 | // here write the palette entries |
1509 | for (int32 b=0;b<((ColorSet*)color_set_list->ItemAt(i))->sizeOfSet();b++) { |
1510 | rgb_color c = ((ColorSet*)color_set_list->ItemAt(i))->palette[b]; |
1511 | if (file.Write(&c,sizeof(rgb_color)) != sizeof(rgb_color)) |
1512 | return B_ERROR(-1); |
1513 | } |
1514 | } |
1515 | |
1516 | |
1517 | return B_OK((int)0); |
1518 | } |