int wxNotebook::DoSetSelection( size_t page, int flags ) { wxCHECK_MSG( m_widget != NULL, wxNOT_FOUND, wxT("invalid notebook") ); wxCHECK_MSG( page < m_pagesData.GetCount(), -1, wxT("invalid notebook index") ); int selOld = GetSelection(); if ( !(flags & SetSelection_SendEvent) ) m_skipNextPageChangeEvent = true; // cache the selection m_selection = page; gtk_notebook_set_page( GTK_NOTEBOOK(m_widget), page ); // gtk_notebook_set_current_page is supposed to emit the switch-page signal // which should be caught by our gtk_notebook_page_change_callback which // should have reset the flag to false, check it: wxASSERT_LEVEL_2_MSG( (flags & SetSelection_SendEvent) || !m_skipNextPageChangeEvent, "internal error in selection events generation" ); wxNotebookPage *client = GetPage(page); if ( client ) client->SetFocus(); return selOld; }
/* static and protected */ wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, wxEllipsizeMode mode, int maxFinalWidthPx, int replacementWidthPx) { wxASSERT_MSG(replacementWidthPx > 0, "Invalid parameters"); wxASSERT_LEVEL_2_MSG(!curLine.Contains('\n'), "Use Ellipsize() instead!"); wxASSERT_MSG( mode != wxELLIPSIZE_NONE, "shouldn't be called at all then" ); // NOTE: this function assumes that any mnemonic/tab character has already // been handled if it was necessary to handle them (see Ellipsize()) if (maxFinalWidthPx <= 0) return wxEmptyString; size_t len = curLine.length(); if (len <= 1 ) return curLine; EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx); if ( !calc.IsOk() ) return curLine; if ( calc.EllipsizationNotNeeded() ) return curLine; // let's compute the range of characters to remove depending on the ellipsization mode: switch (mode) { case wxELLIPSIZE_START: { calc.Init(0, 1); while ( !calc.IsShortEnough() ) calc.RemoveFromEnd(); // always show at least one character of the string: if ( calc.m_nCharsToRemove == len ) return wxString(wxELLIPSE_REPLACEMENT) + curLine[len-1]; break; } case wxELLIPSIZE_MIDDLE: { // NOTE: the following piece of code works also when len == 1 // start the removal process from the middle of the string // i.e. separe the string in three parts: // - the first one to preserve, valid range [0;initialCharToRemove-1] or the empty range if initialCharToRemove==0 // - the second one to remove, valid range [initialCharToRemove;endCharToRemove] // - the third one to preserve, valid range [endCharToRemove+1;len-1] or the empty range if endCharToRemove==len-1 // NOTE: empty range != range [0;0] since the range [0;0] contains 1 character (the zero-th one)! calc.Init(len/2, 0); bool removeFromStart = true; while ( !calc.IsShortEnough() ) { const bool canRemoveFromStart = calc.GetFirstRemoved() > 0; const bool canRemoveFromEnd = calc.GetLastRemoved() < len - 1; if ( !canRemoveFromStart && !canRemoveFromEnd ) { // we need to remove all the characters of the string! break; } // Remove from the beginning in even steps and from the end // in odd steps, unless we exhausted one side already: removeFromStart = !removeFromStart; if ( removeFromStart && !canRemoveFromStart ) removeFromStart = false; else if ( !removeFromStart && !canRemoveFromEnd ) removeFromStart = true; if ( removeFromStart ) calc.RemoveFromStart(); else calc.RemoveFromEnd(); } // Always show at least one character of the string. // Additionally, if there's only one character left, prefer // "a..." to "...a": if ( calc.m_nCharsToRemove == len || calc.m_nCharsToRemove == len - 1 ) { return curLine[0] + wxString(wxELLIPSE_REPLACEMENT); } } break; case wxELLIPSIZE_END: { calc.Init(len - 1, 1); while ( !calc.IsShortEnough() ) calc.RemoveFromStart(); // always show at least one character of the string: if ( calc.m_nCharsToRemove == len ) return curLine[0] + wxString(wxELLIPSE_REPLACEMENT); break; } case wxELLIPSIZE_NONE: default: wxFAIL_MSG("invalid ellipsize mode"); return curLine; } return calc.GetEllipsizedText(); }
/* static and protected */ wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, wxEllipsizeMode mode, int maxFinalWidthPx, int replacementWidthPx, int marginWidthPx) { wxASSERT_MSG(replacementWidthPx > 0 && marginWidthPx > 0, "Invalid parameters"); wxASSERT_LEVEL_2_MSG(!curLine.Contains('\n'), "Use Ellipsize() instead!"); wxASSERT_MSG( mode != wxELLIPSIZE_NONE, "shouldn't be called at all then" ); // NOTE: this function assumes that any mnemonic/tab character has already // been handled if it was necessary to handle them (see Ellipsize()) if (maxFinalWidthPx <= 0) return wxEmptyString; wxArrayInt charOffsetsPx; size_t len = curLine.length(); if (len == 0 || !dc.GetPartialTextExtents(curLine, charOffsetsPx)) return curLine; wxASSERT(charOffsetsPx.GetCount() == len); // NOTE: charOffsetsPx[n] is the width in pixels of the first n characters (with the last one INCLUDED) // thus charOffsetsPx[len-1] is the total width of the string size_t totalWidthPx = charOffsetsPx.Last(); if ( totalWidthPx <= (size_t)maxFinalWidthPx ) return curLine; // we don't need to do any ellipsization! int excessPx = wxMin(totalWidthPx - maxFinalWidthPx + replacementWidthPx + marginWidthPx, // security margin totalWidthPx); wxASSERT(excessPx>0); // excessPx should be in the [1;totalWidthPx] range // REMEMBER: indexes inside the string have a valid range of [0;len-1] if not otherwise constrained // lengths/counts of characters (e.g. nCharsToRemove) have a valid range of [0;len] if not otherwise constrained // NOTE: since this point we know we have for sure a non-empty string from which we need // to remove _at least_ one character (thus nCharsToRemove below is constrained to be >= 1) size_t initialCharToRemove, // index of first character to erase, valid range is [0;len-1] nCharsToRemove; // how many chars do we need to erase? valid range is [1;len-initialCharToRemove] // let's compute the range of characters to remove depending on the ellipsization mode: switch (mode) { case wxELLIPSIZE_START: initialCharToRemove = 0; for ( nCharsToRemove = 1; nCharsToRemove < len && charOffsetsPx[nCharsToRemove-1] < excessPx; nCharsToRemove++ ) ; break; case wxELLIPSIZE_MIDDLE: { // NOTE: the following piece of code works also when len == 1 // start the removal process from the middle of the string // i.e. separe the string in three parts: // - the first one to preserve, valid range [0;initialCharToRemove-1] or the empty range if initialCharToRemove==0 // - the second one to remove, valid range [initialCharToRemove;endCharToRemove] // - the third one to preserve, valid range [endCharToRemove+1;len-1] or the empty range if endCharToRemove==len-1 // NOTE: empty range != range [0;0] since the range [0;0] contains 1 character (the zero-th one)! initialCharToRemove = len/2; size_t endCharToRemove = len/2; // index of the last character to remove; valid range is [0;len-1] int removedPx = 0; for ( ; removedPx < excessPx; ) { // try to remove the last character of the first part of the string if (initialCharToRemove > 0) { // width of the (initialCharToRemove-1)-th character int widthPx; if (initialCharToRemove >= 2) widthPx = charOffsetsPx[initialCharToRemove-1] - charOffsetsPx[initialCharToRemove-2]; else widthPx = charOffsetsPx[initialCharToRemove-1]; // the (initialCharToRemove-1)-th character is the first char of the string wxASSERT(widthPx >= 0); // widthPx is zero for e.g. tab characters // mark the (initialCharToRemove-1)-th character as removable initialCharToRemove--; removedPx += widthPx; } // try to remove the first character of the last part of the string if (endCharToRemove < len - 1 && removedPx < excessPx) { // width of the (endCharToRemove+1)-th character int widthPx = charOffsetsPx[endCharToRemove+1] - charOffsetsPx[endCharToRemove]; wxASSERT(widthPx >= 0); // widthPx is zero for e.g. tab characters // mark the (endCharToRemove+1)-th character as removable endCharToRemove++; removedPx += widthPx; } if (initialCharToRemove == 0 && endCharToRemove == len-1) { // we need to remove all the characters of the string! break; } } nCharsToRemove = endCharToRemove - initialCharToRemove + 1; } break; case wxELLIPSIZE_END: { int maxWidthPx = totalWidthPx - excessPx; // go backward from the end of the string toward the start for ( initialCharToRemove = len-1; initialCharToRemove > 0 && charOffsetsPx[initialCharToRemove-1] > maxWidthPx; initialCharToRemove-- ) ; nCharsToRemove = len - initialCharToRemove; } break; case wxELLIPSIZE_NONE: default: wxFAIL_MSG("invalid ellipsize mode"); return curLine; } #ifdef __VMS #pragma message disable unscomzer // suppress warnings on comparison of unsigned numbers #endif wxASSERT(initialCharToRemove >= 0 && initialCharToRemove <= len-1); // see valid range for initialCharToRemove above #ifdef __VMS #pragma message enable unscomzer // suppress warnings on comparison of unsigned numbers #endif wxASSERT(nCharsToRemove >= 1 && nCharsToRemove <= len-initialCharToRemove); // see valid range for nCharsToRemove above // erase nCharsToRemove characters after initialCharToRemove (included); // e.g. if we have the string "foobar" (len = 6) // ^ // \--- initialCharToRemove = 2 // and nCharsToRemove = 2, then we get "foar" wxString ret(curLine); ret.erase(initialCharToRemove, nCharsToRemove); int removedPx; if (initialCharToRemove >= 1) removedPx = charOffsetsPx[initialCharToRemove+nCharsToRemove-1] - charOffsetsPx[initialCharToRemove-1]; else removedPx = charOffsetsPx[initialCharToRemove+nCharsToRemove-1]; wxASSERT(removedPx >= excessPx); // if there is space for the replacement dots, add them if ((int)totalWidthPx-removedPx+replacementWidthPx < maxFinalWidthPx) ret.insert(initialCharToRemove, wxELLIPSE_REPLACEMENT); // if everything was ok, we should have shortened this line // enough to make it fit in maxFinalWidthPx: wxASSERT_LEVEL_2(dc.GetTextExtent(ret).GetWidth() <= maxFinalWidthPx); return ret; }