1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextsymboldlg.cpp
4 // Author: Julian Smart
6 // Created: 10/5/2006 3:11:58 PM
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/richtext/richtextsymboldlg.h"
25 #include "wx/stattext.h"
26 #include "wx/combobox.h"
27 #include "wx/button.h"
28 #include "wx/settings.h"
30 #include "wx/listbox.h"
33 #include "wx/dcbuffer.h"
35 // Only for cached font name
36 #include "wx/richtext/richtextctrl.h"
38 /* Microsoft Unicode subset numbering
44 U_LATIN_1_SUPPLEMENT
= 1,
45 U_LATIN_EXTENDED_A
= 2,
46 U_LATIN_EXTENDED_B
= 3,
48 U_SPACING_MODIFIER_LETTERS
= 5,
49 U_COMBINING_DIACRITICAL_MARKS
= 6,
51 U_GREEK_SYMBOLS_AND_COPTIC
= 8,
54 U_HEBREW_EXTENDED
= 12,
57 U_ARABIC_EXTENDED
= 14,
69 U_GEORGIAN_EXTENDED
= 27,
70 U_BASIC_GEORGIAN
= 26,
72 U_LATIN_EXTENDED_ADDITIONAL
= 29,
73 U_GREEK_EXTENDED
= 30,
74 U_GENERAL_PUNCTUATION
= 31,
75 U_SUPERSCRIPTS_AND_SUBSCRIPTS
= 32,
76 U_CURRENCY_SYMBOLS
= 33,
77 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS
= 34,
78 U_LETTERLIKE_SYMBOLS
= 35,
81 U_MATHEMATICAL_OPERATORS
= 38,
82 U_MISCELLANEOUS_TECHNICAL
= 39,
83 U_CONTROL_PICTURES
= 40,
84 U_OPTICAL_CHARACTER_RECOGNITION
= 41,
85 U_ENCLOSED_ALPHANUMERICS
= 42,
87 U_BLOCK_ELEMENTS
= 44,
88 U_GEOMETRIC_SHAPES
= 45,
89 U_MISCELLANEOUS_SYMBOLS
= 46,
91 U_CJK_SYMBOLS_AND_PUNCTUATION
= 48,
95 U_HANGUL_COMPATIBILITY_JAMO
= 52,
96 U_CJK_MISCELLANEOUS
= 53,
98 U_CJK_COMPATIBILITY
= 55,
100 U_HANGUL_SUPPLEMENTARY_A
= 57,
101 U_HANGUL_SUPPLEMENTARY_B
= 58,
102 U_CJK_UNIFIED_IDEOGRAPHS
= 59,
103 U_PRIVATE_USE_AREA
= 60,
104 U_CJK_COMPATIBILITY_IDEOGRAPHS
= 61,
105 U_ALPHABETIC_PRESENTATION_FORMS
= 62,
106 U_ARABIC_PRESENTATION_FORMS_A
= 63,
107 U_COMBINING_HALF_MARKS
= 64,
108 U_CJK_COMPATIBILITY_FORMS
= 65,
109 U_SMALL_FORM_VARIANTS
= 66,
110 U_ARABIC_PRESENTATION_FORMS_B
= 67,
112 U_HALFWIDTH_AND_FULLWIDTH_FORMS
= 68,
114 } wxUnicodeSubsetCodes
;
116 /* Unicode subsets */
122 wxUnicodeSubsetCodes m_subset
;
124 } g_UnicodeSubsetTable
[] =
127 U_BASIC_LATIN
, wxT("Basic Latin") },
129 U_LATIN_1_SUPPLEMENT
, wxT("Latin-1 Supplement") },
131 U_LATIN_EXTENDED_A
, wxT("Latin Extended-A") },
133 U_LATIN_EXTENDED_B
, wxT("Latin Extended-B") },
135 U_IPA_EXTENSIONS
, wxT("IPA Extensions") },
137 U_SPACING_MODIFIER_LETTERS
, wxT("Spacing Modifier Letters") },
139 U_COMBINING_DIACRITICAL_MARKS
, wxT("Combining Diacritical Marks") },
141 U_BASIC_GREEK
, wxT("Basic Greek") },
143 U_GREEK_SYMBOLS_AND_COPTIC
, wxT("Greek Symbols and Coptic") },
145 U_CYRILLIC
, wxT("Cyrillic") },
147 U_ARMENIAN
, wxT("Armenian") },
149 U_HEBREW_EXTENDED
, wxT("Hebrew Extended") },
151 U_BASIC_HEBREW
, wxT("Basic Hebrew") },
153 U_BASIC_ARABIC
, wxT("Basic Arabic") },
155 U_ARABIC_EXTENDED
, wxT("Arabic Extended") },
157 U_DEVANAGARI
, wxT("Devanagari") },
159 U_BENGALI
, wxT("Bengali") },
161 U_GURMUKHI
, wxT("Gurmukhi") },
163 U_GUJARATI
, wxT("Gujarati") },
165 U_ORIYA
, wxT("Oriya") },
167 U_TAMIL
, wxT("Tamil") },
169 U_TELUGU
, wxT("Telugu") },
171 U_KANNADA
, wxT("Kannada") },
173 U_MALAYALAM
, wxT("Malayalam") },
175 U_THAI
, wxT("Thai") },
179 U_GEORGIAN_EXTENDED
, wxT("Georgian Extended") },
181 U_BASIC_GEORGIAN
, wxT("Basic Georgian") },
183 U_HANGUL_JAMO
, wxT("Hangul Jamo") },
185 U_LATIN_EXTENDED_ADDITIONAL
, wxT("Latin Extended Additional") },
187 U_GREEK_EXTENDED
, wxT("Greek Extended") },
189 U_GENERAL_PUNCTUATION
, wxT("General Punctuation") },
191 U_SUPERSCRIPTS_AND_SUBSCRIPTS
, wxT("Superscripts and Subscripts") },
193 U_CURRENCY_SYMBOLS
, wxT("Currency Symbols") },
195 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS
, wxT("Combining Diacritical Marks for Symbols") },
197 U_LETTERLIKE_SYMBOLS
, wxT("Letterlike Symbols") },
199 U_NUMBER_FORMS
, wxT("Number Forms") },
201 U_ARROWS
, wxT("Arrows") },
203 U_MATHEMATICAL_OPERATORS
, wxT("Mathematical Operators") },
205 U_MISCELLANEOUS_TECHNICAL
, wxT("Miscellaneous Technical") },
207 U_CONTROL_PICTURES
, wxT("Control Pictures") },
209 U_OPTICAL_CHARACTER_RECOGNITION
, wxT("Optical Character Recognition") },
211 U_ENCLOSED_ALPHANUMERICS
, wxT("Enclosed Alphanumerics") },
213 U_BOX_DRAWING
, wxT("Box Drawing") },
215 U_BLOCK_ELEMENTS
, wxT("Block Elements") },
217 U_GEOMETRIC_SHAPES
, wxT("Geometric Shapes") },
219 U_MISCELLANEOUS_SYMBOLS
, wxT("Miscellaneous Symbols") },
221 U_DINGBATS
, wxT("Dingbats") },
223 U_CJK_SYMBOLS_AND_PUNCTUATION
, wxT("CJK Symbols and Punctuation") },
225 U_HIRAGANA
, wxT("Hiragana") },
227 U_KATAKANA
, wxT("Katakana") },
229 U_BOPOMOFO
, wxT("Bopomofo") },
231 U_HANGUL_COMPATIBILITY_JAMO
, wxT("Hangul Compatibility Jamo") },
233 U_CJK_MISCELLANEOUS
, wxT("CJK Miscellaneous") },
235 U_ENCLOSED_CJK
, wxT("Enclosed CJK") },
237 U_CJK_COMPATIBILITY
, wxT("CJK Compatibility") },
239 U_CJK_UNIFIED_IDEOGRAPHS
, wxT("CJK Unified Ideographs Extension A") },
241 U_CJK_UNIFIED_IDEOGRAPHS
, wxT("CJK Unified Ideographs") },
243 U_HANGUL
, wxT("Hangul Syllables") },
245 U_PRIVATE_USE_AREA
, wxT("Private Use Area") },
247 U_CJK_COMPATIBILITY_IDEOGRAPHS
, wxT("CJK Compatibility Ideographs") },
249 U_ALPHABETIC_PRESENTATION_FORMS
, wxT("Alphabetic Presentation Forms") },
251 U_ARABIC_PRESENTATION_FORMS_A
, wxT("Arabic Presentation Forms-A") },
253 U_COMBINING_HALF_MARKS
, wxT("Combining Half Marks") },
255 U_CJK_COMPATIBILITY_FORMS
, wxT("CJK Compatibility Forms") },
257 U_SMALL_FORM_VARIANTS
, wxT("Small Form Variants") },
259 U_ARABIC_PRESENTATION_FORMS_B
, wxT("Arabic Presentation Forms-B") },
261 U_SPECIALS
, wxT("Specials") },
263 U_HALFWIDTH_AND_FULLWIDTH_FORMS
, wxT("Halfwidth and Fullwidth Forms") },
265 U_SPECIALS
, wxT("Specials") }
268 #endif // __UNICODE__
271 // Not yet used, but could be used to test under Win32 whether this subset is available
272 // for the given font. The Win32 function is allegedly not accurate, however.
273 bool wxSubsetValidForFont(int subsetIndex
, FONTSIGNATURE
*fontSig
)
275 return (fontSig
->fsUsb
[g_UnicodeSubsetTable
[subsetIndex
].m_subset
/32] & (1 << (g_UnicodeSubsetTable
[subsetIndex
].m_subset
% 32)));
279 bool wxSymbolPickerDialog::sm_showToolTips
= false;
282 * wxSymbolPickerDialog type definition
285 IMPLEMENT_DYNAMIC_CLASS( wxSymbolPickerDialog
, wxDialog
)
288 * wxSymbolPickerDialog event table definition
291 BEGIN_EVENT_TABLE( wxSymbolPickerDialog
, wxDialog
)
292 EVT_LISTBOX(ID_SYMBOLPICKERDIALOG_LISTCTRL
, wxSymbolPickerDialog::OnSymbolSelected
)
294 ////@begin wxSymbolPickerDialog event table entries
295 EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_FONT
, wxSymbolPickerDialog::OnFontCtrlSelected
)
297 #if defined(__UNICODE__)
298 EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_SUBSET
, wxSymbolPickerDialog::OnSubsetSelected
)
301 #if defined(__UNICODE__)
302 EVT_COMBOBOX( ID_SYMBOLPICKERDIALOG_FROM
, wxSymbolPickerDialog::OnFromUnicodeSelected
)
305 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXOS2__) || defined(__WXMGL__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || defined(__WXX11__) || defined(__WXPALMOS__)
306 EVT_UPDATE_UI( wxID_OK
, wxSymbolPickerDialog::OnOkUpdate
)
309 #if defined(__WXMAC__)
310 EVT_UPDATE_UI( wxID_OK
, wxSymbolPickerDialog::OnOkUpdate
)
313 ////@end wxSymbolPickerDialog event table entries
318 * wxSymbolPickerDialog constructors
321 wxSymbolPickerDialog::wxSymbolPickerDialog( )
326 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
)
329 Create(symbol
, fontName
, normalTextFont
, parent
, id
, caption
, pos
, size
, style
);
333 * wxSymbolPickerDialog creator
336 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
)
338 m_fontName
= fontName
;
339 m_normalTextFontName
= normalTextFont
;
342 ////@begin wxSymbolPickerDialog creation
343 SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS
|wxDIALOG_EX_CONTEXTHELP
);
344 wxDialog::Create( parent
, id
, caption
, pos
, size
, style
);
349 GetSizer()->SetSizeHints(this);
352 ////@end wxSymbolPickerDialog creation
357 * Member initialisation for wxSymbolPickerDialog
360 void wxSymbolPickerDialog::Init()
362 ////@begin wxSymbolPickerDialog member initialisation
363 m_fromUnicode
= true;
365 #if defined(__UNICODE__)
368 m_symbolsCtrl
= NULL
;
369 m_symbolStaticCtrl
= NULL
;
370 m_characterCodeCtrl
= NULL
;
371 #if defined(__UNICODE__)
372 m_fromUnicodeCtrl
= NULL
;
374 ////@end wxSymbolPickerDialog member initialisation
375 m_dontUpdate
= false;
379 * Control creation for wxSymbolPickerDialog
382 void wxSymbolPickerDialog::CreateControls()
384 ////@begin wxSymbolPickerDialog content construction
385 wxSymbolPickerDialog
* itemDialog1
= this;
387 wxBoxSizer
* itemBoxSizer2
= new wxBoxSizer(wxVERTICAL
);
388 itemDialog1
->SetSizer(itemBoxSizer2
);
390 wxBoxSizer
* itemBoxSizer3
= new wxBoxSizer(wxVERTICAL
);
391 itemBoxSizer2
->Add(itemBoxSizer3
, 1, wxGROW
|wxALL
, 5);
393 wxBoxSizer
* itemBoxSizer4
= new wxBoxSizer(wxHORIZONTAL
);
394 itemBoxSizer3
->Add(itemBoxSizer4
, 0, wxGROW
, 5);
396 wxBoxSizer
* itemBoxSizer5
= new wxBoxSizer(wxHORIZONTAL
);
397 itemBoxSizer4
->Add(itemBoxSizer5
, 1, wxGROW
, 5);
399 wxStaticText
* itemStaticText6
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&Font:"), wxDefaultPosition
, wxDefaultSize
, 0 );
400 itemBoxSizer5
->Add(itemStaticText6
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
|wxADJUST_MINSIZE
, 5);
402 wxString
* m_fontCtrlStrings
= NULL
;
403 m_fontCtrl
= new wxComboBox( itemDialog1
, ID_SYMBOLPICKERDIALOG_FONT
, _T(""), wxDefaultPosition
, wxSize(240, -1), 0, m_fontCtrlStrings
, wxCB_READONLY
);
404 m_fontCtrl
->SetHelpText(_("The font from which to take the symbol."));
406 m_fontCtrl
->SetToolTip(_("The font from which to take the symbol."));
407 itemBoxSizer5
->Add(m_fontCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
409 itemBoxSizer5
->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
411 #if defined(__UNICODE__)
412 wxStaticText
* itemStaticText9
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&Subset:"), wxDefaultPosition
, wxDefaultSize
, 0 );
413 itemBoxSizer5
->Add(itemStaticText9
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
|wxADJUST_MINSIZE
, 5);
417 #if defined(__UNICODE__)
418 wxString
* m_subsetCtrlStrings
= NULL
;
419 m_subsetCtrl
= new wxComboBox( itemDialog1
, ID_SYMBOLPICKERDIALOG_SUBSET
, _T(""), wxDefaultPosition
, wxDefaultSize
, 0, m_subsetCtrlStrings
, wxCB_READONLY
);
420 m_subsetCtrl
->SetHelpText(_("Shows a Unicode subset."));
422 m_subsetCtrl
->SetToolTip(_("Shows a Unicode subset."));
423 itemBoxSizer5
->Add(m_subsetCtrl
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
427 m_symbolsCtrl
= new wxSymbolListCtrl( itemDialog1
, ID_SYMBOLPICKERDIALOG_LISTCTRL
, wxDefaultPosition
, wxSize(500, 240), wxSIMPLE_BORDER
);
428 itemBoxSizer3
->Add(m_symbolsCtrl
, 1, wxGROW
|wxALL
, 5);
430 wxBoxSizer
* itemBoxSizer12
= new wxBoxSizer(wxHORIZONTAL
);
431 itemBoxSizer3
->Add(itemBoxSizer12
, 0, wxGROW
, 5);
433 m_symbolStaticCtrl
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("xxxx"), wxDefaultPosition
, wxSize(40, -1), wxALIGN_CENTRE
);
434 itemBoxSizer12
->Add(m_symbolStaticCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
|wxADJUST_MINSIZE
, 5);
436 itemBoxSizer12
->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
438 wxStaticText
* itemStaticText15
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&Character code:"), wxDefaultPosition
, wxDefaultSize
, 0 );
439 itemBoxSizer12
->Add(itemStaticText15
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
|wxADJUST_MINSIZE
, 5);
441 m_characterCodeCtrl
= new wxTextCtrl( itemDialog1
, ID_SYMBOLPICKERDIALOG_CHARACTERCODE
, _T(""), wxDefaultPosition
, wxSize(140, -1), wxTE_READONLY
|wxTE_CENTRE
);
442 m_characterCodeCtrl
->SetHelpText(_("The character code."));
444 m_characterCodeCtrl
->SetToolTip(_("The character code."));
445 itemBoxSizer12
->Add(m_characterCodeCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
447 itemBoxSizer12
->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
449 #if defined(__UNICODE__)
450 wxStaticText
* itemStaticText18
= new wxStaticText( itemDialog1
, wxID_STATIC
, _("&From:"), wxDefaultPosition
, wxDefaultSize
, 0 );
451 itemBoxSizer12
->Add(itemStaticText18
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
|wxADJUST_MINSIZE
, 5);
455 #if defined(__UNICODE__)
456 wxString m_fromUnicodeCtrlStrings
[] = {
460 m_fromUnicodeCtrl
= new wxComboBox( itemDialog1
, ID_SYMBOLPICKERDIALOG_FROM
, _("ASCII"), wxDefaultPosition
, wxDefaultSize
, 2, m_fromUnicodeCtrlStrings
, wxCB_READONLY
);
461 m_fromUnicodeCtrl
->SetStringSelection(_("ASCII"));
462 m_fromUnicodeCtrl
->SetHelpText(_("The range to show."));
464 m_fromUnicodeCtrl
->SetToolTip(_("The range to show."));
465 itemBoxSizer12
->Add(m_fromUnicodeCtrl
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
469 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXOS2__) || defined(__WXMGL__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || defined(__WXX11__) || defined(__WXPALMOS__)
470 wxBoxSizer
* itemBoxSizer20
= new wxBoxSizer(wxHORIZONTAL
);
471 itemBoxSizer3
->Add(itemBoxSizer20
, 0, wxGROW
, 5);
473 itemBoxSizer20
->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
475 wxButton
* itemButton22
= new wxButton( itemDialog1
, wxID_OK
, _("Insert"), wxDefaultPosition
, wxDefaultSize
, 0 );
476 itemButton22
->SetDefault();
477 itemButton22
->SetHelpText(_("Inserts the chosen symbol."));
479 itemButton22
->SetToolTip(_("Inserts the chosen symbol."));
480 itemBoxSizer20
->Add(itemButton22
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
482 wxButton
* itemButton23
= new wxButton( itemDialog1
, wxID_CANCEL
, _("Close"), wxDefaultPosition
, wxDefaultSize
, 0 );
483 itemButton23
->SetHelpText(_("Closes the dialog without inserting a symbol."));
485 itemButton23
->SetToolTip(_("Closes the dialog without inserting a symbol."));
486 itemBoxSizer20
->Add(itemButton23
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
490 #if defined(__WXMAC__)
491 wxBoxSizer
* itemBoxSizer24
= new wxBoxSizer(wxHORIZONTAL
);
492 itemBoxSizer3
->Add(itemBoxSizer24
, 0, wxGROW
, 5);
494 itemBoxSizer24
->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
496 wxButton
* itemButton26
= new wxButton( itemDialog1
, wxID_CANCEL
, _("Close"), wxDefaultPosition
, wxDefaultSize
, 0 );
497 itemButton26
->SetHelpText(_("Closes the dialog without inserting a symbol."));
499 itemButton26
->SetToolTip(_("Closes the dialog without inserting a symbol."));
500 itemBoxSizer24
->Add(itemButton26
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
502 wxButton
* itemButton27
= new wxButton( itemDialog1
, wxID_OK
, _("Insert"), wxDefaultPosition
, wxDefaultSize
, 0 );
503 itemButton27
->SetDefault();
504 itemButton27
->SetHelpText(_("Inserts the chosen symbol."));
506 itemButton27
->SetToolTip(_("Inserts the chosen symbol."));
507 itemBoxSizer24
->Add(itemButton27
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
511 ////@end wxSymbolPickerDialog content construction
516 bool wxSymbolPickerDialog::TransferDataToWindow()
520 if (m_fontCtrl
->GetCount() == 0)
522 wxArrayString faceNames
= wxRichTextCtrl::GetAvailableFontNames();
525 faceNames
.Insert(_("(Normal text)"), 0);
526 m_fontCtrl
->Append(faceNames
);
529 if (m_fontName
.empty())
530 m_fontCtrl
->SetSelection(0);
533 if (m_fontCtrl
->FindString(m_fontName
) != wxNOT_FOUND
)
534 m_fontCtrl
->SetStringSelection(m_fontName
);
536 m_fontCtrl
->SetSelection(0);
539 if (!m_symbol
.empty())
541 int sel
= (int) m_symbol
[0];
542 m_symbolsCtrl
->SetSelection(sel
);
545 #if defined(__UNICODE__)
546 if (m_subsetCtrl
->GetCount() == 0)
548 // Insert items into subset combo
550 for (i
= 0; i
< (int) (sizeof(g_UnicodeSubsetTable
)/sizeof(g_UnicodeSubsetTable
[0])); i
++)
552 m_subsetCtrl
->Append(g_UnicodeSubsetTable
[i
].m_name
);
554 m_subsetCtrl
->SetSelection(0);
558 UpdateSymbolDisplay();
560 m_dontUpdate
= false;
565 void wxSymbolPickerDialog::UpdateSymbolDisplay(bool updateSymbolList
, bool showAtSubset
)
568 wxString fontNameToUse
;
569 if (m_fontName
.empty())
570 fontNameToUse
= m_normalTextFontName
;
572 fontNameToUse
= m_fontName
;
574 if (!fontNameToUse
.empty())
576 font
= wxFont(14, wxDEFAULT
, wxNORMAL
, wxNORMAL
, false, fontNameToUse
);
579 font
= *wxNORMAL_FONT
;
581 if (updateSymbolList
)
583 m_symbolsCtrl
->SetFont(font
);
586 if (!m_symbol
.empty())
588 m_symbolStaticCtrl
->SetFont(font
);
589 m_symbolStaticCtrl
->SetLabel(m_symbol
);
591 int symbol
= (int) m_symbol
[0];
592 m_characterCodeCtrl
->SetValue(wxString::Format(wxT("%X hex (%d dec)"), symbol
, symbol
));
596 m_symbolStaticCtrl
->SetLabel(wxEmptyString
);
597 m_characterCodeCtrl
->SetValue(wxEmptyString
);
600 #if defined(__UNICODE__)
604 wxUnusedVar(showAtSubset
);
608 /// Show at the current subset selection
609 void wxSymbolPickerDialog::ShowAtSubset()
611 #if defined(__UNICODE__)
614 int sel
= m_subsetCtrl
->GetSelection();
615 int low
= g_UnicodeSubsetTable
[sel
].m_low
;
616 m_symbolsCtrl
->EnsureVisible(low
);
621 // Handle font selection
622 void wxSymbolPickerDialog::OnFontCtrlSelected( wxCommandEvent
& WXUNUSED(event
) )
624 if (m_fontCtrl
->GetSelection() == 0)
625 m_fontName
= wxEmptyString
;
627 m_fontName
= m_fontCtrl
->GetStringSelection();
629 UpdateSymbolDisplay();
632 /// Respond to symbol selection
633 void wxSymbolPickerDialog::OnSymbolSelected( wxCommandEvent
& event
)
638 int sel
= event
.GetSelection();
639 if (sel
== wxNOT_FOUND
)
640 m_symbol
= wxEmptyString
;
643 m_symbol
= wxEmptyString
;
644 m_symbol
<< (wxChar
) sel
;
647 #if defined(__UNICODE__)
648 if (sel
!= -1 && m_fromUnicode
)
650 // Need to make the subset selection reflect the current symbol
652 for (i
= 0; i
< (int) (sizeof(g_UnicodeSubsetTable
)/sizeof(g_UnicodeSubsetTable
[0])); i
++)
654 if (sel
>= g_UnicodeSubsetTable
[i
].m_low
&& sel
<= g_UnicodeSubsetTable
[i
].m_high
)
657 m_subsetCtrl
->SetSelection(i
);
658 m_dontUpdate
= false;
665 UpdateSymbolDisplay(false, false);
668 #if defined(__UNICODE__)
669 // Handle Unicode/ASCII selection
670 void wxSymbolPickerDialog::OnFromUnicodeSelected( wxCommandEvent
& WXUNUSED(event
) )
675 m_fromUnicode
= (m_fromUnicodeCtrl
->GetSelection() == 1);
676 m_symbolsCtrl
->SetUnicodeMode(m_fromUnicode
);
677 UpdateSymbolDisplay(false);
680 // Handle subset selection
681 void wxSymbolPickerDialog::OnSubsetSelected( wxCommandEvent
& WXUNUSED(event
) )
691 * wxEVT_UPDATE_UI event handler for wxID_OK
694 void wxSymbolPickerDialog::OnOkUpdate( wxUpdateUIEvent
& event
)
696 event
.Enable(HasSelection());
700 void wxSymbolPickerDialog::SetUnicodeMode(bool unicodeMode
)
702 #if defined(__UNICODE__)
704 m_fromUnicode
= unicodeMode
;
705 if (m_fromUnicodeCtrl
)
706 m_fromUnicodeCtrl
->SetSelection(m_fromUnicode
? 1 : 0);
707 UpdateSymbolDisplay();
708 m_dontUpdate
= false;
710 wxUnusedVar(unicodeMode
);
714 /// Get the selected symbol character
715 int wxSymbolPickerDialog::GetSymbolChar() const
717 if (m_symbol
.empty())
720 return (int) m_symbol
[0];
725 * Get bitmap resources
728 wxBitmap
wxSymbolPickerDialog::GetBitmapResource( const wxString
& name
)
731 ////@begin wxSymbolPickerDialog bitmap retrieval
734 ////@end wxSymbolPickerDialog bitmap retrieval
741 wxIcon
wxSymbolPickerDialog::GetIconResource( const wxString
& name
)
744 ////@begin wxSymbolPickerDialog icon retrieval
747 ////@end wxSymbolPickerDialog icon retrieval
751 * The scrolling symbol list.
754 // ----------------------------------------------------------------------------
756 // ----------------------------------------------------------------------------
758 BEGIN_EVENT_TABLE(wxSymbolListCtrl
, wxVScrolledWindow
)
759 EVT_PAINT(wxSymbolListCtrl::OnPaint
)
760 EVT_SIZE(wxSymbolListCtrl::OnSize
)
762 EVT_KEY_DOWN(wxSymbolListCtrl::OnKeyDown
)
763 EVT_LEFT_DOWN(wxSymbolListCtrl::OnLeftDown
)
764 EVT_LEFT_DCLICK(wxSymbolListCtrl::OnLeftDClick
)
767 // ============================================================================
769 // ============================================================================
771 IMPLEMENT_ABSTRACT_CLASS(wxSymbolListCtrl
, wxVScrolledWindow
)
773 // ----------------------------------------------------------------------------
774 // wxSymbolListCtrl creation
775 // ----------------------------------------------------------------------------
777 void wxSymbolListCtrl::Init()
779 m_current
= wxNOT_FOUND
;
780 m_doubleBuffer
= NULL
;
781 m_cellSize
= wxSize(40, 40);
782 m_minSymbolValue
= 0;
783 m_maxSymbolValue
= 255;
784 m_symbolsPerLine
= 0;
785 m_unicodeMode
= false;
788 bool wxSymbolListCtrl::Create(wxWindow
*parent
,
793 const wxString
& name
)
795 style
|= wxWANTS_CHARS
| wxFULL_REPAINT_ON_RESIZE
;
796 if ( !wxVScrolledWindow::Create(parent
, id
, pos
, size
, style
, name
) )
799 // make sure the native widget has the right colour since we do
800 // transparent drawing by default
801 SetBackgroundColour(GetBackgroundColour());
802 m_colBgSel
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
804 // flicker-free drawing requires this
805 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
807 SetFont(*wxNORMAL_FONT
);
814 wxSymbolListCtrl::~wxSymbolListCtrl()
816 delete m_doubleBuffer
;
819 // ----------------------------------------------------------------------------
820 // selection handling
821 // ----------------------------------------------------------------------------
823 bool wxSymbolListCtrl::IsSelected(int item
) const
825 return item
== m_current
;
828 bool wxSymbolListCtrl::DoSetCurrent(int current
)
830 wxASSERT_MSG( current
== wxNOT_FOUND
||
831 (current
>= m_minSymbolValue
&& current
<= m_maxSymbolValue
),
832 _T("wxSymbolListCtrl::DoSetCurrent(): invalid symbol value") );
834 if ( current
== m_current
)
840 if ( m_current
!= wxNOT_FOUND
)
841 RefreshLine(SymbolValueToLineNumber(m_current
));
845 if ( m_current
!= wxNOT_FOUND
)
847 int lineNo
= SymbolValueToLineNumber(m_current
);
849 // if the line is not visible at all, we scroll it into view but we
850 // don't need to refresh it -- it will be redrawn anyhow
851 if ( !IsVisible(lineNo
) )
853 ScrollToLine(lineNo
);
855 else // line is at least partly visible
857 // it is, indeed, only partly visible, so scroll it into view to
858 // make it entirely visible
859 while ( unsigned(lineNo
) == GetLastVisibleLine() &&
860 ScrollToLine(GetVisibleBegin()+1) )
863 // but in any case refresh it as even if it was only partly visible
864 // before we need to redraw it entirely as its background changed
872 void wxSymbolListCtrl::SendSelectedEvent()
874 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_SELECTED
, GetId());
875 event
.SetEventObject(this);
876 event
.SetInt(m_current
);
878 (void)GetEventHandler()->ProcessEvent(event
);
881 void wxSymbolListCtrl::SetSelection(int selection
)
883 wxCHECK_RET( selection
== wxNOT_FOUND
||
884 (selection
>= m_minSymbolValue
&& selection
< m_maxSymbolValue
),
885 _T("wxSymbolListCtrl::SetSelection(): invalid symbol value") );
887 DoSetCurrent(selection
);
890 // ----------------------------------------------------------------------------
891 // wxSymbolListCtrl appearance parameters
892 // ----------------------------------------------------------------------------
894 void wxSymbolListCtrl::SetMargins(const wxPoint
& pt
)
896 if ( pt
!= m_ptMargins
)
904 void wxSymbolListCtrl::SetSelectionBackground(const wxColour
& col
)
909 // ----------------------------------------------------------------------------
910 // wxSymbolListCtrl painting
911 // ----------------------------------------------------------------------------
913 wxCoord
wxSymbolListCtrl::OnGetLineHeight(size_t WXUNUSED(line
)) const
915 return m_cellSize
.y
+ 2*m_ptMargins
.y
+ 1 /* for divider */ ;
918 // draws a line of symbols
919 void wxSymbolListCtrl::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
921 wxColour oldTextColour
= dc
.GetTextForeground();
922 int startSymbol
= n
*m_symbolsPerLine
;
925 for (i
= 0; i
< m_symbolsPerLine
; i
++)
927 bool resetColour
= false;
928 int symbol
= startSymbol
+i
;
929 if (symbol
== m_current
)
931 dc
.SetBrush(wxBrush(m_colBgSel
));
933 dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
));
936 wxPen oldPen
= dc
.GetPen();
937 dc
.SetPen(*wxTRANSPARENT_PEN
);
939 dc
.DrawRectangle(rect
.x
+ i
*m_cellSize
.x
, rect
.y
, m_cellSize
.x
, rect
.y
+rect
.height
);
943 // Don't draw first line
945 dc
.DrawLine(rect
.x
+ i
*m_cellSize
.x
, rect
.y
, i
*m_cellSize
.x
, rect
.y
+rect
.height
);
947 if (symbol
>= m_minSymbolValue
&& symbol
<= m_maxSymbolValue
)
950 text
<< (wxChar
) symbol
;
953 dc
.GetTextExtent(text
, & w
, & h
);
955 int x
= rect
.x
+ i
*m_cellSize
.x
+ (m_cellSize
.x
- w
)/2;
956 int y
= rect
.y
+ (m_cellSize
.y
- h
)/2;
957 dc
.DrawText(text
, x
, y
);
961 dc
.SetTextForeground(oldTextColour
);
964 // Draw horizontal separator line
965 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1, rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
968 void wxSymbolListCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
970 // If size is larger, recalculate double buffer bitmap
971 wxSize clientSize
= GetClientSize();
973 if ( !m_doubleBuffer
||
974 clientSize
.x
> m_doubleBuffer
->GetWidth() ||
975 clientSize
.y
> m_doubleBuffer
->GetHeight() )
977 delete m_doubleBuffer
;
978 m_doubleBuffer
= new wxBitmap(clientSize
.x
+25,clientSize
.y
+25);
981 wxBufferedPaintDC
dc(this,*m_doubleBuffer
);
983 // the update rectangle
984 wxRect rectUpdate
= GetUpdateClientRect();
986 // fill it with background colour
987 dc
.SetBackground(GetBackgroundColour());
990 // set the font to be displayed
991 dc
.SetFont(GetFont());
993 // the bounding rectangle of the current line
995 rectLine
.width
= clientSize
.x
;
997 dc
.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)));
998 dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
));
999 dc
.SetBackgroundMode(wxTRANSPARENT
);
1001 // iterate over all visible lines
1002 const size_t lineMax
= GetVisibleEnd();
1003 for ( size_t line
= GetFirstVisibleLine(); line
< lineMax
; line
++ )
1005 const wxCoord hLine
= OnGetLineHeight(line
);
1007 rectLine
.height
= hLine
;
1009 // and draw the ones which intersect the update rect
1010 if ( rectLine
.Intersects(rectUpdate
) )
1012 // don't allow drawing outside of the lines rectangle
1013 wxDCClipper
clip(dc
, rectLine
);
1015 wxRect rect
= rectLine
;
1016 rect
.Deflate(m_ptMargins
.x
, m_ptMargins
.y
);
1017 OnDrawItem(dc
, rect
, line
);
1019 else // no intersection
1021 if ( rectLine
.GetTop() > rectUpdate
.GetBottom() )
1023 // we are already below the update rect, no need to continue
1027 //else: the next line may intersect the update rect
1030 rectLine
.y
+= hLine
;
1034 // ============================================================================
1035 // wxSymbolListCtrl keyboard/mouse handling
1036 // ============================================================================
1038 void wxSymbolListCtrl::DoHandleItemClick(int item
, int WXUNUSED(flags
))
1040 if (m_current
!= item
)
1044 SendSelectedEvent();
1048 // ----------------------------------------------------------------------------
1049 // keyboard handling
1050 // ----------------------------------------------------------------------------
1052 void wxSymbolListCtrl::OnKeyDown(wxKeyEvent
& event
)
1054 // No keyboard interface for now
1057 // flags for DoHandleItemClick()
1058 int flags
= ItemClick_Kbd
;
1060 int currentLineNow
= SymbolValueToLineNumber(m_current
);
1063 switch ( event
.GetKeyCode() )
1070 currentLine
= GetLineCount() - 1;
1074 if ( currentLineNow
== (int)GetLineCount() - 1 )
1077 currentLine
= currentLineNow
+ 1;
1081 if ( m_current
== wxNOT_FOUND
)
1082 currentLine
= GetLineCount() - 1;
1083 else if ( currentLineNow
!= 0 )
1084 currentLine
= currentLineNow
- 1;
1085 else // currentLineNow == 0
1091 currentLine
= GetFirstVisibleLine();
1095 if ( currentLineNow
== (int)GetFirstVisibleLine() )
1100 currentLine
= GetFirstVisibleLine();
1104 // hack: pressing space should work like a mouse click rather than
1105 // like a keyboard arrow press, so trick DoHandleItemClick() in
1106 // thinking we were clicked
1107 flags
&= ~ItemClick_Kbd
;
1108 currentLine
= currentLineNow
;
1113 // Since we are using wxWANTS_CHARS we need to send navigation
1114 // events for the tabs on MSW
1116 wxNavigationKeyEvent ne
;
1117 ne
.SetDirection(!event
.ShiftDown());
1118 ne
.SetCurrentFocus(this);
1119 ne
.SetEventObject(this);
1120 GetParent()->GetEventHandler()->ProcessEvent(ne
);
1122 // fall through to default
1126 currentLine
= 0; // just to silent the stupid compiler warnings
1127 wxUnusedVar(currentNow
);
1132 if ( event
.ShiftDown() )
1133 flags
|= ItemClick_Shift
;
1134 if ( event
.ControlDown() )
1135 flags
|= ItemClick_Ctrl
;
1137 DoHandleItemClick(current
, flags
);
1142 // ----------------------------------------------------------------------------
1143 // wxSymbolListCtrl mouse handling
1144 // ----------------------------------------------------------------------------
1146 void wxSymbolListCtrl::OnLeftDown(wxMouseEvent
& event
)
1150 int item
= HitTest(event
.GetPosition());
1152 if ( item
!= wxNOT_FOUND
)
1155 if ( event
.ShiftDown() )
1156 flags
|= ItemClick_Shift
;
1158 // under Mac Apple-click is used in the same way as Ctrl-click
1161 if ( event
.MetaDown() )
1163 if ( event
.ControlDown() )
1165 flags
|= ItemClick_Ctrl
;
1167 DoHandleItemClick(item
, flags
);
1171 void wxSymbolListCtrl::OnLeftDClick(wxMouseEvent
& eventMouse
)
1173 int item
= HitTest(eventMouse
.GetPosition());
1174 if ( item
!= wxNOT_FOUND
)
1177 // if item double-clicked was not yet selected, then treat
1178 // this event as a left-click instead
1179 if ( item
== m_current
)
1181 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
, GetId());
1182 event
.SetEventObject(this);
1185 (void)GetEventHandler()->ProcessEvent(event
);
1189 OnLeftDown(eventMouse
);
1195 // calculate line number from symbol value
1196 int wxSymbolListCtrl::SymbolValueToLineNumber(int item
)
1198 return (int) (item
/m_symbolsPerLine
);
1201 // initialise control from current min/max values
1202 void wxSymbolListCtrl::SetupCtrl(bool scrollToSelection
)
1204 wxSize sz
= GetClientSize();
1206 m_symbolsPerLine
= sz
.x
/(m_cellSize
.x
+m_ptMargins
.x
);
1207 int noLines
= (1 + SymbolValueToLineNumber(m_maxSymbolValue
));
1209 SetLineCount(noLines
);
1212 if (scrollToSelection
&& m_current
!= wxNOT_FOUND
&& m_current
>= m_minSymbolValue
&& m_current
<= m_maxSymbolValue
)
1214 ScrollToLine(SymbolValueToLineNumber(m_current
));
1218 // make this item visible
1219 void wxSymbolListCtrl::EnsureVisible(int item
)
1221 if (item
!= wxNOT_FOUND
&& item
>= m_minSymbolValue
&& item
<= m_maxSymbolValue
)
1223 ScrollToLine(SymbolValueToLineNumber(item
));
1229 int wxSymbolListCtrl::HitTest(const wxPoint
& pt
)
1231 wxCoord lineHeight
= OnGetLineHeight(0);
1233 int atLine
= GetVisibleBegin() + (pt
.y
/lineHeight
);
1234 int symbol
= (atLine
*m_symbolsPerLine
) + (pt
.x
/(m_cellSize
.x
+1));
1236 if (symbol
>= m_minSymbolValue
&& symbol
<= m_maxSymbolValue
)
1242 // Respond to size change
1243 void wxSymbolListCtrl::OnSize(wxSizeEvent
& event
)
1249 // set the current font
1250 bool wxSymbolListCtrl::SetFont(const wxFont
& font
)
1252 wxVScrolledWindow::SetFont(font
);
1259 // set Unicode/ASCII mode
1260 void wxSymbolListCtrl::SetUnicodeMode(bool unicodeMode
)
1262 bool changed
= false;
1263 if (unicodeMode
&& !m_unicodeMode
)
1267 m_minSymbolValue
= 0;
1268 m_maxSymbolValue
= 65535;
1270 else if (!unicodeMode
&& m_unicodeMode
)
1273 m_minSymbolValue
= 0;
1274 m_maxSymbolValue
= 255;
1276 m_unicodeMode
= unicodeMode
;
1282 // ----------------------------------------------------------------------------
1283 // use the same default attributes as wxListBox
1284 // ----------------------------------------------------------------------------
1288 wxSymbolListCtrl::GetClassDefaultAttributes(wxWindowVariant variant
)
1290 return wxListBox::GetClassDefaultAttributes(variant
);
1293 #endif // wxUSE_RICHTEXT