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