1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextsymboldlg.cpp
4 // Author: Julian Smart
6 // Created: 10/5/2006 3:11:58 PM
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
20 #include "wx/richtext/richtextsymboldlg.h"
24 #include "wx/stattext.h"
25 #include "wx/combobox.h"
26 #include "wx/button.h"
27 #include "wx/settings.h"
29 #include "wx/listbox.h"
32 #include "wx/dcbuffer.h"
34 // Only for cached font name
35 #include "wx/richtext/richtextctrl.h"
37 /* Microsoft Unicode subset numbering
43 U_LATIN_1_SUPPLEMENT
= 1,
44 U_LATIN_EXTENDED_A
= 2,
45 U_LATIN_EXTENDED_B
= 3,
47 U_SPACING_MODIFIER_LETTERS
= 5,
48 U_COMBINING_DIACRITICAL_MARKS
= 6,
50 U_GREEK_SYMBOLS_AND_COPTIC
= 8,
53 U_HEBREW_EXTENDED
= 12,
56 U_ARABIC_EXTENDED
= 14,
68 U_GEORGIAN_EXTENDED
= 27,
69 U_BASIC_GEORGIAN
= 26,
71 U_LATIN_EXTENDED_ADDITIONAL
= 29,
72 U_GREEK_EXTENDED
= 30,
73 U_GENERAL_PUNCTUATION
= 31,
74 U_SUPERSCRIPTS_AND_SUBSCRIPTS
= 32,
75 U_CURRENCY_SYMBOLS
= 33,
76 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS
= 34,
77 U_LETTERLIKE_SYMBOLS
= 35,
80 U_MATHEMATICAL_OPERATORS
= 38,
81 U_MISCELLANEOUS_TECHNICAL
= 39,
82 U_CONTROL_PICTURES
= 40,
83 U_OPTICAL_CHARACTER_RECOGNITION
= 41,
84 U_ENCLOSED_ALPHANUMERICS
= 42,
86 U_BLOCK_ELEMENTS
= 44,
87 U_GEOMETRIC_SHAPES
= 45,
88 U_MISCELLANEOUS_SYMBOLS
= 46,
90 U_CJK_SYMBOLS_AND_PUNCTUATION
= 48,
94 U_HANGUL_COMPATIBILITY_JAMO
= 52,
95 U_CJK_MISCELLANEOUS
= 53,
97 U_CJK_COMPATIBILITY
= 55,
99 U_HANGUL_SUPPLEMENTARY_A
= 57,
100 U_HANGUL_SUPPLEMENTARY_B
= 58,
101 U_CJK_UNIFIED_IDEOGRAPHS
= 59,
102 U_PRIVATE_USE_AREA
= 60,
103 U_CJK_COMPATIBILITY_IDEOGRAPHS
= 61,
104 U_ALPHABETIC_PRESENTATION_FORMS
= 62,
105 U_ARABIC_PRESENTATION_FORMS_A
= 63,
106 U_COMBINING_HALF_MARKS
= 64,
107 U_CJK_COMPATIBILITY_FORMS
= 65,
108 U_SMALL_FORM_VARIANTS
= 66,
109 U_ARABIC_PRESENTATION_FORMS_B
= 67,
111 U_HALFWIDTH_AND_FULLWIDTH_FORMS
= 68,
113 } wxUnicodeSubsetCodes
;
115 /* Unicode subsets */
121 wxUnicodeSubsetCodes m_subset
;
122 const wxChar
* m_name
;
123 } g_UnicodeSubsetTable
[] =
126 U_BASIC_LATIN
, wxT("Basic Latin") },
128 U_LATIN_1_SUPPLEMENT
, wxT("Latin-1 Supplement") },
130 U_LATIN_EXTENDED_A
, wxT("Latin Extended-A") },
132 U_LATIN_EXTENDED_B
, wxT("Latin Extended-B") },
134 U_IPA_EXTENSIONS
, wxT("IPA Extensions") },
136 U_SPACING_MODIFIER_LETTERS
, wxT("Spacing Modifier Letters") },
138 U_COMBINING_DIACRITICAL_MARKS
, wxT("Combining Diacritical Marks") },
140 U_BASIC_GREEK
, wxT("Basic Greek") },
142 U_GREEK_SYMBOLS_AND_COPTIC
, wxT("Greek Symbols and Coptic") },
144 U_CYRILLIC
, wxT("Cyrillic") },
146 U_ARMENIAN
, wxT("Armenian") },
148 U_HEBREW_EXTENDED
, wxT("Hebrew Extended") },
150 U_BASIC_HEBREW
, wxT("Basic Hebrew") },
152 U_BASIC_ARABIC
, wxT("Basic Arabic") },
154 U_ARABIC_EXTENDED
, wxT("Arabic Extended") },
156 U_DEVANAGARI
, wxT("Devanagari") },
158 U_BENGALI
, wxT("Bengali") },
160 U_GURMUKHI
, wxT("Gurmukhi") },
162 U_GUJARATI
, wxT("Gujarati") },
164 U_ORIYA
, wxT("Oriya") },
166 U_TAMIL
, wxT("Tamil") },
168 U_TELUGU
, wxT("Telugu") },
170 U_KANNADA
, wxT("Kannada") },
172 U_MALAYALAM
, wxT("Malayalam") },
174 U_THAI
, wxT("Thai") },
178 U_GEORGIAN_EXTENDED
, wxT("Georgian Extended") },
180 U_BASIC_GEORGIAN
, wxT("Basic Georgian") },
182 U_HANGUL_JAMO
, wxT("Hangul Jamo") },
184 U_LATIN_EXTENDED_ADDITIONAL
, wxT("Latin Extended Additional") },
186 U_GREEK_EXTENDED
, wxT("Greek Extended") },
188 U_GENERAL_PUNCTUATION
, wxT("General Punctuation") },
190 U_SUPERSCRIPTS_AND_SUBSCRIPTS
, wxT("Superscripts and Subscripts") },
192 U_CURRENCY_SYMBOLS
, wxT("Currency Symbols") },
194 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS
, wxT("Combining Diacritical Marks for Symbols") },
196 U_LETTERLIKE_SYMBOLS
, wxT("Letterlike Symbols") },
198 U_NUMBER_FORMS
, wxT("Number Forms") },
200 U_ARROWS
, wxT("Arrows") },
202 U_MATHEMATICAL_OPERATORS
, wxT("Mathematical Operators") },
204 U_MISCELLANEOUS_TECHNICAL
, wxT("Miscellaneous Technical") },
206 U_CONTROL_PICTURES
, wxT("Control Pictures") },
208 U_OPTICAL_CHARACTER_RECOGNITION
, wxT("Optical Character Recognition") },
210 U_ENCLOSED_ALPHANUMERICS
, wxT("Enclosed Alphanumerics") },
212 U_BOX_DRAWING
, wxT("Box Drawing") },
214 U_BLOCK_ELEMENTS
, wxT("Block Elements") },
216 U_GEOMETRIC_SHAPES
, wxT("Geometric Shapes") },
218 U_MISCELLANEOUS_SYMBOLS
, wxT("Miscellaneous Symbols") },
220 U_DINGBATS
, wxT("Dingbats") },
222 U_CJK_SYMBOLS_AND_PUNCTUATION
, wxT("CJK Symbols and Punctuation") },
224 U_HIRAGANA
, wxT("Hiragana") },
226 U_KATAKANA
, wxT("Katakana") },
228 U_BOPOMOFO
, wxT("Bopomofo") },
230 U_HANGUL_COMPATIBILITY_JAMO
, wxT("Hangul Compatibility Jamo") },
232 U_CJK_MISCELLANEOUS
, wxT("CJK Miscellaneous") },
234 U_ENCLOSED_CJK
, wxT("Enclosed CJK") },
236 U_CJK_COMPATIBILITY
, wxT("CJK Compatibility") },
238 U_CJK_UNIFIED_IDEOGRAPHS
, wxT("CJK Unified Ideographs Extension A") },
240 U_CJK_UNIFIED_IDEOGRAPHS
, wxT("CJK Unified Ideographs") },
242 U_HANGUL
, wxT("Hangul Syllables") },
244 U_PRIVATE_USE_AREA
, wxT("Private Use Area") },
246 U_CJK_COMPATIBILITY_IDEOGRAPHS
, wxT("CJK Compatibility Ideographs") },
248 U_ALPHABETIC_PRESENTATION_FORMS
, wxT("Alphabetic Presentation Forms") },
250 U_ARABIC_PRESENTATION_FORMS_A
, wxT("Arabic Presentation Forms-A") },
252 U_COMBINING_HALF_MARKS
, wxT("Combining Half Marks") },
254 U_CJK_COMPATIBILITY_FORMS
, wxT("CJK Compatibility Forms") },
256 U_SMALL_FORM_VARIANTS
, wxT("Small Form Variants") },
258 U_ARABIC_PRESENTATION_FORMS_B
, wxT("Arabic Presentation Forms-B") },
260 U_SPECIALS
, wxT("Specials") },
262 U_HALFWIDTH_AND_FULLWIDTH_FORMS
, wxT("Halfwidth and Fullwidth Forms") },
264 U_SPECIALS
, wxT("Specials") }
267 #endif // __UNICODE__
270 // Not yet used, but could be used to test under Win32 whether this subset is available
271 // for the given font. The Win32 function is allegedly not accurate, however.
272 bool wxSubsetValidForFont(int subsetIndex
, FONTSIGNATURE
*fontSig
)
274 return (fontSig
->fsUsb
[g_UnicodeSubsetTable
[subsetIndex
].m_subset
/32] & (1 << (g_UnicodeSubsetTable
[subsetIndex
].m_subset
% 32)));
278 bool wxSymbolPickerDialog::sm_showToolTips
= false;
281 * wxSymbolPickerDialog type definition
284 IMPLEMENT_DYNAMIC_CLASS( wxSymbolPickerDialog
, wxDialog
)
287 * wxSymbolPickerDialog event table definition
290 BEGIN_EVENT_TABLE( wxSymbolPickerDialog
, wxDialog
)
291 EVT_LISTBOX(ID_SYMBOLPICKERDIALOG_LISTCTRL
, wxSymbolPickerDialog::OnSymbolSelected
)
293 ////@begin wxSymbolPickerDialog event table entries
294 EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_FONT
, wxSymbolPickerDialog::OnFontCtrlSelected
)
295 #if defined(__UNICODE__)
296 EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_SUBSET
, wxSymbolPickerDialog::OnSubsetSelected
)
297 EVT_UPDATE_UI( ID_SYMBOLPICKERDIALOG_SUBSET
, wxSymbolPickerDialog::OnSymbolpickerdialogSubsetUpdate
)
300 #if defined(__UNICODE__)
301 EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_FROM
, wxSymbolPickerDialog::OnFromUnicodeSelected
)
304 EVT_UPDATE_UI( wxID_OK
, wxSymbolPickerDialog::OnOkUpdate
)
305 EVT_BUTTON( wxID_HELP
, wxSymbolPickerDialog::OnHelpClick
)
306 EVT_UPDATE_UI( wxID_HELP
, wxSymbolPickerDialog::OnHelpUpdate
)
307 ////@end wxSymbolPickerDialog event table entries
311 IMPLEMENT_HELP_PROVISION(wxSymbolPickerDialog
)
314 * wxSymbolPickerDialog constructors
317 wxSymbolPickerDialog::wxSymbolPickerDialog( )
322 wxSymbolPickerDialog::wxSymbolPickerDialog( const wxString
& symbol
, const wxString
& fontName
, const wxString
& normalTextFont
, wxWindow
* parent
, wxWindowID id
, const wxString
& caption
, const wxPoint
& pos
, const wxSize
& size
, long style
)
325 Create(symbol
, fontName
, normalTextFont
, parent
, id
, caption
, pos
, size
, style
);
329 * wxSymbolPickerDialog creator
332 bool wxSymbolPickerDialog::Create( const wxString
& symbol
, const wxString
& fontName
, const wxString
& normalTextFont
, wxWindow
* parent
, wxWindowID id
, const wxString
& caption
, const wxPoint
& pos
, const wxSize
& size
, long style
)
334 m_fontName
= fontName
;
335 m_normalTextFontName
= normalTextFont
;
338 ////@begin wxSymbolPickerDialog creation
339 SetExtraStyle(wxWS_EX_BLOCK_EVENTS
|wxDIALOG_EX_CONTEXTHELP
);
340 wxDialog::Create( parent
, id
, caption
, pos
, size
, style
);
345 GetSizer()->SetSizeHints(this);
348 ////@end wxSymbolPickerDialog creation
353 * Member initialisation for wxSymbolPickerDialog
356 void wxSymbolPickerDialog::Init()
358 ////@begin wxSymbolPickerDialog member initialisation
359 m_fromUnicode
= true;
361 #if defined(__UNICODE__)
364 m_symbolsCtrl
= NULL
;
365 m_symbolStaticCtrl
= NULL
;
366 m_characterCodeCtrl
= NULL
;
367 #if defined(__UNICODE__)
368 m_fromUnicodeCtrl
= NULL
;
370 m_stdButtonSizer
= NULL
;
371 ////@end wxSymbolPickerDialog member initialisation
372 m_dontUpdate
= false;
376 * Control creation for wxSymbolPickerDialog
379 void wxSymbolPickerDialog::CreateControls()
382 SetWindowVariant(wxWINDOW_VARIANT_SMALL
);
385 ////@begin wxSymbolPickerDialog content construction
386 wxSymbolPickerDialog
* itemDialog1
= this;
388 wxBoxSizer
* itemBoxSizer2
= new wxBoxSizer(wxVERTICAL
);
389 itemDialog1
->SetSizer(itemBoxSizer2
);
391 wxBoxSizer
* itemBoxSizer3
= new wxBoxSizer(wxVERTICAL
);
392 itemBoxSizer2
->Add(itemBoxSizer3
, 1, wxGROW
|wxALL
, 5);
394 wxBoxSizer
* itemBoxSizer4
= new wxBoxSizer(wxHORIZONTAL
);
395 itemBoxSizer3
->Add(itemBoxSizer4
, 0, wxGROW
, 5);
397 wxBoxSizer
* itemBoxSizer5
= new wxBoxSizer(wxHORIZONTAL
);
398 itemBoxSizer4
->Add(itemBoxSizer5
, 1, wxGROW
, 5);
400 wxStaticText
* itemStaticText6
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&Font:"), wxDefaultPosition
, wxDefaultSize
, 0 );
401 itemBoxSizer5
->Add(itemStaticText6
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
403 wxArrayString m_fontCtrlStrings
;
404 m_fontCtrl
= new wxComboBox( itemDialog1
, ID_SYMBOLPICKERDIALOG_FONT
, wxEmptyString
, wxDefaultPosition
, wxSize(240, -1), m_fontCtrlStrings
, wxCB_READONLY
);
405 m_fontCtrl
->SetHelpText(_("The font from which to take the symbol."));
406 if (wxSymbolPickerDialog::ShowToolTips())
407 m_fontCtrl
->SetToolTip(_("The font from which to take the symbol."));
408 itemBoxSizer5
->Add(m_fontCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
410 itemBoxSizer5
->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
412 #if defined(__UNICODE__)
413 wxStaticText
* itemStaticText9
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&Subset:"), wxDefaultPosition
, wxDefaultSize
, 0 );
414 itemBoxSizer5
->Add(itemStaticText9
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
418 #if defined(__UNICODE__)
419 wxArrayString m_subsetCtrlStrings
;
420 m_subsetCtrl
= new wxComboBox( itemDialog1
, ID_SYMBOLPICKERDIALOG_SUBSET
, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, m_subsetCtrlStrings
, wxCB_READONLY
);
421 m_subsetCtrl
->SetHelpText(_("Shows a Unicode subset."));
422 if (wxSymbolPickerDialog::ShowToolTips())
423 m_subsetCtrl
->SetToolTip(_("Shows a Unicode subset."));
424 itemBoxSizer5
->Add(m_subsetCtrl
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
428 m_symbolsCtrl
= new wxSymbolListCtrl( itemDialog1
, ID_SYMBOLPICKERDIALOG_LISTCTRL
, wxDefaultPosition
, wxSize(500, 200), 0 );
429 itemBoxSizer3
->Add(m_symbolsCtrl
, 1, wxGROW
|wxALL
, 5);
431 wxBoxSizer
* itemBoxSizer12
= new wxBoxSizer(wxHORIZONTAL
);
432 itemBoxSizer3
->Add(itemBoxSizer12
, 0, wxGROW
, 5);
434 m_symbolStaticCtrl
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("xxxx"), wxDefaultPosition
, wxSize(40, -1), wxALIGN_CENTRE
);
435 itemBoxSizer12
->Add(m_symbolStaticCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
437 itemBoxSizer12
->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
439 wxStaticText
* itemStaticText15
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&Character code:"), wxDefaultPosition
, wxDefaultSize
, 0 );
440 itemBoxSizer12
->Add(itemStaticText15
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
442 m_characterCodeCtrl
= new wxTextCtrl( itemDialog1
, ID_SYMBOLPICKERDIALOG_CHARACTERCODE
, wxEmptyString
, wxDefaultPosition
, wxSize(140, -1), wxTE_READONLY
|wxTE_CENTRE
);
443 m_characterCodeCtrl
->SetHelpText(_("The character code."));
444 if (wxSymbolPickerDialog::ShowToolTips())
445 m_characterCodeCtrl
->SetToolTip(_("The character code."));
446 itemBoxSizer12
->Add(m_characterCodeCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
448 itemBoxSizer12
->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
450 #if defined(__UNICODE__)
451 wxStaticText
* itemStaticText18
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&From:"), wxDefaultPosition
, wxDefaultSize
, 0 );
452 itemBoxSizer12
->Add(itemStaticText18
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
456 #if defined(__UNICODE__)
457 wxArrayString m_fromUnicodeCtrlStrings
;
458 m_fromUnicodeCtrlStrings
.Add(_("ASCII"));
459 m_fromUnicodeCtrlStrings
.Add(_("Unicode"));
460 m_fromUnicodeCtrl
= new wxComboBox( itemDialog1
, ID_SYMBOLPICKERDIALOG_FROM
, _("Unicode"), wxDefaultPosition
, wxDefaultSize
, m_fromUnicodeCtrlStrings
, wxCB_READONLY
);
461 m_fromUnicodeCtrl
->SetStringSelection(_("Unicode"));
462 m_fromUnicodeCtrl
->SetHelpText(_("The range to show."));
463 if (wxSymbolPickerDialog::ShowToolTips())
464 m_fromUnicodeCtrl
->SetToolTip(_("The range to show."));
465 itemBoxSizer12
->Add(m_fromUnicodeCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
469 m_stdButtonSizer
= new wxStdDialogButtonSizer
;
471 itemBoxSizer3
->Add(m_stdButtonSizer
, 0, wxGROW
|wxTOP
|wxBOTTOM
, 5);
472 wxButton
* itemButton21
= new wxButton( itemDialog1
, wxID_OK
, _("Insert"), wxDefaultPosition
, wxDefaultSize
, 0 );
473 itemButton21
->SetDefault();
474 m_stdButtonSizer
->AddButton(itemButton21
);
476 wxButton
* itemButton22
= new wxButton( itemDialog1
, wxID_CANCEL
, _("Close"), wxDefaultPosition
, wxDefaultSize
, 0 );
477 m_stdButtonSizer
->AddButton(itemButton22
);
479 wxButton
* itemButton23
= new wxButton( itemDialog1
, wxID_HELP
, _("&Help"), wxDefaultPosition
, wxDefaultSize
, 0 );
480 m_stdButtonSizer
->AddButton(itemButton23
);
482 m_stdButtonSizer
->Realize();
484 ////@end wxSymbolPickerDialog content construction
486 if (GetHelpId() == -1)
488 wxWindow
* button
= FindWindowById(wxID_HELP
);
490 m_stdButtonSizer
->Show(button
, false);
495 bool wxSymbolPickerDialog::TransferDataToWindow()
499 if (m_fontCtrl
->GetCount() == 0)
501 wxArrayString faceNames
= wxRichTextCtrl::GetAvailableFontNames();
504 faceNames
.Insert(_("(Normal text)"), 0);
505 m_fontCtrl
->Append(faceNames
);
508 if (m_fontName
.empty())
509 m_fontCtrl
->SetSelection(0);
512 if (m_fontCtrl
->FindString(m_fontName
) != wxNOT_FOUND
)
513 m_fontCtrl
->SetStringSelection(m_fontName
);
515 m_fontCtrl
->SetSelection(0);
518 #if defined(__UNICODE__)
519 if (m_subsetCtrl
->GetCount() == 0)
521 // Insert items into subset combo
523 for (i
= 0; i
< (int) WXSIZEOF(g_UnicodeSubsetTable
); i
++)
525 m_subsetCtrl
->Append(g_UnicodeSubsetTable
[i
].m_name
);
527 m_subsetCtrl
->SetSelection(0);
531 #if defined(__UNICODE__)
532 m_symbolsCtrl
->SetUnicodeMode(m_fromUnicode
);
535 if (!m_symbol
.empty())
537 int sel
= (int) m_symbol
[0];
538 m_symbolsCtrl
->SetSelection(sel
);
541 UpdateSymbolDisplay(true, m_symbol
.empty());
543 m_dontUpdate
= false;
548 void wxSymbolPickerDialog::UpdateSymbolDisplay(bool updateSymbolList
, bool showAtSubset
)
551 wxString fontNameToUse
;
552 if (m_fontName
.empty())
553 fontNameToUse
= m_normalTextFontName
;
555 fontNameToUse
= m_fontName
;
557 if (!fontNameToUse
.empty())
559 font
= wxFont(14, wxDEFAULT
, wxNORMAL
, wxNORMAL
, false, fontNameToUse
);
562 font
= *wxNORMAL_FONT
;
564 if (updateSymbolList
)
566 m_symbolsCtrl
->SetFont(font
);
569 if (!m_symbol
.empty())
571 m_symbolStaticCtrl
->SetFont(font
);
572 m_symbolStaticCtrl
->SetLabel(m_symbol
);
574 int symbol
= (int) m_symbol
[0];
575 m_characterCodeCtrl
->SetValue(wxString::Format(wxT("%X hex (%d dec)"), symbol
, symbol
));
579 m_symbolStaticCtrl
->SetLabel(wxEmptyString
);
580 m_characterCodeCtrl
->SetValue(wxEmptyString
);
583 #if defined(__UNICODE__)
587 wxUnusedVar(showAtSubset
);
591 /// Show at the current subset selection
592 void wxSymbolPickerDialog::ShowAtSubset()
594 #if defined(__UNICODE__)
597 int sel
= m_subsetCtrl
->GetSelection();
598 int low
= g_UnicodeSubsetTable
[sel
].m_low
;
599 m_symbolsCtrl
->EnsureVisible(low
);
604 // Handle font selection
605 void wxSymbolPickerDialog::OnFontCtrlSelected( wxCommandEvent
& WXUNUSED(event
) )
607 if (m_fontCtrl
->GetSelection() == 0)
608 m_fontName
= wxEmptyString
;
610 m_fontName
= m_fontCtrl
->GetStringSelection();
612 UpdateSymbolDisplay();
615 /// Respond to symbol selection
616 void wxSymbolPickerDialog::OnSymbolSelected( wxCommandEvent
& event
)
621 int sel
= event
.GetSelection();
622 if (sel
== wxNOT_FOUND
)
623 m_symbol
= wxEmptyString
;
626 m_symbol
= wxEmptyString
;
627 m_symbol
<< (wxChar
) sel
;
630 #if defined(__UNICODE__)
631 if (sel
!= -1 && m_fromUnicode
)
633 // Need to make the subset selection reflect the current symbol
635 for (i
= 0; i
< (int) WXSIZEOF(g_UnicodeSubsetTable
); i
++)
637 if (sel
>= g_UnicodeSubsetTable
[i
].m_low
&& sel
<= g_UnicodeSubsetTable
[i
].m_high
)
640 m_subsetCtrl
->SetSelection(i
);
641 m_dontUpdate
= false;
648 UpdateSymbolDisplay(false, false);
651 #if defined(__UNICODE__)
652 // Handle Unicode/ASCII selection
653 void wxSymbolPickerDialog::OnFromUnicodeSelected( wxCommandEvent
& WXUNUSED(event
) )
658 m_fromUnicode
= (m_fromUnicodeCtrl
->GetSelection() == 1);
659 m_symbolsCtrl
->SetUnicodeMode(m_fromUnicode
);
660 UpdateSymbolDisplay(false);
663 // Handle subset selection
664 void wxSymbolPickerDialog::OnSubsetSelected( wxCommandEvent
& WXUNUSED(event
) )
673 #if defined(__UNICODE__)
676 * wxEVT_UPDATE_UI event handler for ID_SYMBOLPICKERDIALOG_SUBSET
679 void wxSymbolPickerDialog::OnSymbolpickerdialogSubsetUpdate( wxUpdateUIEvent
& event
)
681 event
.Enable(m_fromUnicode
);
686 * wxEVT_UPDATE_UI event handler for wxID_OK
689 void wxSymbolPickerDialog::OnOkUpdate( wxUpdateUIEvent
& event
)
691 event
.Enable(HasSelection());
695 void wxSymbolPickerDialog::SetUnicodeMode(bool unicodeMode
)
697 #if defined(__UNICODE__)
699 m_fromUnicode
= unicodeMode
;
700 if (m_fromUnicodeCtrl
)
701 m_fromUnicodeCtrl
->SetSelection(m_fromUnicode
? 1 : 0);
702 UpdateSymbolDisplay();
703 m_dontUpdate
= false;
705 wxUnusedVar(unicodeMode
);
709 /// Get the selected symbol character
710 int wxSymbolPickerDialog::GetSymbolChar() const
712 if (m_symbol
.empty())
715 return (int) m_symbol
[0];
720 * Get bitmap resources
723 wxBitmap
wxSymbolPickerDialog::GetBitmapResource( const wxString
& name
)
726 ////@begin wxSymbolPickerDialog bitmap retrieval
729 ////@end wxSymbolPickerDialog bitmap retrieval
736 wxIcon
wxSymbolPickerDialog::GetIconResource( const wxString
& name
)
739 ////@begin wxSymbolPickerDialog icon retrieval
742 ////@end wxSymbolPickerDialog icon retrieval
746 * The scrolling symbol list.
749 // ----------------------------------------------------------------------------
751 // ----------------------------------------------------------------------------
753 BEGIN_EVENT_TABLE(wxSymbolListCtrl
, wxVScrolledWindow
)
754 EVT_PAINT(wxSymbolListCtrl::OnPaint
)
755 EVT_SIZE(wxSymbolListCtrl::OnSize
)
757 EVT_KEY_DOWN(wxSymbolListCtrl::OnKeyDown
)
758 EVT_LEFT_DOWN(wxSymbolListCtrl::OnLeftDown
)
759 EVT_LEFT_DCLICK(wxSymbolListCtrl::OnLeftDClick
)
762 // ============================================================================
764 // ============================================================================
766 IMPLEMENT_ABSTRACT_CLASS(wxSymbolListCtrl
, wxVScrolledWindow
)
768 // ----------------------------------------------------------------------------
769 // wxSymbolListCtrl creation
770 // ----------------------------------------------------------------------------
772 void wxSymbolListCtrl::Init()
774 m_current
= wxNOT_FOUND
;
775 m_doubleBuffer
= NULL
;
776 m_cellSize
= wxSize(40, 40);
777 m_minSymbolValue
= 0;
778 m_maxSymbolValue
= 255;
779 m_symbolsPerLine
= 0;
780 m_unicodeMode
= false;
783 bool wxSymbolListCtrl::Create(wxWindow
*parent
,
788 const wxString
& name
)
790 style
|= wxWANTS_CHARS
| wxFULL_REPAINT_ON_RESIZE
;
792 if ((style
& wxBORDER_MASK
) == wxBORDER_DEFAULT
)
793 style
|= wxBORDER_THEME
;
795 if ( !wxVScrolledWindow::Create(parent
, id
, pos
, size
, style
, name
) )
798 // make sure the native widget has the right colour since we do
799 // transparent drawing by default
800 SetBackgroundColour(GetBackgroundColour());
801 m_colBgSel
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
803 // flicker-free drawing requires this
804 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
806 SetFont(*wxNORMAL_FONT
);
810 SetInitialSize(size
);
815 wxSymbolListCtrl::~wxSymbolListCtrl()
817 delete m_doubleBuffer
;
820 // ----------------------------------------------------------------------------
821 // selection handling
822 // ----------------------------------------------------------------------------
824 bool wxSymbolListCtrl::IsSelected(int item
) const
826 return item
== m_current
;
829 bool wxSymbolListCtrl::DoSetCurrent(int current
)
831 wxASSERT_MSG( current
== wxNOT_FOUND
||
832 (current
>= m_minSymbolValue
&& current
<= m_maxSymbolValue
),
833 wxT("wxSymbolListCtrl::DoSetCurrent(): invalid symbol value") );
835 if ( current
== m_current
)
841 if ( m_current
!= wxNOT_FOUND
)
842 RefreshRow(SymbolValueToLineNumber(m_current
));
846 if ( m_current
!= wxNOT_FOUND
)
848 int lineNo
= SymbolValueToLineNumber(m_current
);
850 // if the line is not visible at all, we scroll it into view but we
851 // don't need to refresh it -- it will be redrawn anyhow
852 if ( !IsVisible(lineNo
) )
856 else // line is at least partly visible
858 // it is, indeed, only partly visible, so scroll it into view to
859 // make it entirely visible
860 while ( (unsigned)lineNo
+ 1 == GetVisibleEnd() &&
861 ScrollToRow(GetVisibleBegin() + 1) )
864 // but in any case refresh it as even if it was only partly visible
865 // before we need to redraw it entirely as its background changed
873 void wxSymbolListCtrl::SendSelectedEvent()
875 wxCommandEvent
event(wxEVT_LISTBOX
, GetId());
876 event
.SetEventObject(this);
877 event
.SetInt(m_current
);
879 (void)GetEventHandler()->ProcessEvent(event
);
882 void wxSymbolListCtrl::SetSelection(int selection
)
884 wxCHECK_RET( selection
== wxNOT_FOUND
||
885 (selection
>= m_minSymbolValue
&& selection
< m_maxSymbolValue
),
886 wxT("wxSymbolListCtrl::SetSelection(): invalid symbol value") );
888 DoSetCurrent(selection
);
891 // ----------------------------------------------------------------------------
892 // wxSymbolListCtrl appearance parameters
893 // ----------------------------------------------------------------------------
895 void wxSymbolListCtrl::SetMargins(const wxPoint
& pt
)
897 if ( pt
!= m_ptMargins
)
905 void wxSymbolListCtrl::SetSelectionBackground(const wxColour
& col
)
910 // ----------------------------------------------------------------------------
911 // wxSymbolListCtrl painting
912 // ----------------------------------------------------------------------------
914 wxCoord
wxSymbolListCtrl::OnGetRowHeight(size_t WXUNUSED(line
)) const
916 return m_cellSize
.y
+ 2*m_ptMargins
.y
+ 1 /* for divider */ ;
919 // draws a line of symbols
920 void wxSymbolListCtrl::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
922 wxColour oldTextColour
= dc
.GetTextForeground();
923 int startSymbol
= n
*m_symbolsPerLine
;
926 for (i
= 0; i
< m_symbolsPerLine
; i
++)
928 bool resetColour
= false;
929 int symbol
= startSymbol
+i
;
930 if (symbol
== m_current
)
932 dc
.SetBrush(wxBrush(m_colBgSel
));
934 dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
));
937 wxPen oldPen
= dc
.GetPen();
938 dc
.SetPen(*wxTRANSPARENT_PEN
);
940 dc
.DrawRectangle(rect
.x
+ i
*m_cellSize
.x
, rect
.y
, m_cellSize
.x
, rect
.y
+rect
.height
);
944 // Don't draw first line
946 dc
.DrawLine(rect
.x
+ i
*m_cellSize
.x
, rect
.y
, i
*m_cellSize
.x
, rect
.y
+rect
.height
);
948 if (symbol
>= m_minSymbolValue
&& symbol
<= m_maxSymbolValue
)
951 text
<< (wxChar
) symbol
;
954 dc
.GetTextExtent(text
, & w
, & h
);
956 int x
= rect
.x
+ i
*m_cellSize
.x
+ (m_cellSize
.x
- w
)/2;
957 int y
= rect
.y
+ (m_cellSize
.y
- h
)/2;
958 dc
.DrawText(text
, x
, y
);
962 dc
.SetTextForeground(oldTextColour
);
965 // Draw horizontal separator line
966 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1, rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
969 void wxSymbolListCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
971 // If size is larger, recalculate double buffer bitmap
972 wxSize clientSize
= GetClientSize();
974 if ( !m_doubleBuffer
||
975 clientSize
.x
> m_doubleBuffer
->GetWidth() ||
976 clientSize
.y
> m_doubleBuffer
->GetHeight() )
978 delete m_doubleBuffer
;
979 m_doubleBuffer
= new wxBitmap(clientSize
.x
+25,clientSize
.y
+25);
982 wxBufferedPaintDC
dc(this,*m_doubleBuffer
);
984 // the update rectangle
985 wxRect rectUpdate
= GetUpdateClientRect();
987 // fill it with background colour
988 dc
.SetBackground(GetBackgroundColour());
991 // set the font to be displayed
992 dc
.SetFont(GetFont());
994 // the bounding rectangle of the current line
996 rectRow
.width
= clientSize
.x
;
998 dc
.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)));
999 dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
));
1000 dc
.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT
);
1002 // iterate over all visible lines
1003 const size_t lineMax
= GetVisibleEnd();
1004 for ( size_t line
= GetVisibleBegin(); line
< lineMax
; line
++ )
1006 const wxCoord hRow
= OnGetRowHeight(line
);
1008 rectRow
.height
= hRow
;
1010 // and draw the ones which intersect the update rect
1011 if ( rectRow
.Intersects(rectUpdate
) )
1013 // don't allow drawing outside of the lines rectangle
1014 wxDCClipper
clip(dc
, rectRow
);
1016 wxRect rect
= rectRow
;
1017 rect
.Deflate(m_ptMargins
.x
, m_ptMargins
.y
);
1018 OnDrawItem(dc
, rect
, line
);
1020 else // no intersection
1022 if ( rectRow
.GetTop() > rectUpdate
.GetBottom() )
1024 // we are already below the update rect, no need to continue
1028 //else: the next line may intersect the update rect
1035 // ============================================================================
1036 // wxSymbolListCtrl keyboard/mouse handling
1037 // ============================================================================
1039 void wxSymbolListCtrl::DoHandleItemClick(int item
, int WXUNUSED(flags
))
1041 if (m_current
!= item
)
1045 SendSelectedEvent();
1049 // ----------------------------------------------------------------------------
1050 // keyboard handling
1051 // ----------------------------------------------------------------------------
1053 void wxSymbolListCtrl::OnKeyDown(wxKeyEvent
& event
)
1055 // No keyboard interface for now
1058 // flags for DoHandleItemClick()
1059 int flags
= ItemClick_Kbd
;
1061 int currentLineNow
= SymbolValueToLineNumber(m_current
);
1064 switch ( event
.GetKeyCode() )
1071 currentLine
= GetLineCount() - 1;
1075 if ( currentLineNow
== (int)GetLineCount() - 1 )
1078 currentLine
= currentLineNow
+ 1;
1082 if ( m_current
== wxNOT_FOUND
)
1083 currentLine
= GetLineCount() - 1;
1084 else if ( currentLineNow
!= 0 )
1085 currentLine
= currentLineNow
- 1;
1086 else // currentLineNow == 0
1092 currentLine
= GetFirstVisibleLine();
1096 if ( currentLineNow
== (int)GetFirstVisibleLine() )
1101 currentLine
= GetFirstVisibleLine();
1105 // hack: pressing space should work like a mouse click rather than
1106 // like a keyboard arrow press, so trick DoHandleItemClick() in
1107 // thinking we were clicked
1108 flags
&= ~ItemClick_Kbd
;
1109 currentLine
= currentLineNow
;
1114 // Since we are using wxWANTS_CHARS we need to send navigation
1115 // events for the tabs on MSW
1117 wxNavigationKeyEvent ne
;
1118 ne
.SetDirection(!event
.ShiftDown());
1119 ne
.SetCurrentFocus(this);
1120 ne
.SetEventObject(this);
1121 GetParent()->GetEventHandler()->ProcessEvent(ne
);
1123 // fall through to default
1127 currentLine
= 0; // just to silent the stupid compiler warnings
1128 wxUnusedVar(currentNow
);
1133 if ( event
.ShiftDown() )
1134 flags
|= ItemClick_Shift
;
1135 if ( event
.ControlDown() )
1136 flags
|= ItemClick_Ctrl
;
1138 DoHandleItemClick(current
, flags
);
1143 // ----------------------------------------------------------------------------
1144 // wxSymbolListCtrl mouse handling
1145 // ----------------------------------------------------------------------------
1147 void wxSymbolListCtrl::OnLeftDown(wxMouseEvent
& event
)
1151 int item
= HitTest(event
.GetPosition());
1153 if ( item
!= wxNOT_FOUND
)
1156 if ( event
.ShiftDown() )
1157 flags
|= ItemClick_Shift
;
1159 // under Mac Apple-click is used in the same way as Ctrl-click
1162 if ( event
.MetaDown() )
1164 if ( event
.ControlDown() )
1166 flags
|= ItemClick_Ctrl
;
1168 DoHandleItemClick(item
, flags
);
1172 void wxSymbolListCtrl::OnLeftDClick(wxMouseEvent
& eventMouse
)
1174 int item
= HitTest(eventMouse
.GetPosition());
1175 if ( item
!= wxNOT_FOUND
)
1178 // if item double-clicked was not yet selected, then treat
1179 // this event as a left-click instead
1180 if ( item
== m_current
)
1182 wxCommandEvent
event(wxEVT_LISTBOX_DCLICK
, GetId());
1183 event
.SetEventObject(this);
1186 (void)GetEventHandler()->ProcessEvent(event
);
1190 OnLeftDown(eventMouse
);
1196 // calculate line number from symbol value
1197 int wxSymbolListCtrl::SymbolValueToLineNumber(int item
)
1199 return (int) (item
/m_symbolsPerLine
);
1202 // initialise control from current min/max values
1203 void wxSymbolListCtrl::SetupCtrl(bool scrollToSelection
)
1205 wxSize sz
= GetClientSize();
1207 m_symbolsPerLine
= sz
.x
/(m_cellSize
.x
+m_ptMargins
.x
);
1208 int noLines
= (1 + SymbolValueToLineNumber(m_maxSymbolValue
));
1210 SetRowCount(noLines
);
1213 if (scrollToSelection
&& m_current
!= wxNOT_FOUND
&& m_current
>= m_minSymbolValue
&& m_current
<= m_maxSymbolValue
)
1215 ScrollToRow(SymbolValueToLineNumber(m_current
));
1219 // make this item visible
1220 void wxSymbolListCtrl::EnsureVisible(int item
)
1222 if (item
!= wxNOT_FOUND
&& item
>= m_minSymbolValue
&& item
<= m_maxSymbolValue
)
1224 ScrollToRow(SymbolValueToLineNumber(item
));
1230 int wxSymbolListCtrl::HitTest(const wxPoint
& pt
)
1232 wxCoord lineHeight
= OnGetRowHeight(0);
1234 int atLine
= GetVisibleBegin() + (pt
.y
/lineHeight
);
1235 int symbol
= (atLine
*m_symbolsPerLine
) + (pt
.x
/(m_cellSize
.x
+1));
1237 if (symbol
>= m_minSymbolValue
&& symbol
<= m_maxSymbolValue
)
1243 // Respond to size change
1244 void wxSymbolListCtrl::OnSize(wxSizeEvent
& event
)
1250 // set the current font
1251 bool wxSymbolListCtrl::SetFont(const wxFont
& font
)
1253 wxVScrolledWindow::SetFont(font
);
1260 // set Unicode/ASCII mode
1261 void wxSymbolListCtrl::SetUnicodeMode(bool unicodeMode
)
1263 bool changed
= false;
1264 if (unicodeMode
&& !m_unicodeMode
)
1268 m_minSymbolValue
= 0;
1269 m_maxSymbolValue
= 65535;
1271 else if (!unicodeMode
&& m_unicodeMode
)
1274 m_minSymbolValue
= 0;
1275 m_maxSymbolValue
= 255;
1277 m_unicodeMode
= unicodeMode
;
1283 // ----------------------------------------------------------------------------
1284 // use the same default attributes as wxListBox
1285 // ----------------------------------------------------------------------------
1289 wxSymbolListCtrl::GetClassDefaultAttributes(wxWindowVariant variant
)
1291 return wxListBox::GetClassDefaultAttributes(variant
);
1295 * wxEVT_BUTTON event handler for wxID_HELP
1298 void wxSymbolPickerDialog::OnHelpClick( wxCommandEvent
& WXUNUSED(event
) )
1300 if ((GetHelpInfo().GetHelpId() != -1) && GetHelpInfo().GetUICustomization())
1305 * wxEVT_UPDATE_UI event handler for wxID_HELP
1308 void wxSymbolPickerDialog::OnHelpUpdate( wxUpdateUIEvent
& event
)
1310 event
.Enable((GetHelpInfo().GetHelpId() != -1) && GetHelpInfo().GetUICustomization());