void WrappingTextView::ResetTextRect() { BRect bounds = Bounds(); BRect textRect = bounds; textRect.left = 4.0; textRect.top = m_vertical_offset + 4.0f; if (m_fixed_width) textRect.right = 8.0f + StringWidth( "0") * float(m_fixed_width); else textRect.right -= 4.0f; textRect.bottom -= 4.0f; SetTextRect(textRect); // we have to readjust the scrollbar-proportion, since // the BTextView doesn't do it correctly when we have // fooled in a vertical_offset: float small, big; BScrollBar* bar = ScrollBar( B_VERTICAL); if (!bar) return; bar->GetSteps( &small, &big); float height = TextHeight( 0, TextLength()); if (height+m_vertical_offset) bar->SetProportion( MIN( 1.0f, big/(height+m_vertical_offset))); else bar->SetProportion( 1.0f); if (BeamOnDano) { // circumvent a special feature/bug in Zeta with respect to // the scrollbar not always calling ValueChanged() on a click. // Seemingly, changing the value twice hides the bug: bar->SetValue(1); bar->SetValue(0); } bar = ScrollBar( B_HORIZONTAL); if (!bar) return; float width = bounds.Width(); float maxWidth = MAX( width, textRect.right); int numChildren = IsEditable() ? 0 : CountChildren(); for( int i=0; i<numChildren; ++i) { float w = ChildAt( i)->Frame().Width(); if (w > maxWidth) maxWidth = w; } bar->SetSteps( width/10, width); bar->SetRange( 0, MAX(0, maxWidth-width)); bar->SetProportion( MIN( 1.0f, width/maxWidth)); }
void WrappingTextView::KeyDown(const char *bytes, int32 numBytes) { if (IsEditable() && numBytes==1) { m_last_key_was_del = (bytes[0]==B_DELETE); switch( bytes[0]) { case B_RIGHT_ARROW: { // implement word-wise movement: int32 mods = Window()->CurrentMessage()->FindInt32("modifiers"); if (mods & (B_LEFT_CONTROL_KEY | B_RIGHT_OPTION_KEY)) { int32 len=TextLength(); int32 startPos, endPos; GetSelection( &startPos, &endPos); if (endPos==len) break; if (startPos==endPos && (mods & B_SHIFT_KEY)) m_selection_start=B_RIGHT_ARROW; int32 wordStart, wordEnd; if (mods & B_SHIFT_KEY && m_selection_start==B_LEFT_ARROW) { do { FindWord( startPos, &wordStart, &wordEnd); if (wordEnd > wordStart+1) break; if (wordEnd == wordStart+1 && ByteAt( wordStart)!=' ') break; } while( ++startPos < len); Select( MIN(endPos, wordEnd), endPos); } else { do { FindWord( endPos, &wordStart, &wordEnd); if (wordEnd > wordStart+1) break; if (wordEnd == wordStart+1 && ByteAt( wordStart)!=' ') break; } while( ++endPos < len); if (mods & B_SHIFT_KEY) { Select( startPos, wordEnd); } else Select( wordEnd, wordEnd); } ScrollToSelection(); } else inherited::KeyDown( bytes, numBytes); break; } case B_LEFT_ARROW: { // implement word-wise movement: int32 mods = Window()->CurrentMessage()->FindInt32("modifiers"); if (mods & (B_LEFT_CONTROL_KEY | B_RIGHT_OPTION_KEY)) { int32 startPos, endPos; GetSelection( &startPos, &endPos); if (!startPos) break; if (startPos==endPos && (mods & B_SHIFT_KEY)) m_selection_start=B_LEFT_ARROW; int32 wordStart, wordEnd; if (mods & B_SHIFT_KEY && m_selection_start==B_RIGHT_ARROW) { --endPos; do { FindWord( endPos, &wordStart, &wordEnd); if (wordEnd > wordStart+1) break; if (wordEnd == wordStart+1 && ByteAt( wordStart)!=' ') break; } while( --endPos > 0); Select( startPos, MAX( startPos, wordStart)); } else { --startPos; do { FindWord( startPos, &wordStart, &wordEnd); if (wordEnd > wordStart+1) break; if (wordEnd == wordStart+1 && ByteAt( wordStart)!=' ') break; } while( --startPos > 0); if (mods & B_SHIFT_KEY) Select( wordStart, endPos); else Select( wordStart, wordStart); } ScrollToSelection(); } else inherited::KeyDown( bytes, numBytes); break; } default: inherited::KeyDown( bytes, numBytes); break; } } else if ( numBytes == 1 ) { // in read-only mode, we use cursor-keys to move scrollbar, and // we remap HOME / END to the vertical scrollbar (not the horizontal, // which is default). switch( bytes[0]) { case B_PAGE_UP: case B_PAGE_DOWN: case B_UP_ARROW: case B_DOWN_ARROW: case B_HOME: case B_END: { // move vertical scrollbar: float min, max, smallStep, bigStep, value; BScrollBar* bar = ScrollBar( B_VERTICAL); if (!bar) return; bar->GetRange( &min, &max); bar->GetSteps( &smallStep, &bigStep); value = bar->Value(); if (bytes[0] == B_UP_ARROW) { value = MAX( value-smallStep, min); } else if (bytes[0] == B_DOWN_ARROW) { value = MIN( value+smallStep, max); } else if (bytes[0] == B_PAGE_UP) { value = MAX( value-bigStep, min); } else if (bytes[0] == B_PAGE_DOWN) { value = MIN( value+bigStep, max); } else if (bytes[0] == B_HOME) { value = min; } else if (bytes[0] == B_END) { value = max; } bar->SetValue( value); break; } default: BTextView::KeyDown( bytes, numBytes); break; } } else inherited::KeyDown( bytes, numBytes); }