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