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