wxTextCtrl work:

1. horz scrolling (not perfect yet)
2. more actions (clipboard, double click)
3. wxCaret fixes
4. clipboard support
5. wxTE_PASSWORD support

wxScrolledWindow/wxlistBox:

better hit test calculation: take into account GetClientAreaOrigin()

fix for wxGTK bug in wxDC::Blit() in wxWindow::ScrollWindow

draw transparent radio bitmaps under GTK

wxWindow::ScrollWindow() can now scroll a part of window only


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8404 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-09-22 22:49:15 +00:00
parent 634b9eb4e4
commit 025f9ba319
31 changed files with 943 additions and 377 deletions

7
TODO
View File

@@ -1,13 +1,18 @@
All
! wxThemeSettings
! actions/wxInputHandler?
* problem with lbox horz scrolling: the focus rect isn't drawn entirely...
* write sample testing all listbox styles/events
* text ctrl horz scrolling
+ text ctrl horz scrolling
* text ctrl wxTE_XXX styles support
MSW
GTK
* listbox scrolling leaves unpainted areas
+ check/radio box remains pressed in win32 mode
+ wxCheckListBox::HitTest doesn't work (clicking the check)

View File

@@ -3519,6 +3519,7 @@ fi
if test "$wxUSE_CLIPBOARD" = "yes"; then
AC_DEFINE(wxUSE_CLIPBOARD)
AC_DEFINE(wxUSE_DATAOBJ)
fi
if test "$wxUSE_DRAG_AND_DROP" = "yes" ; then

View File

@@ -337,13 +337,13 @@ button.cpp R
checkbox.cpp R
checklst.cpp R
choice.cpp R
clipbrd.cpp R
clipbrd.cpp R L
colour.cpp R L
combobox.cpp R
control.cpp R
cursor.cpp R L
data.cpp R L
dataobj.cpp R
dataobj.cpp R L
dc.cpp R L
dcclient.cpp R L
dcmemory.cpp R L
@@ -379,7 +379,7 @@ statline.cpp R
stattext.cpp R
tbargtk.cpp R
textctrl.cpp R
timer.cpp R
timer.cpp R L
tooltip.cpp R
utilsgtk.cpp R L
utilsres.cpp R

View File

@@ -196,5 +196,31 @@ private:
#include "wx/generic/caret.h"
#endif // platform
// ----------------------------------------------------------------------------
// wxCaretSuspend: a simple class which hides the caret in its ctor and
// restores it in the dtor, this should be used when drawing on the screen to
// avoid overdrawing the caret
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxCaretSuspend
{
public:
wxCaretSuspend(wxWindow *win)
{
m_caret = win->GetCaret();
if ( m_caret )
m_caret->Hide();
}
~wxCaretSuspend()
{
if ( m_caret )
m_caret->Show();
}
private:
wxCaret *m_caret;
};
#endif // _WX_CARET_H_BASE_

View File

@@ -73,6 +73,12 @@ private:
// GTK specific initialization
void InitGeneric();
// the bitmap holding the part of window hidden by the caret when it was
// at (m_xOld, m_yOld)
wxBitmap m_bmpUnderCaret;
int m_xOld,
m_yOld;
wxCaretTimer m_timer;
bool m_blinkedOut, // TRUE => caret hidden right now
m_hasFocus; // TRUE => our window has focus

View File

@@ -82,7 +82,7 @@ public:
virtual void OnDraw(wxDC& WXUNUSED(dc)) { }
// change the DC origin according to the scroll position.
void DoPrepareDC(wxDC& dc);
virtual void DoPrepareDC(wxDC& dc);
// the methods to be called from the window event handlers
void HandleOnScroll(wxScrollWinEvent& event);

View File

@@ -38,7 +38,7 @@ public:
virtual bool AcceptsFocus() const { return FALSE; }
protected:
virtual wxSize DoGetBestSize() const;
virtual wxSize DoGetBestClientSize() const;
};
#if defined(__WXUNIVERSAL__)

View File

@@ -80,7 +80,8 @@ typedef wxColourScheme wxColorScheme;
// retrieve the default colour from the theme or the given scheme
#define wxSCHEME_COLOUR(scheme, what) scheme->Get(wxColorScheme::what)
#define wxTHEME_COLOUR(what) wxSCHEME_COLOUR(wxTheme::Get(), what)
#define wxTHEME_COLOUR(what) \
wxSCHEME_COLOUR(wxTheme::Get()->GetColourScheme(), what)
// get the background colour for the window in the current theme
#define wxTHEME_BG_COLOUR(win) \

View File

@@ -32,6 +32,7 @@ class WXDLLEXPORT wxDC;
class WXDLLEXPORT wxCheckListBox;
class WXDLLEXPORT wxListBox;
class WXDLLEXPORT wxScrollBar;
class WXDLLEXPORT wxTextCtrl;
class WXDLLEXPORT wxWindow;
#include "wx/string.h"
@@ -97,15 +98,6 @@ public:
int indexAccel = -1,
wxRect *rectBounds = NULL) = 0;
// draw a line of the text ctrl optionally highlighting the characters in
// the given range
virtual void DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect &rect,
int selStart = -1,
int selEnd = -1,
int flags = 0) = 0;
// draw the border and optionally return the rectangle containing the
// region inside the border
virtual void DrawBorder(wxDC& dc,
@@ -234,6 +226,14 @@ public:
virtual wxSize GetRadioBitmapSize() const = 0;
virtual wxCoord GetCheckItemMargin() const = 0;
// convert between text rectangle and client rectangle for text controls:
// by default, the former is equal to the latter, but it can be made
// smaller to leave margins around text
virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
const wxRect& rect) = 0;
virtual wxRect GetTextClientArea(const wxTextCtrl *text,
const wxRect& rect) = 0;
// virtual dtor for any base class
virtual ~wxRenderer();
@@ -300,13 +300,6 @@ public:
wxRect *rectBounds = NULL)
{ m_renderer->DrawButtonLabel(dc, label, image, rect,
flags, align, indexAccel, rectBounds); }
virtual void DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect &rect,
int selStart = -1,
int selEnd = -1,
int flags = 0)
{ m_renderer->DrawTextLine(dc, text, rect, flags); }
virtual void DrawBorder(wxDC& dc,
wxBorder border,
const wxRect& rect,
@@ -410,6 +403,11 @@ public:
virtual wxCoord GetCheckItemMargin() const
{ return m_renderer->GetCheckItemMargin(); }
virtual wxRect GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect)
{ return m_renderer->GetTextTotalArea(text, rect); }
virtual wxRect GetTextClientArea(const wxTextCtrl *text, const wxRect& rect)
{ return m_renderer->GetTextClientArea(text, rect); }
protected:
wxRenderer *m_renderer;
};
@@ -428,7 +426,6 @@ public:
// operations
void DrawLabel(const wxBitmap& bitmap = wxNullBitmap,
wxCoord marginX = 0, wxCoord marginY = 0);
void DrawTextLine(const wxString& text, int selStart = -1, int selEnd = -1);
void DrawItems(const wxListBox *listbox,
size_t itemFirst, size_t itemLast);
void DrawCheckItems(const wxCheckListBox *listbox,

View File

@@ -64,7 +64,6 @@ public:
wxIcon GetIcon() const;
private:
virtual wxSize DoGetBestClientSize() const;
virtual void DoDraw(wxControlRenderer *renderer);
// the bitmap which we show

View File

@@ -53,6 +53,8 @@ class WXDLLEXPORT wxCaret;
// mouse selection
#define wxACTION_TEXT_ANCHOR_SEL _T("anchorsel")
#define wxACTION_TEXT_EXTEND_SEL _T("extendsel")
#define wxACTION_TEXT_SEL_WORD _T("wordsel")
#define wxACTION_TEXT_SEL_LINE _T("linesel")
// ----------------------------------------------------------------------------
// wxTextCtrl
@@ -156,6 +158,7 @@ public:
// caret stuff
virtual void ShowCaret(bool show = TRUE);
void HideCaret() { ShowCaret(FALSE); }
wxCoord GetCaretPosition() const; // in pixels
// helpers for cursor movement
long GetWordStart() const;
@@ -165,10 +168,25 @@ public:
bool HasSelection() const { return m_selStart != -1; }
void ClearSelection();
void RemoveSelection();
wxString GetSelectionText() const;
// find the character at this position, return TRUE if the character is
// really there or FALSE if it the position is beyond the end of line/text
// and the returned character is the last one
bool HitTest(const wxPoint& pt, long *col, long *row) const;
// scroll the window horizontally
void ScrollText(wxCoord x);
// adjust the DC for horz text control scrolling too
virtual void DoPrepareDC(wxDC& dc);
// implementation only from now on
// -------------------------------
// override this to take into account our scrollbar-less scrolling
virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
// set the right colours
virtual bool IsContainerWindow() const { return TRUE; }
virtual wxBorder GetDefaultBorder() const { return wxBORDER_SUNKEN; }
@@ -180,6 +198,10 @@ public:
protected:
// draw the text
void DrawTextLine(wxDC& dc, const wxRect& rect,
const wxString& text,
long selStart, long selEnd);
virtual void DoDraw(wxControlRenderer *renderer);
// calc the size from the text extent
@@ -191,11 +213,31 @@ protected:
// common part of all ctors
void Init();
// is this a single-line control?
// more readable flag testing methods
bool IsSingleLine() const { return !(GetWindowStyle() & wxTE_MULTILINE); }
bool IsPassword() const { return (GetWindowStyle() & wxTE_PASSWORD) != 0; }
// get the extent (width) of the text
wxCoord GetTextWidth(const wxString& text) const;
// refresh the text in the given range (in client coords) of this line
void RefreshLine(long line, wxCoord from, wxCoord to);
// get the text to show: either the text itself or the text replaced with
// starts for wxTE_PASSWORD control
wxString GetTextToShow(const wxString& text) const;
// get the start and end of the selection for this line: if the line is
// outside the selection, both will be -1 and FALSE will be returned
bool GetSelectedPartOfLine(long line, int *start, int *end) const;
// update the text rect: the zone inside our client rect (its coords are
// client coords) which contains the text
void UpdateTextRect();
// event handlers
void OnChar(wxKeyEvent& event);
void OnSize(wxSizeEvent& event);
private:
// the value (may be only part of it for the multiline controls)
@@ -215,6 +257,13 @@ private:
bool m_isModified:1,
m_isEditable:1;
// the rectangle (in client coordinates) to draw text inside
wxRect m_rectText;
// for the controls without horz scrollbar: the offset by which the window
// is scrolled to the right
wxCoord m_ofsHorz;
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS(wxTextCtrl)
};

View File

@@ -214,6 +214,7 @@ bool MyUnivApp::OnInit()
#ifdef DEBUG_LISTBOX
wxLog::AddTraceMask(_T("listbox"));
#endif
wxLog::AddTraceMask(_T("text"));
return TRUE;
}

View File

@@ -563,6 +563,10 @@
* Use clipboard
*/
#define wxUSE_CLIPBOARD 0
/*
* Use wxDataObject
*/
#define wxUSE_DATAOBJ 0
/*
* Use tooltips
*/

View File

@@ -125,7 +125,7 @@ void wxControlBase::InitCommandEvent(wxCommandEvent& event) const
#if wxUSE_STATBMP
wxSize wxStaticBitmapBase::DoGetBestSize() const
wxSize wxStaticBitmapBase::DoGetBestClientSize() const
{
wxBitmap bmp = GetBitmap();
if ( bmp.Ok() )

View File

@@ -33,6 +33,7 @@
#ifndef WX_PRECOMP
#include "wx/window.h"
#include "wx/dcclient.h"
#include "wx/dcmemory.h"
#endif //WX_PRECOMP
#include "wx/caret.h"
@@ -91,6 +92,10 @@ void wxCaret::InitGeneric()
{
m_hasFocus = TRUE;
m_blinkedOut = FALSE;
m_xOld =
m_yOld = -1;
m_bmpUnderCaret.Create(m_width, m_height);
}
wxCaret::~wxCaret()
@@ -98,6 +103,7 @@ wxCaret::~wxCaret()
if ( IsVisible() )
{
// stop blinking
if ( m_timer.IsRunning() )
m_timer.Stop();
}
}
@@ -108,7 +114,9 @@ wxCaret::~wxCaret()
void wxCaret::DoShow()
{
m_timer.Start(GetBlinkTime());
int blinkTime = GetBlinkTime();
if ( blinkTime )
m_timer.Start(blinkTime);
m_blinkedOut = TRUE;
Blink();
@@ -126,11 +134,20 @@ void wxCaret::DoHide()
void wxCaret::DoMove()
{
if ( IsVisible() && !m_blinkedOut )
if ( IsVisible() )
{
if ( !m_blinkedOut )
{
// hide it right now and it will be shown the next time it blinks
Blink();
// but if the caret is not blinking, we should blink it back into
// visibility manually
if ( !m_timer.IsRunning() )
Blink();
}
//else: will be shown at the correct location next time it blinks
}
//else: will be shown at the correct location when it is shown
}
// ----------------------------------------------------------------------------
@@ -153,10 +170,14 @@ void wxCaret::OnKillFocus()
// the caret must be shown - otherwise, if it is hidden now, it will
// stay so until the focus doesn't return because it won't blink any
// more
m_blinkedOut = FALSE;
}
Refresh();
// hide it first if it isn't hidden ...
if ( !m_blinkedOut )
Blink();
// .. and show it in the new style
Blink();
}
}
// ----------------------------------------------------------------------------
@@ -172,20 +193,41 @@ void wxCaret::Blink()
void wxCaret::Refresh()
{
if ( !m_blinkedOut )
wxClientDC dcWin(GetWindow());
wxMemoryDC dcMem;
dcMem.SelectObject(m_bmpUnderCaret);
if ( m_blinkedOut )
{
wxClientDC dc(GetWindow());
DoDraw(&dc);
// restore the old image
dcWin.Blit(m_xOld, m_yOld, m_width, m_height,
&dcMem, 0, 0);
m_xOld =
m_yOld = -1;
}
else
{
// FIXME can't be less efficient than this... we probably should use
// backing store for the caret instead of leaving all the burden
// of correct refresh logic handling to the user code
if ( m_xOld == -1 && m_yOld == -1 )
{
// save the part we're going to overdraw
// NB: +1 is needed!
wxRect rect(m_x, m_y, m_width + 1, m_height + 1);
GetWindow()->Refresh(FALSE, &rect);
int x = m_x,
y = m_y;
#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__)
wxPoint pt = dcWin.GetDeviceOrigin();
x += pt.x;
y += pt.y;
#endif // broken wxGTK wxDC::Blit
dcMem.Blit(0, 0, m_width, m_height,
&dcWin, x, y);
m_xOld = m_x;
m_yOld = m_y;
}
//else: we already saved the image below the caret, don't do it any
// more
// and draw the caret there
DoDraw(&dcWin);
}
}
@@ -193,19 +235,14 @@ void wxCaret::DoDraw(wxDC *dc)
{
dc->SetPen( *wxBLACK_PEN );
// VZ: Robert's code for I-shaped caret - this is nice but doesn't look
// at all the same as the MSW version and I don't know how to indicate
// that the window has focus or not with such caret
#if 0
dc->DrawLine( m_x, m_y, m_x+m_width, m_y );
dc->DrawLine( m_x, m_y+m_height, m_x+m_width, m_y+m_height );
dc->DrawLine( m_x+(m_width/2), m_y, m_x+(m_width/2), m_y+m_height );
// dc->DrawLine( m_x+(m_width/2)+1, m_y, m_x+(m_width/2)+1, m_y+m_height );
#else // 1
if ( m_hasFocus )
dc->SetBrush( *wxBLACK_BRUSH );
dc->SetBrush(*(m_hasFocus ? wxBLACK_BRUSH : wxTRANSPARENT_BRUSH));
dc->SetPen(*wxBLACK_PEN);
// VZ: unfortunately, the rectangle comes out a pixel smaller when this is
// done under wxGTK - no idea why
//dc->SetLogicalFunction(wxINVERT);
dc->DrawRectangle(m_x, m_y, m_width, m_height);
#endif // 0/1
}
#endif // wxUSE_CARET

View File

@@ -24,7 +24,6 @@
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#include "wx/mdi.h"
#endif

View File

@@ -480,8 +480,9 @@ void wxScrollHelper::AdjustScrollbars()
void wxScrollHelper::DoPrepareDC(wxDC& dc)
{
dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine,
-m_yScrollPosition * m_yScrollPixelsPerLine );
wxPoint pt = dc.GetDeviceOrigin();
dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine,
pt.y - m_yScrollPosition * m_yScrollPixelsPerLine );
dc.SetUserScale( m_scaleX, m_scaleY );
}

View File

@@ -21,7 +21,6 @@
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#if wxUSE_TREELAYOUT

View File

@@ -1068,9 +1068,12 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
}
}
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int logical_func, bool useMask )
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
wxCoord width, wxCoord height,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
int logical_func,
bool useMask )
{
/* this is the nth try to get this utterly useless function to
work. it now completely ignores the scaling or translation
@@ -1083,6 +1086,12 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
if (!m_window) return FALSE;
#if 0
// transform the source DC coords to the device ones
xsrc = XLOG2DEV(xsrc);
ysrc = YLOG2DEV(ysrc);
#endif
wxClientDC *srcDC = (wxClientDC*)source;
wxMemoryDC *memDC = (wxMemoryDC*)source;
@@ -2213,13 +2222,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
wxPaintDC::wxPaintDC( wxWindow *win )
: wxClientDC( win )
{
#ifdef __WXUNIVERSAL__
wxPoint ptOrigin = win->GetClientAreaOrigin();
SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
wxSize size = win->GetClientSize();
SetClippingRegion(wxPoint(0, 0), size);
#endif // __WXUNIVERSAL__
#if USE_PAINT_REGION
if (!win->m_clipPaintRegion)
return;
@@ -2252,6 +2254,12 @@ wxClientDC::wxClientDC()
wxClientDC::wxClientDC( wxWindow *win )
: wxWindowDC( win )
{
#ifdef __WXUNIVERSAL__
wxPoint ptOrigin = win->GetClientAreaOrigin();
SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
wxSize size = win->GetClientSize();
SetClippingRegion(wxPoint(0, 0), size);
#endif // __WXUNIVERSAL__
}
// ----------------------------------------------------------------------------

View File

@@ -1,4 +1,4 @@
# This file was automatically generated by tmake at 14:01, 2000/08/11
# This file was automatically generated by tmake at 18:07, 2000/09/19
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE GTK.T!
ALL_SOURCES = \
generic/busyinfo.cpp \
@@ -976,9 +976,11 @@ GUI_LOWLEVEL_OBJS = \
app.o \
bitmap.o \
brush.o \
clipbrd.o \
colour.o \
cursor.o \
data.o \
dataobj.o \
dc.o \
dcclient.o \
dcmemory.o \
@@ -1002,9 +1004,11 @@ GUI_LOWLEVEL_DEPS = \
app.d \
bitmap.d \
brush.d \
clipbrd.d \
colour.d \
cursor.d \
data.d \
dataobj.d \
dc.d \
dcclient.d \
dcmemory.d \

View File

@@ -1068,9 +1068,12 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
}
}
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int logical_func, bool useMask )
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
wxCoord width, wxCoord height,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
int logical_func,
bool useMask )
{
/* this is the nth try to get this utterly useless function to
work. it now completely ignores the scaling or translation
@@ -1083,6 +1086,12 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
if (!m_window) return FALSE;
#if 0
// transform the source DC coords to the device ones
xsrc = XLOG2DEV(xsrc);
ysrc = YLOG2DEV(ysrc);
#endif
wxClientDC *srcDC = (wxClientDC*)source;
wxMemoryDC *memDC = (wxMemoryDC*)source;
@@ -2213,13 +2222,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
wxPaintDC::wxPaintDC( wxWindow *win )
: wxClientDC( win )
{
#ifdef __WXUNIVERSAL__
wxPoint ptOrigin = win->GetClientAreaOrigin();
SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
wxSize size = win->GetClientSize();
SetClippingRegion(wxPoint(0, 0), size);
#endif // __WXUNIVERSAL__
#if USE_PAINT_REGION
if (!win->m_clipPaintRegion)
return;
@@ -2252,6 +2254,12 @@ wxClientDC::wxClientDC()
wxClientDC::wxClientDC( wxWindow *win )
: wxWindowDC( win )
{
#ifdef __WXUNIVERSAL__
wxPoint ptOrigin = win->GetClientAreaOrigin();
SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
wxSize size = win->GetClientSize();
SetClippingRegion(wxPoint(0, 0), size);
#endif // __WXUNIVERSAL__
}
// ----------------------------------------------------------------------------

View File

@@ -1,4 +1,4 @@
# This file was automatically generated by tmake at 14:01, 2000/08/11
# This file was automatically generated by tmake at 18:07, 2000/09/19
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE GTK.T!
ALL_SOURCES = \
generic/busyinfo.cpp \
@@ -976,9 +976,11 @@ GUI_LOWLEVEL_OBJS = \
app.o \
bitmap.o \
brush.o \
clipbrd.o \
colour.o \
cursor.o \
data.o \
dataobj.o \
dc.o \
dcclient.o \
dcmemory.o \
@@ -1002,9 +1004,11 @@ GUI_LOWLEVEL_DEPS = \
app.d \
bitmap.d \
brush.d \
clipbrd.d \
colour.d \
cursor.d \
data.d \
dataobj.d \
dc.d \
dcclient.d \
dcmemory.d \

View File

@@ -215,7 +215,8 @@ bool wxStdCheckListboxInputHandler::HandleMouse(wxControl *control,
wxCheckListBox *lbox = wxStaticCast(control, wxCheckListBox);
int x, y;
const wxPoint& pt = event.GetPosition();
wxPoint pt = event.GetPosition();
pt -= control->GetClientAreaOrigin();
lbox->CalcUnscrolledPosition(pt.x, pt.y, &x, &y);
wxRenderer *renderer = lbox->GetRenderer();

View File

@@ -15,12 +15,13 @@ UNIVOBJS = \
statbox.o \
statline.o \
stattext.o \
textctrl.o \
theme.o \
gtk.o \
winuniv.o \
win32.o
# textctrl.o \
UNIVDEPS = \
bmpbuttn.d \
button.d \

View File

@@ -524,15 +524,20 @@ void wxListBox::DoDraw(wxControlRenderer *renderer)
PrepareDC(dc);
dc.SetFont(GetFont());
// get the items which must be redrawn
wxCoord lineHeight = GetLineHeight();
// get the update rect
wxRegion rgnUpdate = GetUpdateRegion();
rgnUpdate.Intersect(GetClientRect());
wxRect rectUpdate = rgnUpdate.GetBox();
wxPoint ptOrigin = GetClientAreaOrigin();
rectUpdate.x -= ptOrigin.x;
rectUpdate.y -= ptOrigin.y;
int yTop, yBottom;
CalcUnscrolledPosition(0, rectUpdate.GetTop(), NULL, &yTop);
CalcUnscrolledPosition(0, rectUpdate.GetBottom(), NULL, &yBottom);
// get the items which must be redrawn
wxCoord lineHeight = GetLineHeight();
size_t itemFirst = yTop / lineHeight,
itemLast = (yBottom + lineHeight - 1) / lineHeight,
itemMax = m_strings.GetCount();
@@ -934,8 +939,10 @@ wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler,
int wxStdListboxInputHandler::HitTest(const wxListBox *lbox,
const wxMouseEvent& event)
{
wxPoint pt = event.GetPosition();
pt -= lbox->GetClientAreaOrigin();
int y;
lbox->CalcUnscrolledPosition(0, event.GetPosition().y, NULL, &y);
lbox->CalcUnscrolledPosition(0, pt.y, NULL, &y);
int item = y / lbox->GetLineHeight();
return (item >= 0) && (item < lbox->GetCount()) ? item : -1;

View File

@@ -456,7 +456,8 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
{
wxRect rectUpdate = rgnUpdate.GetBox();
wxLogTrace(_T("scroll"), _T("%s redraw: update box is (%d, %d)-(%d, %d)"),
wxLogTrace(_T("scrollbar"),
_T("%s redraw: update box is (%d, %d)-(%d, %d)"),
scrollbar->IsVertical() ? _T("vert") : _T("horz"),
rectUpdate.GetLeft(),
rectUpdate.GetTop(),
@@ -477,7 +478,7 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
if ( rgnUpdate.Contains(rectBar) )
{
wxLogTrace(_T("scroll"),
wxLogTrace(_T("scrollbar"),
_T("drawing bar part %d at (%d, %d)-(%d, %d)"),
nBar + 1,
rectBar.GetLeft(),
@@ -507,7 +508,7 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem);
if ( rgnUpdate.Contains(rectArrow) )
{
wxLogTrace(_T("scroll"),
wxLogTrace(_T("scrollbar"),
_T("drawing arrow %d at (%d, %d)-(%d, %d)"),
nArrow + 1,
rectArrow.GetLeft(),
@@ -529,7 +530,8 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
if ( rectThumb.width && rectThumb.height && rgnUpdate.Contains(rectThumb) )
{
wxLogTrace(_T("scroll"), _T("drawing thumb at (%d, %d)-(%d, %d)"),
wxLogTrace(_T("scrollbar"),
_T("drawing thumb at (%d, %d)-(%d, %d)"),
rectThumb.GetLeft(),
rectThumb.GetTop(),
rectThumb.GetRight(),
@@ -630,12 +632,3 @@ void wxControlRenderer::DoDrawItems(const wxListBox *lbox,
}
}
void wxControlRenderer::DrawTextLine(const wxString& text,
int selStart, int selEnd)
{
m_dc.SetFont(m_window->GetFont());
m_dc.SetTextForeground(m_window->GetForegroundColour());
m_renderer->DrawTextLine(m_dc, text, m_rect, selStart, selEnd,
m_window->GetStateFlags());
}

View File

@@ -102,11 +102,6 @@ wxIcon wxStaticBitmap::GetIcon() const
// drawing
// ----------------------------------------------------------------------------
wxSize wxStaticBitmap::DoGetBestClientSize() const
{
return wxStaticBitmapBase::DoGetBestSize();
}
void wxStaticBitmap::DoDraw(wxControlRenderer *renderer)
{
wxControl::DoDraw(renderer);

View File

@@ -30,6 +30,10 @@
#if wxUSE_TEXTCTRL
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/clipbrd.h"
#include "wx/dcclient.h"
#include "wx/validate.h"
#include "wx/textctrl.h"
@@ -39,6 +43,7 @@
#include "wx/univ/inphand.h"
#include "wx/univ/renderer.h"
#include "wx/univ/colschem.h"
#include "wx/univ/theme.h"
// ============================================================================
@@ -47,6 +52,7 @@
BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
EVT_CHAR(OnChar)
EVT_SIZE(OnSize)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
@@ -64,7 +70,7 @@ void wxTextCtrl::Init()
m_isModified = FALSE;
m_isEditable = TRUE;
m_caret = (wxCaret *)NULL;
m_ofsHorz = 0;
}
bool wxTextCtrl::Create(wxWindow *parent,
@@ -83,15 +89,17 @@ bool wxTextCtrl::Create(wxWindow *parent,
}
// FIXME use renderer
wxCaret *caret = new wxCaret(this, 2, GetCharHeight());
wxCaret *caret = new wxCaret(this, 1, GetCharHeight());
caret->SetBlinkTime(0);
SetCaret(caret);
caret->Show();
SetCursor(wxCURSOR_IBEAM);
SetValue(value);
SetBestSize(size);
caret->Show();
return TRUE;
}
@@ -122,6 +130,10 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
wxCHECK_RET( from >= 0 && to >= 0 && from <= to && to <= GetLastPosition(),
_T("invalid range in wxTextCtrl::Replace") );
// remember the line width as we may need to refresh beyond the end of the
// new text if the text shrinks
wxCoord widthOld = GetTextWidth(m_value);
// replace the part of the text with the new value
wxString valueNew(m_value, (size_t)from);
valueNew += text;
@@ -138,8 +150,12 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
// for selection anchor)
ClearSelection();
// FIXME shouldn't refresh everything of course
Refresh();
// refresh to the end of the line
wxCoord start = GetTextWidth(m_value.Left((size_t)from));
wxCoord end = GetTextWidth(m_value);
RefreshLine(0, start, wxMax(end, widthOld));
// and the affected parts of the next line (TODO)
}
void wxTextCtrl::Remove(long from, long to)
@@ -158,6 +174,9 @@ void wxTextCtrl::Remove(long from, long to)
void wxTextCtrl::WriteText(const wxString& text)
{
// replace the selection with the new text
RemoveSelection();
Replace(m_curPos, m_curPos, text);
}
@@ -174,7 +193,7 @@ void wxTextCtrl::AppendText(const wxString& text)
void wxTextCtrl::SetInsertionPoint(long pos)
{
wxCHECK_RET( pos >= 0 && pos <= GetLastPosition(),
_T("insertion poitn position out of range") );
_T("insertion point position out of range") );
if ( pos != m_curPos )
{
@@ -186,6 +205,34 @@ void wxTextCtrl::SetInsertionPoint(long pos)
{
m_curLine = 0;
m_curRow = m_curPos;
// the current position should always be shown, scroll the window
// for this if necessary
wxCoord x = GetCaretPosition();
static const wxCoord MARGIN = 3;
if ( x < wxMax(0, m_ofsHorz + MARGIN) )
{
// scroll backwards
ScrollText(x - MARGIN);
}
else
{
wxCoord width = m_rectText.width;
if ( !width )
{
// if we are called from the ctor, m_rectText is not
// initialized yet, so do it now
UpdateTextRect();
width = m_rectText.width;
}
if ( x > m_ofsHorz + width - MARGIN )
{
// scroll forward
ScrollText(x - width + MARGIN);
}
}
}
else // multi line
{
@@ -232,6 +279,26 @@ void wxTextCtrl::GetSelection(long* from, long* to) const
*to = m_selEnd;
}
wxString wxTextCtrl::GetSelectionText() const
{
wxString sel;
if ( HasSelection() )
{
if ( IsSingleLine() )
{
sel = wxString(m_value.c_str() + m_selStart,
m_value.c_str() + m_selEnd);
}
else
{
wxFAIL_MSG(_T("unimplemented for multi line"));
}
}
return sel;
}
void wxTextCtrl::SetSelection(long from, long to)
{
if ( from == -1 || to == -1 )
@@ -255,6 +322,10 @@ void wxTextCtrl::SetSelection(long from, long to)
m_selStart = from;
m_selEnd = to;
wxLogTrace(_T("text"), _T("Selection range is %ld-%ld"),
m_selStart, m_selEnd);
// FIXME: shouldn't refresh everything
Refresh();
}
//else: nothing to do
@@ -262,15 +333,20 @@ void wxTextCtrl::SetSelection(long from, long to)
}
void wxTextCtrl::ClearSelection()
{
if ( HasSelection() )
{
m_selStart =
m_selEnd = -1;
m_selAnchor = m_curPos;
// FIXME: shouldn't refresh everything
Refresh();
}
// the anchor should be moved even if there was no selection previously
m_selAnchor = m_curPos;
}
void wxTextCtrl::RemoveSelection()
{
if ( !HasSelection() )
@@ -279,6 +355,60 @@ void wxTextCtrl::RemoveSelection()
Remove(m_selStart, m_selEnd);
}
bool wxTextCtrl::GetSelectedPartOfLine(long line, int *start, int *end) const
{
if ( start )
*start = -1;
if ( end )
*end = -1;
if ( !HasSelection() )
{
// no selection at all, hence no selection in this line
return FALSE;
}
long lineStart, colStart;
PositionToXY(m_selStart, &colStart, &lineStart);
if ( lineStart > line )
{
// this line is entirely above the selection
return FALSE;
}
long lineEnd, colEnd;
PositionToXY(m_selEnd, &colEnd, &lineEnd);
if ( lineEnd < line )
{
// this line is entirely below the selection
return FALSE;
}
if ( line == lineStart )
{
if ( start )
*start = colStart;
if ( end )
*end = lineEnd == lineStart ? colEnd : GetLineLength(line);
}
else if ( line == lineEnd )
{
if ( start )
*start = lineEnd == lineStart ? colStart : 0;
if ( end )
*end = colEnd;
}
else // the line is entirely inside the selection
{
if ( start )
*start = 0;
if ( end )
*end = GetLineLength(line);
}
return TRUE;
}
// ----------------------------------------------------------------------------
// flags
// ----------------------------------------------------------------------------
@@ -304,6 +434,7 @@ void wxTextCtrl::SetEditable(bool editable)
{
m_isEditable = editable;
// the appearance of the control might have changed
Refresh();
}
}
@@ -378,8 +509,11 @@ bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
{
if ( IsSingleLine() )
{
if ( pos > GetLastPosition() )
return FALSE;
if ( x )
*x = m_curPos;
*x = pos;
if ( y )
*y = 0;
@@ -431,6 +565,11 @@ long wxTextCtrl::GetWordStart() const
if ( m_curPos == -1 || m_curPos == 0 )
return 0;
// it shouldn't be possible to learn where the word starts in the password
// text entry zone
if ( IsPassword() )
return 0;
// start at the previous position
const wxChar *p0 = m_value.c_str();
const wxChar *p = p0 + m_curPos - 1;
@@ -455,6 +594,11 @@ long wxTextCtrl::GetWordEnd() const
if ( m_curPos == -1 )
return 0;
// it shouldn't be possible to learn where the word ends in the password
// text entry zone
if ( IsPassword() )
return GetLastPosition();
// start at the current position
const wxChar *p0 = m_value.c_str();
const wxChar *p = p0 + m_curPos;
@@ -480,19 +624,41 @@ long wxTextCtrl::GetWordEnd() const
void wxTextCtrl::Copy()
{
wxFAIL_MSG(_T("not implemented"));
#if wxUSE_CLIPBOARD
if ( HasSelection() )
{
wxClipboardLocker clipLock;
wxString text = GetTextToShow(GetSelectionText());
wxTextDataObject *data = new wxTextDataObject(text);
wxTheClipboard->SetData(data);
}
#endif // wxUSE_CLIPBOARD
}
void wxTextCtrl::Cut()
{
wxFAIL_MSG(_T("not implemented"));
if ( HasSelection() )
{
Copy();
RemoveSelection();
}
}
void wxTextCtrl::Paste()
{
wxFAIL_MSG(_T("not implemented"));
}
#if wxUSE_CLIPBOARD
wxClipboardLocker clipLock;
wxTextDataObject data;
if ( wxTheClipboard->IsSupported(data.GetFormat())
&& wxTheClipboard->GetData(data) )
{
WriteText(data.GetText());
}
#endif // wxUSE_CLIPBOARD
}
void wxTextCtrl::Undo()
{
@@ -522,7 +688,7 @@ bool wxTextCtrl::CanRedo() const
wxSize wxTextCtrl::DoGetBestClientSize() const
{
wxCoord w, h;
GetTextExtent(GetLineText(0), &w, &h);
GetTextExtent(GetTextToShow(GetLineText(0)), &w, &h);
int wChar = GetCharWidth(),
hChar = GetCharHeight();
@@ -532,27 +698,383 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
if ( h < hChar )
h = hChar;
w += 2*wChar;
h += hChar / 2;
wxRect rectText;
rectText.width = w;
rectText.height = h;
wxRect rectTotal = GetRenderer()->GetTextTotalArea(this, rectText);
return wxSize(rectTotal.width, rectTotal.height);
}
return wxSize(w, h);
void wxTextCtrl::UpdateTextRect()
{
m_rectText = GetRenderer()->
GetTextClientArea(this,
wxRect(wxPoint(0, 0), GetClientSize()));
}
void wxTextCtrl::OnSize(wxSizeEvent& event)
{
UpdateTextRect();
event.Skip();
}
wxCoord wxTextCtrl::GetTextWidth(const wxString& text) const
{
wxCoord w;
GetTextExtent(GetTextToShow(text), &w, NULL);
return w;
}
bool wxTextCtrl::HitTest(const wxPoint& pos, long *colOut, long *rowOut) const
{
// is the point in the text area or to the right or below it?
bool inside = TRUE;
int x, y;
wxPoint pt = GetClientAreaOrigin();
pt += m_rectText.GetPosition();
CalcUnscrolledPosition(pos.x - pt.x, pos.y - pt.y, &x, &y);
// row calculation is simple as we assume that all lines have the same
// height
int row = y / GetCharHeight();
int rowMax = GetNumberOfLines() - 1;
if ( row > rowMax )
{
// clicking below the text is the same as clicking on the last line
row = rowMax;
inside = FALSE;
}
else if ( row < 0 )
{
row = 0;
inside = FALSE;
}
// if the line is empty, the column can only be the first one
wxString line = GetTextToShow(GetLineText(row));
int col;
wxTextCtrl *self = wxConstCast(this, wxTextCtrl);
wxClientDC dc(self);
dc.SetFont(GetFont());
self->DoPrepareDC(dc);
wxCoord width;
dc.GetTextExtent(line, &width, NULL);
if ( x >= width )
{
// clicking beyond the end of line is equivalent to clicking at
// the end of it
col = line.length();
inside = FALSE;
}
else if ( x < 0 )
{
col = 0;
inside = FALSE;
}
else // we're inside the line
{
// now calculate the column: first, approximate it with fixed-width
// value and then calculate the correct value iteratively: note that
// we use the first character of the line instead of (average)
// GetCharWidth(): it is common to have lines of dashes, for example,
// and this should give us much better approximation in such case
dc.GetTextExtent(line[0], &width, NULL);
col = x / width;
// matchDir is -1 if we must move left, +1 to move right and 0 when
// we're exactly on the character we need
int matchDir = 0;
for ( ;; )
{
// check that we didn't go beyond the line boundary
if ( col < 0 )
{
col = 0;
break;
}
if ( (size_t)col > line.length() )
{
col = line.length();
break;
}
wxString strBefore(line, (size_t)col);
dc.GetTextExtent(strBefore, &width, NULL);
if ( width >= x )
{
if ( matchDir == 1 )
{
// we were going to the right and, finally, moved beyond
// the original position: so the current is the next after
// the correct one
col--;
break;
}
else if ( matchDir == 0 )
{
// we just started iterating, now we know that we should
// move to the left
matchDir = -1;
}
//else: we are still to the right of the target, continue
}
else // width < x
{
// same logic as above ...
if ( matchDir == -1 )
{
// ... except that we don't need to back track
break;
}
else if ( matchDir == 0 )
{
// go to the right
matchDir = 1;
}
}
// this is not supposed to happen
wxASSERT_MSG( matchDir, _T("logic error in wxTextCtrl::HitTest") );
if ( matchDir == 1 )
col++;
else
col--;
}
}
if ( colOut )
*colOut = col;
if ( rowOut )
*rowOut = row;
return inside;
}
// ----------------------------------------------------------------------------
// scrolling
// ----------------------------------------------------------------------------
void wxTextCtrl::ScrollText(wxCoord x)
{
// never scroll beyond the left border
wxCoord ofsHorz = x > 0 ? x : 0;
if ( ofsHorz != m_ofsHorz )
{
// NB1: to scroll to the right, offset must be negative, hence the
// order of operands
int dx = m_ofsHorz - ofsHorz;
// NB2: ScrollWindow() calls Refresh() which results in a call to
// DoDraw(), so we must update m_ofsHorz before calling it
m_ofsHorz = ofsHorz;
ScrollWindow(dx, 0, &m_rectText);
}
}
void wxTextCtrl::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
{
wxScrollHelper::CalcUnscrolledPosition(x + m_ofsHorz, y, xx, yy);
}
void wxTextCtrl::DoPrepareDC(wxDC& dc)
{
// adjust the DC origin if the text is shifted
if ( m_ofsHorz )
{
wxPoint pt = dc.GetDeviceOrigin();
dc.SetDeviceOrigin(pt.x - m_ofsHorz, pt.y);
}
}
// ----------------------------------------------------------------------------
// refresh
// ----------------------------------------------------------------------------
void wxTextCtrl::RefreshLine(long line, wxCoord from, wxCoord to)
{
wxCoord h = GetCharHeight();
wxRect rect;
wxPoint pt = GetClientAreaOrigin() + m_rectText.GetPosition();
rect.x = pt.x + from;
rect.y = pt.y + line*h;
rect.width = to - from + 1;
rect.height = h;
wxLogTrace(_T("text"), _T("Refreshing (%d, %d)-(%d, %d)"),
rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
Refresh(TRUE, &rect);
}
// ----------------------------------------------------------------------------
// drawing
// ----------------------------------------------------------------------------
wxString wxTextCtrl::GetTextToShow(const wxString& text) const
{
wxString textShown;
if ( IsPassword() )
textShown = wxString(_T('*'), text.length());
else
textShown = text;
return textShown;
}
void wxTextCtrl::DrawTextLine(wxDC& dc, const wxRect& rect,
const wxString& text,
long selStart, long selEnd)
{
if ( selStart == -1 )
{
// just draw it as is
dc.DrawText(text, rect.x, rect.y);
}
else // we have selection
{
wxCoord width,
x = rect.x;
// draw the part before selection
wxString s(text, (size_t)selStart);
if ( !s.empty() )
{
dc.DrawText(s, x, rect.y);
dc.GetTextExtent(s, &width, NULL);
x += width;
}
// draw the selection itself
s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
if ( !s.empty() )
{
wxColour colFg = dc.GetTextForeground();
dc.SetTextForeground(wxTHEME_COLOUR(HIGHLIGHT_TEXT));
dc.SetTextBackground(wxTHEME_COLOUR(HIGHLIGHT));
dc.SetBackgroundMode(wxSOLID);
dc.DrawText(s, x, rect.y);
dc.GetTextExtent(s, &width, NULL);
x += width;
dc.SetBackgroundMode(wxTRANSPARENT);
dc.SetTextForeground(colFg);
}
// draw the final part
s = text.c_str() + selEnd;
if ( !s.empty() )
{
dc.DrawText(s, x, rect.y);
}
}
}
// TODO: don't redraw the parts of line which are not visible because they're
// outside the window (because of horz scrolling)
void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
{
if ( IsSingleLine() )
wxCaretSuspend cs(this);
wxDC& dc = renderer->GetDC();
dc.SetFont(GetFont());
dc.SetTextForeground(GetForegroundColour());
DoPrepareDC(dc);
// calculate the lines which must be redrawn
wxRegion rgnUpdate = GetUpdateRegion();
wxRect rectTextArea = m_rectText;
wxPoint pt = GetClientAreaOrigin();
rectTextArea.x += pt.x;
rectTextArea.y += pt.y;
rgnUpdate.Intersect(rectTextArea);
wxRect rectUpdate = rgnUpdate.GetBox();
pt = rectUpdate.GetPosition();
long colStart, lineStart;
(void)HitTest(pt, &colStart, &lineStart);
long colEnd, lineEnd;
pt.x += rectUpdate.width;
pt.y += rectUpdate.height;
(void)HitTest(pt, &colEnd, &lineEnd);
wxLogTrace(_T("text"), _T("Redrawing positions (%ld, %ld)-(%ld, %ld)"),
colStart, lineStart, colEnd, lineEnd);
// prepare for drawing
wxRect rectText;
rectText.x = m_rectText.x;
rectText.width = m_rectText.width;
rectText.height = GetCharHeight();
rectText.y = m_rectText.y + lineStart*rectText.height;
wxString text;
int selStart, selEnd;
// draw the part of the first line
GetSelectedPartOfLine(lineStart, &selStart, &selEnd);
wxString textLine = GetLineText(lineStart);
text = textLine.c_str() + colStart;
if ( lineEnd == lineStart )
{
// just redraw everything
renderer->DrawTextLine(m_value, (int)m_selStart, (int)m_selEnd);
text.Truncate(colEnd - colStart + 1);
}
else
rectText.x += GetTextWidth(textLine.Left(colStart));
rectText.width = GetTextWidth(text);
DrawTextLine(dc, rectText, GetTextToShow(text), selStart, selEnd);
rectText.y += rectText.height;
wxLogTrace(_T("text"), _T("Start line: positions %ld-%ld redrawn."),
colStart,
lineEnd == lineStart ? colEnd : GetLineLength(lineStart));
// all intermediate lines must be redrawn completely
rectText.x = m_rectText.x;
rectText.width = m_rectText.width;
for ( long line = lineStart + 1; line < lineEnd; line++ )
{
// TODO
GetSelectedPartOfLine(line, &selStart, &selEnd);
DrawTextLine(dc, rectText, GetTextToShow(GetLineText(line)),
selStart, selEnd);
rectText.y += rectText.height;
wxLogTrace(_T("text"), _T("Middle line %ld entirely redrawn."), line);
}
// and draw the part of the last line if it hadn't been drawn yet
if ( lineEnd != lineStart )
{
GetSelectedPartOfLine(lineEnd, &selStart, &selEnd);
text = GetLineText(lineEnd).Left(colEnd);
rectText.y += rectText.height;
DrawTextLine(dc, rectText, GetTextToShow(text),
selStart, selEnd);
wxLogTrace(_T("text"), _T("End line: positions 0-%ld redrawn."),
colEnd);
}
}
wxCoord wxTextCtrl::GetCaretPosition() const
{
wxString textBeforeCaret(GetLineText(m_curLine), (size_t)m_curRow);
return GetTextWidth(textBeforeCaret);
}
void wxTextCtrl::ShowCaret(bool show)
@@ -562,16 +1084,9 @@ void wxTextCtrl::ShowCaret(bool show)
{
caret->Show(show);
if ( caret->IsVisible() )
{
// position it correctly
wxString textBeforeCaret(m_value, (size_t)m_curPos);
wxCoord x;
GetTextExtent(textBeforeCaret, &x, NULL);
// FIXME: use renderer
caret->Move(x + 3, 3);
}
caret->Move(m_rectText.x + GetCaretPosition() - m_ofsHorz,
m_rectText.y + m_curLine*GetCharHeight());
}
}
@@ -635,14 +1150,15 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
{
if ( !strArg.empty() )
{
// replace the selection with the new text
RemoveSelection();
WriteText(strArg);
textChanged = TRUE;
}
}
else if ( action == wxACTION_TEXT_SEL_WORD )
{
SetSelection(GetWordStart(), GetWordEnd());
}
else if ( action == wxACTION_TEXT_ANCHOR_SEL )
{
newPos = numArg;
@@ -651,6 +1167,18 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
{
SetSelection(m_selAnchor, numArg);
}
else if ( action == wxACTION_TEXT_COPY )
{
Copy();
}
else if ( action == wxACTION_TEXT_CUT )
{
Cut();
}
else if ( action == wxACTION_TEXT_PASTE )
{
Paste();
}
else
{
return wxControl::PerformAction(action, numArg, strArg);
@@ -719,7 +1247,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
if ( !event.HasModifiers() )
{
int keycode = event.GetKeyCode();
if ( keycode != WXK_DELETE && keycode != WXK_BACK )
if ( keycode < 255 && keycode != WXK_DELETE && keycode != WXK_BACK )
{
PerformAction(wxACTION_TEXT_INSERT, -1, (wxChar)keycode);
@@ -745,105 +1273,8 @@ wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand)
long wxStdTextCtrlInputHandler::HitTest(const wxTextCtrl *text,
const wxPoint& pos)
{
int x, y;
text->CalcUnscrolledPosition(pos.x, pos.y, &x, &y);
// row calculation is simple as we assume that all lines have the same
// height
int row = y / text->GetCharHeight();
int rowMax = text->GetNumberOfLines() - 1;
if ( row > rowMax )
{
// clicking below the text is the same as clicking on the last line
row = rowMax;
}
// if the line is empty, the column can only be the first one
wxString line = text->GetLineText(row);
int col;
wxClientDC dc(wxConstCast(text, wxTextCtrl));
dc.SetFont(text->GetFont());
wxCoord width;
dc.GetTextExtent(line, &width, NULL);
if ( x >= width )
{
// clicking beyond the end of line is equivalent to clicking at
// the end of it
col = line.length();
}
else // we're inside the line
{
// now calculate the column: first, approximate it with fixed-width
// value and then calculate the correct value iteratively: note that
// we use the first character of the line instead of (average)
// GetCharWidth(): it is common to have lines of dashes, for example,
// and this should give us much better approximation in such case
dc.GetTextExtent(line[0], &width, NULL);
col = x / width;
// matchDir is -1 if we must move left, +1 to move right and 0 when
// we're exactly on the character we need
int matchDir = 0;
for ( ;; )
{
// check that we didn't go beyond the line boundary
if ( col < 0 )
{
col = 0;
break;
}
if ( col > line.length() )
{
col = line.length();
break;
}
wxString strBefore(line, (size_t)col);
dc.GetTextExtent(strBefore, &width, NULL);
if ( width >= x )
{
if ( matchDir == 1 )
{
// we were going to the right and, finally, moved beyond
// the original position: so the current is the next after
// the correct one
col--;
break;
}
else if ( matchDir == 0 )
{
// we just started iterating, now we know that we should
// move to the left
matchDir = -1;
}
//else: we are still to the right of the target, continue
}
else // width < x
{
// same logic as above ...
if ( matchDir == -1 )
{
// ... except that we don't need to back track
break;
}
else if ( matchDir == 0 )
{
// go to the right
matchDir = 1;
}
}
// this is not supposed to happen
wxASSERT_MSG( matchDir, _T("logic error in wxTextCtrl::HitTest") );
if ( matchDir == 1 )
col++;
else
col--;
}
}
long col, row;
(void)text->HitTest(pos, &col, &row);
return text->XYToPosition(col, row);
}
@@ -899,6 +1330,24 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
// reset the action as it could be already set to one of the
// prefixes
action = wxACTION_NONE;
if ( ctrlDown )
{
switch ( keycode )
{
case 'C':
action = wxACTION_TEXT_COPY;
break;
case 'V':
action = wxACTION_TEXT_PASTE;
break;
case 'X':
action = wxACTION_TEXT_CUT;
break;
}
}
}
if ( action != wxACTION_NONE )
@@ -933,7 +1382,8 @@ bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
}
else if ( event.LeftDClick() )
{
// TODO: select the word the cursor is on
// select the word the cursor is on
control->PerformAction(wxACTION_TEXT_SEL_WORD);
}
else if ( event.LeftUp() )
{

View File

@@ -72,12 +72,6 @@ public:
int alignment = wxALIGN_LEFT | wxALIGN_TOP,
int indexAccel = -1,
wxRect *rectBounds = NULL);
virtual void DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect &rect,
int selStart = -1,
int selEnd = -1,
int flags = 0);
virtual void DrawBorder(wxDC& dc,
wxBorder border,
const wxRect& rect,
@@ -159,6 +153,13 @@ public:
virtual wxCoord GetCheckItemMargin() const
{ return 2; }
virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
const wxRect& rect)
{ wxRect rectTotal = rect; rectTotal.Inflate(10); return rectTotal; }
virtual wxRect GetTextClientArea(const wxTextCtrl *text,
const wxRect& rect)
{ wxRect rectText = rect; rectText.Inflate(-10); return rectText; }
// helpers for "wxBitmap wxColourScheme::Get()"
void DrawCheckBitmap(wxDC& dc, const wxRect& rect);
void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
@@ -680,8 +681,11 @@ void wxGTKRenderer::DrawBorder(wxDC& dc,
switch ( border )
{
case wxBORDER_SUNKEN:
for ( int width = 0; width < 10; width++ )
{
DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
}
break;
case wxBORDER_STATIC:
@@ -689,6 +693,7 @@ void wxGTKRenderer::DrawBorder(wxDC& dc,
break;
case wxBORDER_RAISED:
for ( int width = 0; width < 10; width++ )
DrawRaisedBorder(dc, &rect);
break;
@@ -722,7 +727,7 @@ wxRect wxGTKRenderer::GetBorderDimensions(wxBorder border) const
{
case wxBORDER_RAISED:
case wxBORDER_SUNKEN:
width = 2;
width = 20;
break;
case wxBORDER_SIMPLE:
@@ -913,59 +918,6 @@ void wxGTKRenderer::DrawButtonLabel(wxDC& dc,
dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds);
}
void wxGTKRenderer::DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect &rect,
int selStart,
int selEnd,
int flags)
{
if ( selStart == -1 )
{
// just draw it as is
dc.DrawText(text, rect.x, rect.y);
}
else // we have selection
{
wxCoord width,
x = rect.x;
// draw the part before selection
wxString s(text, (size_t)selStart);
if ( !s.empty() )
{
dc.DrawText(s, x, rect.y);
dc.GetTextExtent(s, &width, NULL);
x += width;
}
// draw the selection itself
s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
if ( !s.empty() )
{
wxColour colFg = dc.GetTextForeground();
dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT));
dc.SetBackgroundMode(wxSOLID);
dc.DrawText(s, x, rect.y);
dc.GetTextExtent(s, &width, NULL);
x += width;
dc.SetBackgroundMode(wxTRANSPARENT);
dc.SetTextForeground(colFg);
}
// draw the final part
s = text.c_str() + selEnd;
if ( !s.empty() )
{
dc.DrawText(s, x, rect.y);
}
}
}
void wxGTKRenderer::DrawItem(wxDC& dc,
const wxString& label,
const wxRect& rect,
@@ -1077,7 +1029,9 @@ void wxGTKRenderer::DrawRadioBitmap(wxDC& dc,
wxCoord yMid = (y + yBottom) / 2;
// this looks ugly when the background colour of the control is not the
// same ours - radiobox is not transparent as it should be
#if 0
// first fill the middle: as FloodFill() is not implemented on all
// platforms, this is the only thing to do
wxColour colBg = flags & wxCONTROL_CURRENT
@@ -1086,6 +1040,7 @@ void wxGTKRenderer::DrawRadioBitmap(wxDC& dc,
dc.SetBrush(wxBrush(colBg, wxSOLID));
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(rect);
#endif // 0
// then draw the upper half
dc.SetPen(flags & wxCONTROL_CHECKED ? m_penDarkGrey : m_penHighlight);
@@ -1277,7 +1232,10 @@ void wxGTKRenderer::DrawRadioButton(wxDC& dc,
bitmap.Create(rect.width, rect.height);
wxMemoryDC dc;
dc.SelectObject(bitmap);
dc.SetBackground(*wxLIGHT_GREY_BRUSH);
dc.Clear();
DrawRadioBitmap(dc, rect, flags);
bitmap.SetMask(new wxMask(bitmap, *wxLIGHT_GREY));
}
DoDrawCheckOrRadioBitmap(dc, label, bitmap, rectTotal,

View File

@@ -89,12 +89,6 @@ public:
int alignment = wxALIGN_LEFT | wxALIGN_TOP,
int indexAccel = -1,
wxRect *rectBounds = NULL);
virtual void DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect &rect,
int selStart = -1,
int selEnd = -1,
int flags = 0);
virtual void DrawBorder(wxDC& dc,
wxBorder border,
const wxRect& rect,
@@ -174,6 +168,13 @@ public:
virtual wxCoord GetCheckItemMargin() const
{ return 0; }
virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
const wxRect& rect)
{ return rect; }
virtual wxRect GetTextClientArea(const wxTextCtrl *text,
const wxRect& rect)
{ return rect; }
protected:
// common part of DrawLabel() and DrawItem()
void DrawFocusRect(wxDC& dc, const wxRect& rect);
@@ -1393,16 +1394,6 @@ void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
}
}
void wxWin32Renderer::DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect &rect,
int selStart,
int selEnd,
int flags)
{
dc.DrawText(text, rect.x + 2, rect.y + 1);
}
// ----------------------------------------------------------------------------
// (check)listbox items
// ----------------------------------------------------------------------------

View File

@@ -164,9 +164,12 @@ void wxWindow::OnErase(wxEraseEvent& event)
rectCorner.SetRight(size.x - rectBorder.width);
rectCorner.SetBottom(size.y - rectBorder.height);
if ( GetUpdateRegion().Contains(rectCorner) )
{
m_renderer->DrawScrollCorner(*event.GetDC(), rectCorner);
}
}
}
// the event handlers executed when the window must be repainted
void wxWindow::OnNcPaint(wxPaintEvent& event)
@@ -201,11 +204,7 @@ void wxWindow::OnPaint(wxPaintEvent& event)
bool wxWindow::DoDrawBackground(wxDC& dc)
{
wxRect rect;
wxSize size = GetSize(); // full, not client only
rect.width = size.x;
rect.height = size.y;
wxRect rect = GetUpdateRegion().GetBox();
if ( GetBackgroundBitmap().Ok() )
{
// get the bitmap and the flags
@@ -246,10 +245,16 @@ void wxWindow::DoDrawBorder(wxDC& dc)
rect.height -= scrollbar->GetSize().y;
}
// draw outline
// draw outline unless the update region is enitrely inside it in which
// case we don't need to do it
#if 0 // doesn't seem to work, why?
if ( wxRegion(rect).Contains(GetUpdateRegion().GetBox()) != wxInRegion )
#endif
{
m_renderer->DrawBorder(dc, GetBorder(),
rect, GetStateFlags(), &rect);
}
}
void wxWindow::DoDraw(wxControlRenderer *renderer)
{
@@ -371,11 +376,17 @@ void wxWindow::DoGetClientSize(int *width, int *height) const
wxSize size = GetSize();
bool inside = m_renderer->AreScrollbarsInsideBorder();
if ( width )
{
// in any case, take account of the scrollbar
if ( m_scrollbarVert )
*width -= size.x - m_scrollbarVert->GetPosition().x;
else
// if we don't have scrollbar or if it is outside the border (and not
// blended into it), take account of the right border as well
if ( !m_scrollbarVert || !inside )
*width -= rectBorder.width;
*width -= rectBorder.x;
@@ -385,7 +396,8 @@ void wxWindow::DoGetClientSize(int *width, int *height) const
{
if ( m_scrollbarHorz )
*height -= size.y - m_scrollbarHorz->GetPosition().y;
else
if ( !m_scrollbarHorz || !inside )
*height -= rectBorder.height;
*height -= rectBorder.y;
@@ -402,15 +414,16 @@ void wxWindow::DoSetClientSize(int width, int height)
// and the scrollbars (as they may be offset into the border, use the
// scrollbar position, not size - this supposes that PositionScrollbars()
// had been called before)
bool inside = m_renderer->AreScrollbarsInsideBorder();
wxSize size = GetSize();
if ( m_scrollbarVert )
width += size.x - m_scrollbarVert->GetPosition().x;
else
if ( !m_scrollbarVert || !inside )
width += rectBorder.width;
if ( m_scrollbarHorz )
height += size.y - m_scrollbarHorz->GetPosition().y;
else
if ( !m_scrollbarHorz || !inside )
height += rectBorder.height;
wxWindowNative::DoSetClientSize(width, height);
@@ -551,8 +564,6 @@ int wxWindow::GetScrollRange(int orient) const
void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
{
wxASSERT_MSG( !rect, _T("scrolling only part of window not implemented") );
if ( !dx && !dy )
{
// nothing to do
@@ -561,27 +572,30 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
// calculate the part of the window which we can just redraw in the new
// location
wxSize sizeTotal = GetClientSize();
wxSize sizeTotal = rect ? rect->GetSize() : GetClientSize();
wxLogTrace(_T("scroll"), _T("window is %dx%d, scroll by %d, %d"),
wxLogTrace(_T("scroll"), _T("rect is %dx%d, scroll by %d, %d"),
sizeTotal.x, sizeTotal.y, dx, dy);
wxPoint ptSource, ptDest, ptOrigin;
ptSource =
ptDest =
ptOrigin = GetClientAreaOrigin();
wxPoint ptSource, ptDest;
if ( rect )
ptDest = rect->GetPosition();
wxSize size;
size.x = sizeTotal.x - abs(dx) - 1;
size.y = sizeTotal.y - abs(dy) - 1;
size.x = sizeTotal.x - abs(dx);
size.y = sizeTotal.y - abs(dy);
if ( size.x <= 0 || size.y <= 0 )
{
// just redraw everything as nothing of the displayed image will stay
wxLogTrace(_T("scroll"), _T("refreshing everything"));
Refresh();
Refresh(TRUE, rect);
}
else // move the part which doesn't change to the new location
{
wxPoint ptOrigin = GetClientAreaOrigin();
if ( rect )
ptOrigin += rect->GetPosition();
// note that when we scroll the canvas in some direction we move the
// block which doesn't need to be refreshed in the opposite direction
@@ -612,7 +626,12 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
wxBitmap bmp(size.x, size.y);
wxMemoryDC dcMem;
dcMem.SelectObject(bmp);
dcMem.Blit(wxPoint(0, 0), size, &dc, ptSource);
dcMem.Blit(wxPoint(0, 0), size, &dc, ptSource
#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__)
+ ptOrigin
#endif // broken wxGTK wxDC::Blit
);
dc.Blit(ptDest, size, &dcMem, wxPoint(0, 0));
wxLogTrace(_T("scroll"),
@@ -647,7 +666,8 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
rect.height = sizeTotal.y;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),
rect.x, rect.y, rect.GetRight(), rect.GetBottom());
rect.x, rect.y,
rect.GetRight() + 1, rect.GetBottom() + 1);
Refresh(TRUE /* erase bkgnd */, &rect);
}
@@ -669,7 +689,8 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
rect.width = sizeTotal.x;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),
rect.x, rect.y, rect.GetRight(), rect.GetBottom());
rect.x, rect.y,
rect.GetRight() + 1, rect.GetBottom() + 1);
Refresh(TRUE /* erase bkgnd */, &rect);
}