]>
git.saurik.com Git - wxWidgets.git/blob - src/common/stattextcmn.cpp
184c9f1c983832e4230a41ae1d69b4bf7d72c936
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/stattextcmn.cpp
3 // Purpose: common (to all ports) wxStaticText functions
4 // Author: Vadim Zeitlin, Francesco Montorsi
5 // Created: 2007-01-07 (extracted from dlgcmn.cpp)
7 // Copyright: (c) 1999-2006 Vadim Zeitlin
8 // (c) 2007 Francesco Montorsi
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/private/stattext.h"
30 #include "wx/button.h"
31 #include "wx/dcclient.h"
33 #include "wx/settings.h"
34 #include "wx/stattext.h"
36 #include "wx/containr.h"
41 const wxChar
*wxMarkupEntities
[][wxMARKUP_ENTITY_MAX
] =
43 // the entities handled by SetLabel() when wxST_MARKUP is used and their referenced string
45 { wxT("&"), wxT("<"), wxT(">"), wxT("'"), wxT(""") },
46 { wxT("&"), wxT("<"), wxT(">"), wxT("'"), wxT("\"") }
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 void wxTextWrapper::Wrap(wxWindow
*win
, const wxString
& text
, int widthMax
)
56 const wxChar
*lastSpace
= NULL
;
59 const wxChar
*lineStart
= text
.c_str();
60 for ( const wxChar
*p
= lineStart
; ; p
++ )
62 if ( IsStartOfNewLine() )
71 if ( *p
== _T('\n') || *p
== _T('\0') )
85 if ( widthMax
>= 0 && lastSpace
)
88 win
->GetTextExtent(line
, &width
, NULL
);
90 if ( width
> widthMax
)
92 // remove the last word from this line
93 line
.erase(lastSpace
- lineStart
, p
+ 1 - lineStart
);
96 // go back to the last word of this line which we didn't
101 //else: no wrapping at all or impossible to wrap
107 // ----------------------------------------------------------------------------
108 // wxLabelWrapper: helper class for wxStaticTextBase::Wrap()
109 // ----------------------------------------------------------------------------
111 class wxLabelWrapper
: public wxTextWrapper
114 void WrapLabel(wxWindow
*text
, int widthMax
)
117 Wrap(text
, text
->GetLabel(), widthMax
);
118 text
->SetLabel(m_text
);
122 virtual void OnOutputLine(const wxString
& line
)
127 virtual void OnNewLine()
137 // ----------------------------------------------------------------------------
139 // ----------------------------------------------------------------------------
141 void wxStaticTextBase::Wrap(int width
)
143 wxLabelWrapper wrapper
;
144 wrapper
.WrapLabel(this, width
);
147 wxString
wxStaticTextBase::GetLabelText() const
149 wxString
ret(GetLabel());
151 if (HasFlag(wxST_MARKUP
))
152 ret
= RemoveMarkup(ret
);
153 return RemoveMnemonics(ret
);
157 wxString
wxStaticTextBase::RemoveMarkup(const wxString
& text
)
159 // strip out of "text" the markup for platforms which don't support it natively
160 bool inside_tag
= false;
163 const wxChar
*source
= text
;
164 for (size_t i
=0, max
=text
.length(); i
<max
; i
++)
171 wxLogDebug(wxT("Invalid markup !"));
172 return wxEmptyString
;
180 wxLogDebug(wxT("Invalid markup !"));
181 return wxEmptyString
;
190 wxLogDebug(wxT("Cannot use & as last character of the string '%s'"),
192 return wxEmptyString
;
195 // is this ampersand introducing a mnemonic or rather an entity?
196 bool isMnemonic
= true;
197 for (size_t j
=0; j
< wxMARKUP_ENTITY_MAX
; j
++)
199 const wxChar
*entity
= wxMarkupEntities
[wxMARKUP_ELEMENT_NAME
][j
];
200 size_t entityLen
= wxStrlen(entity
);
202 if (max
- i
>= entityLen
&&
203 wxStrncmp(entity
, &source
[i
], entityLen
) == 0)
205 // replace the &entity; string with the entity reference
206 label
<< wxMarkupEntities
[wxMARKUP_ELEMENT_VALUE
][j
];
208 // little exception: when the entity reference is "&"
209 // (i.e. when entity is "&"), substitute it with &&
210 // instead of a single ampersand:
211 if (*wxMarkupEntities
[wxMARKUP_ELEMENT_VALUE
][j
] == wxT('&'))
213 i
+= entityLen
- 1; // the -1 is because main for()
214 // loop already increments i
236 wxString
wxStaticTextBase::EscapeMarkup(const wxString
& text
)
240 for (const wxChar
*source
= text
; *source
!= wxT('\0'); source
++)
242 bool isEntity
= false;
244 // search in the list of the entities and eventually escape this character
245 for (size_t j
=0; j
< wxMARKUP_ENTITY_MAX
; j
++)
247 if (*source
== *wxMarkupEntities
[wxMARKUP_ELEMENT_VALUE
][j
])
249 ret
<< wxMarkupEntities
[wxMARKUP_ELEMENT_NAME
][j
];
256 ret
<< *source
; // this character does not need to be escaped
264 // ----------------------------------------------------------------------------
265 // wxStaticTextBase - generic implementation for wxST_ELLIPSIZE_* support
266 // ----------------------------------------------------------------------------
268 void wxStaticTextBase::UpdateLabel()
273 wxString newlabel
= GetEllipsizedLabelWithoutMarkup();
275 // we need to touch the "real" label (i.e. the text set inside the control,
276 // using port-specific functions) instead of the string returned by GetLabel().
278 // In fact, we must be careful not to touch the original label passed to
279 // SetLabel() otherwise GetLabel() will behave in a strange way to the user
280 // (e.g. returning a "Ver...ing" instead of "Very long string") !
281 if (newlabel
== DoGetLabel())
283 DoSetLabel(newlabel
);
286 wxString
wxStaticTextBase::GetEllipsizedLabelWithoutMarkup() const
288 // this function should be used only by ports which do not support
289 // ellipsis in static texts: we first remove markup (which cannot
290 // be handled safely by Ellipsize()) and then ellipsize the result.
292 wxString
ret(m_labelOrig
);
294 // the order of the following two blocks is important!
296 if (HasFlag(wxST_MARKUP
))
297 ret
= RemoveMarkup(ret
);
300 ret
= Ellipsize(ret
);
305 #define wxELLIPSE_REPLACEMENT wxT("...")
307 wxString
wxStaticTextBase::Ellipsize(const wxString
& label
) const
309 wxSize
sz(GetSize());
310 if (sz
.GetWidth() < 2 || sz
.GetHeight() < 2)
312 // the size of this window is not valid (yet)
316 wxClientDC
dc(wx_const_cast(wxStaticTextBase
*, this));
317 dc
.SetFont(GetFont());
319 wxArrayInt charOffsets
;
322 // these cannot be cached as they can change because of e.g. a font change
323 int replacementWidth
= dc
.GetTextExtent(wxELLIPSE_REPLACEMENT
).GetWidth();
324 int marginWidth
= dc
.GetCharWidth()*2;
326 // handle correctly labels with newlines
330 for ( const wxChar
*pc
= label
; ; pc
++ )
336 len
= curLine
.length();
338 dc
.GetPartialTextExtents(curLine
, charOffsets
))
340 wxASSERT(charOffsets
.GetCount() == len
);
342 size_t totalWidth
= charOffsets
.Last();
343 if ( totalWidth
> (size_t)sz
.GetWidth() )
345 // we need to ellipsize this row
346 int excessPixels
= totalWidth
- sz
.GetWidth() +
348 marginWidth
; // security margin (NEEDED!)
350 // remove characters in excess
351 size_t initialChar
, // index of first char to erase
352 nChars
; // how many chars do we need to erase?
353 if (HasFlag(wxST_ELLIPSIZE_START
))
357 nChars
< len
&& charOffsets
[nChars
] < excessPixels
;
361 else if (HasFlag(wxST_ELLIPSIZE_MIDDLE
))
363 // the start & end of the removed span of chars
365 size_t endChar
= len
/2;
368 for ( ; removed
< excessPixels
; )
372 // width of the initialChar-th character
373 int width
= charOffsets
[initialChar
] -
374 charOffsets
[initialChar
-1];
376 // remove the initialChar-th character
381 if (endChar
< len
- 1 &&
382 removed
< excessPixels
)
384 // width of the (endChar+1)-th character
385 int width
= charOffsets
[endChar
+1] -
386 charOffsets
[endChar
];
388 // remove the endChar-th character
393 if (initialChar
== 0 && endChar
== len
-1)
401 nChars
= endChar
- initialChar
+ 1;
405 wxASSERT(HasFlag(wxST_ELLIPSIZE_END
));
408 int maxWidth
= totalWidth
- excessPixels
;
411 charOffsets
[initialChar
] < maxWidth
;
415 if (initialChar
== 0)
421 initialChar
--; // go back one character
422 nChars
= len
- initialChar
;
428 // need to remove the entire row!
433 // erase nChars characters after initialChar (included):
434 curLine
.erase(initialChar
, nChars
+1);
436 // if there is space for the replacement dots, add them
437 if (sz
.GetWidth() > replacementWidth
)
438 curLine
.insert(initialChar
, wxELLIPSE_REPLACEMENT
);
441 // if everything was ok, we should have shortened this line
442 // enough to make it fit in sz.GetWidth():
443 wxASSERT(dc
.GetTextExtent(curLine
).GetWidth() < sz
.GetWidth());
447 // add this (ellipsized) row to the rest of the label
448 ret
<< curLine
<< *pc
;
451 if ( *pc
== _T('\0') )
456 // we need to remove mnemonics from the label for
457 // correct calculations
459 // pc+1 is safe: at worst we'll hit the \0
460 if (*(pc
+1) == _T('&'))
461 curLine
+= _T('&'); // && becomes &
462 //else: remove this ampersand
466 // we need also to expand tabs to properly calc their size
468 // Windows natively expands the TABs to 6 spaces. Do the same:
480 #endif // wxUSE_STATTEXT