diff --git a/TODO b/TODO index 98cb867e39..c168c50b6e 100644 --- a/TODO +++ b/TODO @@ -12,6 +12,7 @@ wxTextCtrl ? text ctrl display pb when text is truncated * too much is refreshed when double clicking (word select) +! update rect overlaps with horz scrollbar !! own ScrollWindow() for horz scrolling as we must always scroll by char! All diff --git a/include/wx/scrolwin.h b/include/wx/scrolwin.h index 7c6fb6a5ec..627a46fc7c 100644 --- a/include/wx/scrolwin.h +++ b/include/wx/scrolwin.h @@ -100,6 +100,22 @@ protected: return m_rectToScroll.width != 0 ? &m_rectToScroll : NULL; } + // get the size of the target window + wxSize GetTargetSize() const + { + return m_rectToScroll.width != 0 ? m_rectToScroll.GetSize() + : m_targetWindow->GetClientSize(); + } + + void GetTargetSize(int *w, int *h) + { + wxSize size = GetTargetSize(); + if ( w ) + *w = size.x; + if ( h ) + *h = size.y; + } + wxWindow *m_win, *m_targetWindow; diff --git a/include/wx/univ/control.h b/include/wx/univ/control.h index 992758dba5..b1b5d132dc 100644 --- a/include/wx/univ/control.h +++ b/include/wx/univ/control.h @@ -98,6 +98,7 @@ protected: void OnKeyDown(wxKeyEvent& event); void OnKeyUp(wxKeyEvent& event); void OnFocus(wxFocusEvent& event); + void OnActivate(wxActivateEvent& event); private: // common part of all ctors diff --git a/include/wx/univ/inphand.h b/include/wx/univ/inphand.h index 537917d046..b66d4666e5 100644 --- a/include/wx/univ/inphand.h +++ b/include/wx/univ/inphand.h @@ -71,6 +71,11 @@ public: // return TRUE to refresh the control, FALSE otherwise virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event); + // react to the app getting/losing activation + // + // return TRUE to refresh the control, FALSE otherwise + virtual bool HandleActivation(wxControl *control, bool activated); + // virtual dtor for any base class virtual ~wxInputHandler(); }; @@ -124,6 +129,7 @@ public: const wxMouseEvent& event); virtual bool HandleMouseMove(wxControl *control, const wxMouseEvent& event); virtual bool HandleFocus(wxControl *control, const wxFocusEvent& event); + virtual bool HandleActivation(wxControl *control, bool activated); private: // the window (button) which has capture or NULL and the flag telling if diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index ac19ff009e..b128e94658 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -260,6 +260,14 @@ protected: // get the logical text width (accounting for scrolling) wxCoord GetTotalWidth() const; + // the text area is the part of the window in which the text can be + // displayed, i.e. part of it inside the margins and the real text area is + // the area in which the text *is* currently displayed: for example, in the + // multiline control case the text area can have extra space at the bottom + // which is not tall enough for another line and which is then not included + // into the real text area + wxRect GetRealTextArea() const; + // refresh the text in the given (in logical coords) rect void RefreshTextRect(wxRect& rect); diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index 9456dd9d2f..96c824c7cc 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -393,8 +393,10 @@ MyUnivFrame::MyUnivFrame(const wxString& title) sizeText.x = 200; text->SetSize(sizeText); #else - wxTextCtrl *text = new wxTextCtrl(this, -1, _T("Hello,\nMultiverse!"), - wxPoint(10, 30), wxDefaultSize, + wxTextCtrl *text = new wxTextCtrl(this, -1, //_T("Hello,\nMultiverse!"), + "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", + wxPoint(10, 30), + wxSize(-1, 150), wxTE_MULTILINE); #endif text->SetFocus(); diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index 538eff7825..f82ffd7759 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -141,7 +141,12 @@ void wxAppBase::SetActive(bool active, wxWindow *lastFocus) } if ( s_lastFocus ) - s_lastFocus->Refresh(); + { + // give the focused window the chance to refresh itself if its + // appearance depends on the app activation state + wxActivateEvent event(wxEVT_ACTIVATE, active); + s_lastFocus->GetEventHandler()->ProcessEvent(event); + } } #endif // wxUSE_GUI diff --git a/src/generic/scrolwin.cpp b/src/generic/scrolwin.cpp index ca86484221..3d5af27ef6 100644 --- a/src/generic/scrolwin.cpp +++ b/src/generic/scrolwin.cpp @@ -220,7 +220,7 @@ void wxScrollHelper::SetScrollbars(int pixelsPerUnitX, AdjustScrollbars(); if (do_refresh && !noRefresh) - m_targetWindow->Refresh(); + m_targetWindow->Refresh(TRUE, GetRect()); #ifdef __WXMAC__ m_targetWindow->MacUpdateImmediately() ; @@ -383,7 +383,7 @@ int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event) if (m_xScrollPixelsPerLine > 0) { int w, h; - m_targetWindow->GetClientSize(&w, &h); + GetTargetSize(&w, &h); int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine; int noPositions = (int) ( ((nMaxWidth - w)/(double)m_xScrollPixelsPerLine) + 0.5 ); @@ -396,14 +396,14 @@ int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event) nScrollInc = noPositions - m_xScrollPosition; // As +ve as we can go } else - m_targetWindow->Refresh(); + m_targetWindow->Refresh(TRUE, GetRect()); } else { if (m_yScrollPixelsPerLine > 0) { int w, h; - m_targetWindow->GetClientSize(&w, &h); + GetTargetSize(&w, &h); int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine; int noPositions = (int) ( ((nMaxHeight - h)/(double)m_yScrollPixelsPerLine) + 0.5 ); @@ -416,7 +416,7 @@ int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event) nScrollInc = noPositions - m_yScrollPosition; // As +ve as we can go } else - m_targetWindow->Refresh(); + m_targetWindow->Refresh(TRUE, GetRect()); } return nScrollInc; @@ -426,7 +426,7 @@ int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event) void wxScrollHelper::AdjustScrollbars() { int w, h; - m_targetWindow->GetClientSize(&w, &h); + GetTargetSize(&w, &h); int oldXScroll = m_xScrollPosition; int oldYScroll = m_yScrollPosition; @@ -482,17 +482,19 @@ void wxScrollHelper::AdjustScrollbars() if (oldXScroll != m_xScrollPosition) { if (m_xScrollingEnabled) - m_targetWindow->ScrollWindow( m_xScrollPixelsPerLine * (oldXScroll-m_xScrollPosition), 0, (const wxRect *) NULL ); + m_targetWindow->ScrollWindow( m_xScrollPixelsPerLine * (oldXScroll-m_xScrollPosition), 0, + GetRect() ); else - m_targetWindow->Refresh(); + m_targetWindow->Refresh(TRUE, GetRect()); } if (oldYScroll != m_yScrollPosition) { if (m_yScrollingEnabled) - m_targetWindow->ScrollWindow( 0, m_yScrollPixelsPerLine * (oldYScroll-m_yScrollPosition), (const wxRect *) NULL ); + m_targetWindow->ScrollWindow( 0, m_yScrollPixelsPerLine * (oldYScroll-m_yScrollPosition), + GetRect() ); else - m_targetWindow->Refresh(); + m_targetWindow->Refresh(TRUE, GetRect()); } } @@ -540,7 +542,7 @@ void wxScrollHelper::Scroll( int x_pos, int y_pos ) ((y_pos == -1) || (y_pos == m_yScrollPosition))) return; int w, h; - m_targetWindow->GetClientSize(&w, &h); + GetTargetSize(&w, &h); if ((x_pos != -1) && (m_xScrollPixelsPerLine)) { @@ -558,8 +560,9 @@ void wxScrollHelper::Scroll( int x_pos, int y_pos ) m_xScrollPosition = wxMax( 0, m_xScrollPosition ); if (old_x != m_xScrollPosition) { - m_targetWindow->SetScrollPos( wxHORIZONTAL, m_xScrollPosition, TRUE ); - m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); + m_targetWindow->SetScrollPos( wxHORIZONTAL, m_xScrollPosition, FALSE ); + m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0, + GetRect() ); } } if ((y_pos != -1) && (m_yScrollPixelsPerLine)) @@ -578,8 +581,9 @@ void wxScrollHelper::Scroll( int x_pos, int y_pos ) m_yScrollPosition = wxMax( 0, m_yScrollPosition ); if (old_y != m_yScrollPosition) { - m_targetWindow->SetScrollPos( wxVERTICAL, m_yScrollPosition, TRUE ); - m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); + m_targetWindow->SetScrollPos( wxVERTICAL, m_yScrollPosition, FALSE ); + m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine, + GetRect() ); } } @@ -663,7 +667,7 @@ void wxScrollHelper::HandleOnChar(wxKeyEvent& event) clix, cliy; // view size (on screen) GetViewStart(&stx, &sty); - m_win->GetClientSize(&clix, &cliy); + GetTargetSize(&clix, &cliy); GetVirtualSize(&szx, &szy); if( m_xScrollPixelsPerLine ) diff --git a/src/univ/button.cpp b/src/univ/button.cpp index 4782b655c3..a971c3fe67 100644 --- a/src/univ/button.cpp +++ b/src/univ/button.cpp @@ -347,9 +347,16 @@ bool wxStdButtonInputHandler::HandleMouseMove(wxControl *control, bool wxStdButtonInputHandler::HandleFocus(wxControl *control, const wxFocusEvent& event) { - // buttons change appearance when they get/lose focus - control->Refresh(); + // buttons change appearance when they get/lose focus, so return TRUE to + // refresh + return TRUE; +} +bool wxStdButtonInputHandler::HandleActivation(wxControl *control, + bool activated) +{ + // the default button changes appearance when the app is [de]activated, so + // return TRUE to refresh return TRUE; } diff --git a/src/univ/control.cpp b/src/univ/control.cpp index feae6b5f35..6824207783 100644 --- a/src/univ/control.cpp +++ b/src/univ/control.cpp @@ -53,6 +53,8 @@ BEGIN_EVENT_TABLE(wxControl, wxControlBase) EVT_SET_FOCUS(wxControl::OnFocus) EVT_KILL_FOCUS(wxControl::OnFocus) + + EVT_ACTIVATE(wxControl::OnActivate) END_EVENT_TABLE() // ---------------------------------------------------------------------------- @@ -130,12 +132,22 @@ wxString wxControl::GetLabel() const } // ---------------------------------------------------------------------------- -// focus handling +// focus/activation handling // ---------------------------------------------------------------------------- void wxControl::OnFocus(wxFocusEvent& event) { - if ( !m_handler || !m_handler->HandleFocus(this, event) ) + if ( m_handler && m_handler->HandleFocus(this, event) ) + Refresh(); + else + event.Skip(); +} + +void wxControl::OnActivate(wxActivateEvent& event) +{ + if ( m_handler && m_handler->HandleActivation(this, event.GetActive()) ) + Refresh(); + else event.Skip(); } diff --git a/src/univ/inphand.cpp b/src/univ/inphand.cpp index 36305663f6..0e8949d2de 100644 --- a/src/univ/inphand.cpp +++ b/src/univ/inphand.cpp @@ -47,7 +47,14 @@ bool wxInputHandler::HandleMouseMove(wxControl * WXUNUSED(control), return FALSE; } -bool wxInputHandler::HandleFocus(wxControl *control, const wxFocusEvent& event) +bool wxInputHandler::HandleFocus(wxControl *WXUNUSED(control), + const wxFocusEvent& WXUNUSED(event)) +{ + return FALSE; +} + +bool wxInputHandler::HandleActivation(wxControl *WXUNUSED(control), + bool WXUNUSED(activated)) { return FALSE; } diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index d5907c0114..3121f1e897 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -1113,6 +1113,7 @@ bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const } } +// pos may be -1 to show the current position void wxTextCtrl::ShowPosition(long pos) { HideCaret(); @@ -1126,22 +1127,37 @@ void wxTextCtrl::ShowPosition(long pos) int xStart, yStart; GetViewStart(&xStart, &yStart); + long row, col; + if ( (pos == -1) || (pos == m_curPos) ) + { + row = m_curRow; + col = m_curCol; + } + else + { + // TODO + wxFAIL_MSG(_T("not implemented for multiline")); + + return; + } + if ( m_scrollRangeY ) { // scroll the position vertically into view: if it is currently // above it, make it the first one, otherwise the last one - if ( m_curRow < yStart ) + if ( row < yStart ) { - Scroll(0, m_curRow); + Scroll(0, row); } else { - int yEnd = yStart + GetClientSize().y / GetCharHeight() - 1; - if ( yEnd < m_curRow ) + int yEnd = yStart + + GetRealTextArea().height / GetCharHeight() - 1; + if ( yEnd < row ) { // scroll down: the current item should appear at the // bottom of the view - Scroll(0, m_curRow - (yEnd - yStart) + 1); + Scroll(0, row - (yEnd - yStart)); } } } @@ -1368,7 +1384,7 @@ void wxTextCtrl::UpdateTextRect() wxRect(wxPoint(0, 0), GetClientSize())); // only scroll this rect when the window is scrolled - SetTargetRect(m_rectText); + SetTargetRect(GetRealTextArea()); UpdateLastVisible(); } @@ -1435,6 +1451,16 @@ wxCoord wxTextCtrl::GetTextWidth(const wxString& text) const return w; } +wxRect wxTextCtrl::GetRealTextArea() const +{ + // the real text area always holds an entire number of lines, so the only + // difference with the text area is a narrow strip along the bottom border + wxRect rectText = m_rectText; + int hLine = GetCharHeight(); + rectText.height = (m_rectText.height / hLine) * hLine; + return rectText; +} + wxTextCtrlHitTestResult wxTextCtrl::HitTestLine(const wxString& line, wxCoord x, long *colOut) const @@ -1590,7 +1616,7 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTest(const wxPoint& pos, // row calculation is simple as we assume that all lines have the same // height - int row = y / GetCharHeight(); + int row = (y - 1) / GetCharHeight(); int rowMax = GetNumberOfLines() - 1; if ( row > rowMax ) { @@ -1839,7 +1865,7 @@ wxCoord wxTextCtrl::GetMaxWidth() const void wxTextCtrl::UpdateScrollbars() { - wxSize size = GetClientSize(); + wxSize size = GetRealTextArea().GetSize(); // is our height enough to show all items? int nLines = GetNumberOfLines(); @@ -1879,6 +1905,9 @@ void wxTextCtrl::UpdateScrollbars() m_scrollRangeX = scrollRangeX; m_scrollRangeY = scrollRangeY; + + // bring the current position in view + ShowPosition(-1); } } @@ -2005,6 +2034,10 @@ void wxTextCtrl::RefreshTextRect(wxRect& rect) // account for horz scrolling rect.x -= m_ofsHorz; } + else // multiline + { + CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y); + } // account for the text area offset rect.Offset(m_rectText.GetPosition()); @@ -2224,23 +2257,24 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer) // the update region is in window coord and text area is in the client // ones, so it must be shifted before computing intesection wxRegion rgnUpdate = GetUpdateRegion(); - wxRect rectTextArea = m_rectText; + wxRect rectTextArea = GetRealTextArea(); wxPoint pt = GetClientAreaOrigin(); - rectTextArea.x += pt.x; - rectTextArea.y += pt.y; - rgnUpdate.Intersect(rectTextArea); + wxRect rectTextAreaAdjusted = rectTextArea; + rectTextAreaAdjusted.x += pt.x; + rectTextAreaAdjusted.y += pt.y; + rgnUpdate.Intersect(rectTextAreaAdjusted); // even though the drawing is already clipped to the update region, we must // explicitly clip it to the rect we will use as otherwise parts of letters // might be drawn outside of it (if even a small part of a charater is // inside, HitTest() will return its column and DrawText() can't draw only // the part of the character, of course) - dc.SetClippingRegion(m_rectText); + dc.SetClippingRegion(rectTextArea); // adjust for scrolling DoPrepareDC(dc); - // and now refresh thei nvalidated parts of the window + // and now refresh the invalidated parts of the window wxRegionIterator iter(rgnUpdate); for ( ; iter.HaveRects(); iter++ ) { @@ -2323,10 +2357,10 @@ void wxTextCtrl::ShowCaret(bool show) { // position it correctly (taking scrolling into account) wxCoord xCaret, yCaret; - CalcUnscrolledPosition(m_rectText.x + GetCaretPosition() - m_ofsHorz, - m_rectText.y + m_curRow*GetCharHeight(), - &xCaret, - &yCaret); + CalcScrolledPosition(m_rectText.x + GetCaretPosition() - m_ofsHorz, + m_rectText.y + m_curRow*GetCharHeight(), + &xCaret, + &yCaret); caret->Move(xCaret, yCaret); // and show it there