fix bug where color chosen by sliders wouldn't be registered. Optimized a bit.
[wxWidgets.git] / src / generic / colrdlgg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/colrdlgg.cpp
3 // Purpose: Choice dialogs
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "colrdlgg.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_COLOURDLG && (!defined(__WXGTK20__) || defined(__WXUNIVERSAL__))
24
25 #ifndef WX_PRECOMP
26 #include "wx/utils.h"
27 #include "wx/intl.h"
28 #include "wx/dialog.h"
29 #include "wx/listbox.h"
30 #include "wx/button.h"
31 #include "wx/stattext.h"
32 #include "wx/layout.h"
33 #include "wx/dcclient.h"
34 #include "wx/slider.h"
35 #include "wx/sizer.h"
36 #endif
37
38 #if wxUSE_STATLINE
39 #include "wx/statline.h"
40 #endif
41
42 #include "wx/generic/colrdlgg.h"
43
44 IMPLEMENT_DYNAMIC_CLASS(wxGenericColourDialog, wxDialog)
45
46 BEGIN_EVENT_TABLE(wxGenericColourDialog, wxDialog)
47 EVT_BUTTON(wxID_ADD_CUSTOM, wxGenericColourDialog::OnAddCustom)
48 EVT_SLIDER(wxID_RED_SLIDER, wxGenericColourDialog::OnRedSlider)
49 EVT_SLIDER(wxID_GREEN_SLIDER, wxGenericColourDialog::OnGreenSlider)
50 EVT_SLIDER(wxID_BLUE_SLIDER, wxGenericColourDialog::OnBlueSlider)
51 EVT_PAINT(wxGenericColourDialog::OnPaint)
52 EVT_MOUSE_EVENTS(wxGenericColourDialog::OnMouseEvent)
53 EVT_CLOSE(wxGenericColourDialog::OnCloseWindow)
54 END_EVENT_TABLE()
55
56
57 /*
58 * Generic wxColourDialog
59 */
60
61 // don't change the number of elements (48) in this array, the code below is
62 // hardcoded to use it
63 static const wxChar *wxColourDialogNames[] =
64 {
65 wxT("ORANGE"),
66 wxT("GOLDENROD"),
67 wxT("WHEAT"),
68 wxT("SPRING GREEN"),
69 wxT("SKY BLUE"),
70 wxT("SLATE BLUE"),
71 wxT("MEDIUM VIOLET RED"),
72 wxT("PURPLE"),
73
74 wxT("RED"),
75 wxT("YELLOW"),
76 wxT("MEDIUM SPRING GREEN"),
77 wxT("PALE GREEN"),
78 wxT("CYAN"),
79 wxT("LIGHT STEEL BLUE"),
80 wxT("ORCHID"),
81 wxT("LIGHT MAGENTA"),
82
83 wxT("BROWN"),
84 wxT("YELLOW"),
85 wxT("GREEN"),
86 wxT("CADET BLUE"),
87 wxT("MEDIUM BLUE"),
88 wxT("MAGENTA"),
89 wxT("MAROON"),
90 wxT("ORANGE RED"),
91
92 wxT("FIREBRICK"),
93 wxT("CORAL"),
94 wxT("FOREST GREEN"),
95 wxT("AQUAMARINE"),
96 wxT("BLUE"),
97 wxT("NAVY"),
98 wxT("THISTLE"),
99 wxT("MEDIUM VIOLET RED"),
100
101 wxT("INDIAN RED"),
102 wxT("GOLD"),
103 wxT("MEDIUM SEA GREEN"),
104 wxT("MEDIUM BLUE"),
105 wxT("MIDNIGHT BLUE"),
106 wxT("GREY"),
107 wxT("PURPLE"),
108 wxT("KHAKI"),
109
110 wxT("BLACK"),
111 wxT("MEDIUM FOREST GREEN"),
112 wxT("KHAKI"),
113 wxT("DARK GREY"),
114 wxT("SEA GREEN"),
115 wxT("LIGHT GREY"),
116 wxT("MEDIUM SLATE BLUE"),
117 wxT("WHITE")
118 };
119
120 wxGenericColourDialog::wxGenericColourDialog()
121 {
122 dialogParent = NULL;
123 whichKind = 1;
124 colourSelection = -1;
125 }
126
127 wxGenericColourDialog::wxGenericColourDialog(wxWindow *parent,
128 wxColourData *data)
129 {
130 whichKind = 1;
131 colourSelection = -1;
132 Create(parent, data);
133 }
134
135 wxGenericColourDialog::~wxGenericColourDialog()
136 {
137 }
138
139 void wxGenericColourDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
140 {
141 EndModal(wxID_CANCEL);
142 }
143
144 bool wxGenericColourDialog::Create(wxWindow *parent, wxColourData *data)
145 {
146 if ( !wxDialog::Create(parent, wxID_ANY, _("Choose colour"),
147 wxPoint(0, 0), wxSize(900, 900)) )
148 return false;
149
150 dialogParent = parent;
151
152 if (data)
153 colourData = *data;
154
155 InitializeColours();
156 CalculateMeasurements();
157 CreateWidgets();
158
159 return true;
160 }
161
162 int wxGenericColourDialog::ShowModal()
163 {
164 int nResult = wxDialog::ShowModal();
165 colourData.SetColour(singleCustomColour);
166 return nResult;
167 }
168
169
170 // Internal functions
171 void wxGenericColourDialog::OnMouseEvent(wxMouseEvent& event)
172 {
173 if (event.ButtonDown(1))
174 {
175 int x = (int)event.GetX();
176 int y = (int)event.GetY();
177
178 #ifdef __WXPM__
179 // Handle OS/2's reverse coordinate system and account for the dialog title
180 int nClientHeight;
181
182 GetClientSize(NULL, &nClientHeight);
183 y = (nClientHeight - y) + 20;
184 #endif
185 if ((x >= standardColoursRect.x && x <= (standardColoursRect.x + standardColoursRect.width)) &&
186 (y >= standardColoursRect.y && y <= (standardColoursRect.y + standardColoursRect.height)))
187 {
188 int selX = (int)(x - standardColoursRect.x)/(smallRectangleSize.x + gridSpacing);
189 int selY = (int)(y - standardColoursRect.y)/(smallRectangleSize.y + gridSpacing);
190 int ptr = (int)(selX + selY*8);
191 OnBasicColourClick(ptr);
192 }
193 else if ((x >= customColoursRect.x && x <= (customColoursRect.x + customColoursRect.width)) &&
194 (y >= customColoursRect.y && y <= (customColoursRect.y + customColoursRect.height)))
195 {
196 int selX = (int)(x - customColoursRect.x)/(smallRectangleSize.x + gridSpacing);
197 int selY = (int)(y - customColoursRect.y)/(smallRectangleSize.y + gridSpacing);
198 int ptr = (int)(selX + selY*8);
199 OnCustomColourClick(ptr);
200 }
201 else
202 event.Skip();
203 }
204 else
205 event.Skip();
206 }
207
208 void wxGenericColourDialog::OnPaint(wxPaintEvent& event)
209 {
210 #if !defined(__WXMOTIF__) && !defined(__WXMAC__) && !defined(__WXPM__) && !defined(__WXCOCOA__)
211 wxDialog::OnPaint(event);
212 #endif
213
214 wxPaintDC dc(this);
215
216 PaintBasicColours(dc);
217 PaintCustomColours(dc);
218 PaintCustomColour(dc);
219 PaintHighlight(dc, true);
220 }
221
222 void wxGenericColourDialog::CalculateMeasurements()
223 {
224 smallRectangleSize.x = 18;
225 smallRectangleSize.y = 14;
226 customRectangleSize.x = 40;
227 customRectangleSize.y = 40;
228
229 gridSpacing = 6;
230 sectionSpacing = 15;
231
232 standardColoursRect.x = 10;
233 #ifdef __WXPM__
234 standardColoursRect.y = 15 + 20; /* OS/2 needs to account for dialog titlebar */
235 #else
236 standardColoursRect.y = 15;
237 #endif
238 standardColoursRect.width = (8*smallRectangleSize.x) + (7*gridSpacing);
239 standardColoursRect.height = (6*smallRectangleSize.y) + (5*gridSpacing);
240
241 customColoursRect.x = standardColoursRect.x;
242 customColoursRect.y = standardColoursRect.y + standardColoursRect.height + 20;
243 customColoursRect.width = (8*smallRectangleSize.x) + (7*gridSpacing);
244 customColoursRect.height = (2*smallRectangleSize.y) + (1*gridSpacing);
245
246 singleCustomColourRect.x = customColoursRect.width + customColoursRect.x + sectionSpacing;
247 singleCustomColourRect.y = 80;
248 singleCustomColourRect.width = customRectangleSize.x;
249 singleCustomColourRect.height = customRectangleSize.y;
250
251 okButtonX = 10;
252 customButtonX = singleCustomColourRect.x ;
253 buttonY = customColoursRect.y + customColoursRect.height + 10;
254 }
255
256 void wxGenericColourDialog::CreateWidgets()
257 {
258 wxBeginBusyCursor();
259
260 const int sliderX = singleCustomColourRect.x + singleCustomColourRect.width + sectionSpacing;
261 const int sliderHeight = 160;
262
263 redSlider = new wxSlider(this, wxID_RED_SLIDER, singleCustomColour.Red(), 0, 255,
264 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxVERTICAL|wxSL_LABELS);
265 greenSlider = new wxSlider(this, wxID_GREEN_SLIDER, singleCustomColour.Green(), 0, 255,
266 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxVERTICAL|wxSL_LABELS);
267 blueSlider = new wxSlider(this, wxID_BLUE_SLIDER, singleCustomColour.Blue(), 0, 255,
268 wxDefaultPosition, wxSize(wxDefaultCoord, sliderHeight), wxVERTICAL|wxSL_LABELS);
269
270 wxBoxSizer *sliderSizer = new wxBoxSizer( wxHORIZONTAL );
271
272 // 1) space for sliders
273 sliderSizer->Add( sliderX, sliderHeight );
274 sliderSizer->Add( redSlider, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 10 );
275 sliderSizer->Add( greenSlider, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 10 );
276 sliderSizer->Add( blueSlider, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 10 );
277
278 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
279
280 topSizer->Add( sliderSizer, 0, wxCENTRE | wxALL, 10 );
281
282 #if wxUSE_STATLINE
283 // 2) static line
284 topSizer->Add( new wxStaticLine( this, wxID_ANY ), 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10 );
285 #endif
286
287 // 3) buttons
288 wxSizer *buttonsizer = CreateButtonSizer( wxOK|wxCANCEL );
289 buttonsizer->Add( new wxButton(this, wxID_ADD_CUSTOM, _("Add to custom colours") ), 0, wxLEFT|wxRIGHT, 10 );
290 topSizer->Add( buttonsizer, 0, wxCENTRE | wxALL, 10 );
291
292 SetAutoLayout( true );
293 SetSizer( topSizer );
294
295 topSizer->SetSizeHints( this );
296 topSizer->Fit( this );
297
298 Centre( wxBOTH );
299
300 wxEndBusyCursor();
301 }
302
303 void wxGenericColourDialog::InitializeColours(void)
304 {
305 size_t i;
306
307 for (i = 0; i < WXSIZEOF(wxColourDialogNames); i++)
308 {
309 wxColour col = wxTheColourDatabase->Find(wxColourDialogNames[i]);
310 if (col.Ok())
311 standardColours[i].Set(col.Red(), col.Green(), col.Blue());
312 else
313 standardColours[i].Set(0, 0, 0);
314 }
315
316 for (i = 0; i < WXSIZEOF(customColours); i++)
317 {
318 wxColour c = colourData.GetCustomColour(i);
319 if (c.Ok())
320 customColours[i] = colourData.GetCustomColour(i);
321 else
322 customColours[i] = wxColour(255, 255, 255);
323 }
324
325 wxColour curr = colourData.GetColour();
326 if ( curr.Ok() )
327 {
328 bool initColourFound = false;
329
330 for (i = 0; i < WXSIZEOF(wxColourDialogNames); i++)
331 {
332 if ( standardColours[i] == curr && !initColourFound )
333 {
334 whichKind = 1;
335 colourSelection = i;
336 initColourFound = true;
337 break;
338 }
339 }
340 if ( !initColourFound )
341 {
342 for ( i = 0; i < WXSIZEOF(customColours); i++ )
343 {
344 if ( customColours[i] == curr )
345 {
346 whichKind = 2;
347 colourSelection = i;
348 break;
349 }
350 }
351 }
352 singleCustomColour.Set( curr.Red(), curr.Green(), curr.Blue() );
353 }
354 else
355 {
356 whichKind = 1;
357 colourSelection = 0;
358 singleCustomColour.Set( 0, 0, 0 );
359 }
360 }
361
362 void wxGenericColourDialog::PaintBasicColours(wxDC& dc)
363 {
364 dc.BeginDrawing();
365
366 int i;
367 for (i = 0; i < 6; i++)
368 {
369 int j;
370 for (j = 0; j < 8; j++)
371 {
372 int ptr = i*8 + j;
373
374 int x = (j*(smallRectangleSize.x+gridSpacing) + standardColoursRect.x);
375 int y = (i*(smallRectangleSize.y+gridSpacing) + standardColoursRect.y);
376
377 dc.SetPen(*wxBLACK_PEN);
378 wxBrush brush(standardColours[ptr], wxSOLID);
379 dc.SetBrush(brush);
380
381 dc.DrawRectangle( x, y, smallRectangleSize.x, smallRectangleSize.y);
382 }
383 }
384 dc.EndDrawing();
385 }
386
387 void wxGenericColourDialog::PaintCustomColours(wxDC& dc)
388 {
389 dc.BeginDrawing();
390
391 int i;
392 for (i = 0; i < 2; i++)
393 {
394 int j;
395 for (j = 0; j < 8; j++)
396 {
397 int ptr = i*8 + j;
398
399 int x = (j*(smallRectangleSize.x+gridSpacing)) + customColoursRect.x;
400 int y = (i*(smallRectangleSize.y+gridSpacing)) + customColoursRect.y;
401
402 dc.SetPen(*wxBLACK_PEN);
403
404 wxBrush brush(customColours[ptr], wxSOLID);
405 dc.SetBrush(brush);
406
407 dc.DrawRectangle( x, y, smallRectangleSize.x, smallRectangleSize.y);
408 }
409 }
410 dc.EndDrawing();
411 }
412
413 void wxGenericColourDialog::PaintHighlight(wxDC& dc, bool draw)
414 {
415 if ( colourSelection < 0 )
416 return;
417
418 dc.BeginDrawing();
419
420 // Number of pixels bigger than the standard rectangle size
421 // for drawing a highlight
422 int deltaX = 2;
423 int deltaY = 2;
424
425 if (whichKind == 1)
426 {
427 // Standard colours
428 int y = (int)(colourSelection / 8);
429 int x = (int)(colourSelection - (y*8));
430
431 x = (x*(smallRectangleSize.x + gridSpacing) + standardColoursRect.x) - deltaX;
432 y = (y*(smallRectangleSize.y + gridSpacing) + standardColoursRect.y) - deltaY;
433
434 if (draw)
435 dc.SetPen(*wxBLACK_PEN);
436 else
437 dc.SetPen(*wxLIGHT_GREY_PEN);
438
439 dc.SetBrush(*wxTRANSPARENT_BRUSH);
440 dc.DrawRectangle( x, y, (smallRectangleSize.x + (2*deltaX)), (smallRectangleSize.y + (2*deltaY)));
441 }
442 else
443 {
444 // User-defined colours
445 int y = (int)(colourSelection / 8);
446 int x = (int)(colourSelection - (y*8));
447
448 x = (x*(smallRectangleSize.x + gridSpacing) + customColoursRect.x) - deltaX;
449 y = (y*(smallRectangleSize.y + gridSpacing) + customColoursRect.y) - deltaY;
450
451 if (draw)
452 dc.SetPen(*wxBLACK_PEN);
453 else
454 dc.SetPen(*wxLIGHT_GREY_PEN);
455
456 dc.SetBrush(*wxTRANSPARENT_BRUSH);
457 dc.DrawRectangle( x, y, (smallRectangleSize.x + (2*deltaX)), (smallRectangleSize.y + (2*deltaY)));
458 }
459
460 dc.EndDrawing();
461 }
462
463 void wxGenericColourDialog::PaintCustomColour(wxDC& dc)
464 {
465 dc.BeginDrawing();
466
467 dc.SetPen(*wxBLACK_PEN);
468
469 wxBrush *brush = new wxBrush(singleCustomColour, wxSOLID);
470 dc.SetBrush(*brush);
471
472 dc.DrawRectangle( singleCustomColourRect.x, singleCustomColourRect.y,
473 customRectangleSize.x, customRectangleSize.y);
474
475 dc.SetBrush(wxNullBrush);
476 delete brush;
477
478 dc.EndDrawing();
479 }
480
481 void wxGenericColourDialog::OnBasicColourClick(int which)
482 {
483 wxClientDC dc(this);
484
485 PaintHighlight(dc, false);
486 whichKind = 1;
487 colourSelection = which;
488 redSlider->SetValue( standardColours[colourSelection].Red() );
489 greenSlider->SetValue( standardColours[colourSelection].Green() );
490 blueSlider->SetValue( standardColours[colourSelection].Blue() );
491 singleCustomColour.Set(standardColours[colourSelection].Red(), standardColours[colourSelection].Green(), standardColours[colourSelection].Blue());
492
493 PaintCustomColour(dc);
494 PaintHighlight(dc, true);
495 }
496
497 void wxGenericColourDialog::OnCustomColourClick(int which)
498 {
499 wxClientDC dc(this);
500 PaintHighlight(dc, false);
501 whichKind = 2;
502 colourSelection = which;
503 redSlider->SetValue( customColours[colourSelection].Red() );
504 greenSlider->SetValue( customColours[colourSelection].Green() );
505 blueSlider->SetValue( customColours[colourSelection].Blue() );
506 singleCustomColour.Set(customColours[colourSelection].Red(), customColours[colourSelection].Green(), customColours[colourSelection].Blue());
507 PaintCustomColour(dc);
508 PaintHighlight(dc, true);
509 }
510
511 /*
512 void wxGenericColourDialog::OnOk(void)
513 {
514 Show(false);
515 }
516
517 void wxGenericColourDialog::OnCancel(void)
518 {
519 colourDialogCancelled = true;
520 Show(false);
521 }
522 */
523
524 void wxGenericColourDialog::OnAddCustom(wxCommandEvent& WXUNUSED(event))
525 {
526 wxClientDC dc(this);
527 if (whichKind != 2)
528 {
529 PaintHighlight(dc, false);
530 whichKind = 2;
531 colourSelection = 0;
532 PaintHighlight(dc, true);
533 }
534
535 customColours[colourSelection].Set(singleCustomColour.Red(), singleCustomColour.Green(), singleCustomColour.Blue());
536 colourData.SetCustomColour(colourSelection, customColours[colourSelection]);
537
538 PaintCustomColours(dc);
539 }
540
541 void wxGenericColourDialog::OnRedSlider(wxCommandEvent& WXUNUSED(event))
542 {
543 if (!redSlider)
544 return;
545
546 wxClientDC dc(this);
547 singleCustomColour.Set((unsigned char)redSlider->GetValue(), singleCustomColour.Green(), singleCustomColour.Blue());
548 PaintCustomColour(dc);
549 }
550
551 void wxGenericColourDialog::OnGreenSlider(wxCommandEvent& WXUNUSED(event))
552 {
553 if (!greenSlider)
554 return;
555
556 wxClientDC dc(this);
557 singleCustomColour.Set(singleCustomColour.Red(), (unsigned char)greenSlider->GetValue(), singleCustomColour.Blue());
558 PaintCustomColour(dc);
559 }
560
561 void wxGenericColourDialog::OnBlueSlider(wxCommandEvent& WXUNUSED(event))
562 {
563 if (!blueSlider)
564 return;
565
566 wxClientDC dc(this);
567 singleCustomColour.Set(singleCustomColour.Red(), singleCustomColour.Green(), (unsigned char)blueSlider->GetValue());
568 PaintCustomColour(dc);
569 }
570
571 #endif // wxUSE_COLOURDLG && !defined(__WXGTK20__)
572