Files
wxWidgets/src/gtk/textctrl.cpp
Robert Roebling 65045edde4 Added wxFFileStream base on wxFFile (as opposed to wxFile)
Implemented the "endl" thing for text streams,
  Corrected cursor display for text ctrls,
  Corrected the strange spin button behaviour when dynamically
    changing its range
  Corrcected bug in wxListBox when programmatically unselecting
   an item in multi-select mode (bug reports are getting esoteric)


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3440 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1999-08-22 16:12:48 +00:00

955 lines
25 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: textctrl.cpp
// Purpose:
// Author: Robert Roebling
// Id: $Id$
// Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "textctrl.h"
#endif
#include "wx/textctrl.h"
#include "wx/utils.h"
#include "wx/intl.h"
#include "wx/settings.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include "gdk/gdk.h"
#include "gtk/gtk.h"
#include "gdk/gdkkeysyms.h"
//-----------------------------------------------------------------------------
// idle system
//-----------------------------------------------------------------------------
extern void wxapp_install_idle_handler();
extern bool g_isIdle;
//-----------------------------------------------------------------------------
// data
//-----------------------------------------------------------------------------
extern bool g_blockEventsOnDrag;
extern wxCursor g_globalCursor;
//-----------------------------------------------------------------------------
// "changed"
//-----------------------------------------------------------------------------
static void
gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
{
if (!win->m_hasVMT) return;
if (g_isIdle)
wxapp_install_idle_handler();
win->SetModified();
wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, win->GetId() );
event.SetString( win->GetValue() );
event.SetEventObject( win );
win->GetEventHandler()->ProcessEvent( event );
}
//-----------------------------------------------------------------------------
// "changed" from vertical scrollbar
//-----------------------------------------------------------------------------
static void
gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
{
if (!win->m_hasVMT) return;
if (g_isIdle)
wxapp_install_idle_handler();
win->CalculateScrollbar();
}
//-----------------------------------------------------------------------------
// wxTextCtrl
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl,wxControl)
BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
EVT_CHAR(wxTextCtrl::OnChar)
EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
END_EVENT_TABLE()
wxTextCtrl::wxTextCtrl()
{
m_modified = FALSE;
}
wxTextCtrl::wxTextCtrl( wxWindow *parent, wxWindowID id, const wxString &value,
const wxPoint &pos, const wxSize &size,
int style, const wxValidator& validator, const wxString &name )
{
m_modified = FALSE;
Create( parent, id, value, pos, size, style, validator, name );
}
bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value,
const wxPoint &pos, const wxSize &size,
int style, const wxValidator& validator, const wxString &name )
{
m_needParent = TRUE;
m_acceptsFocus = TRUE;
if (!PreCreation( parent, pos, size ) ||
!CreateBase( parent, id, pos, size, style, validator, name ))
{
wxFAIL_MSG( _T("wxTextCtrl creation failed") );
return FALSE;
}
m_vScrollbarVisible = FALSE;
bool multi_line = (style & wxTE_MULTILINE) != 0;
if (multi_line)
{
#if (GTK_MINOR_VERSION > 2)
/* a multi-line edit control: create a vertical scrollbar by default and
horizontal if requested */
bool bHasHScrollbar = (style & wxHSCROLL) != 0;
#else
bool bHasHScrollbar = FALSE;
#endif
/* create our control ... */
m_text = gtk_text_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
/* ... and put into the upper left hand corner of the table */
m_widget = gtk_table_new(bHasHScrollbar ? 2 : 1, 2, FALSE);
GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
gtk_table_attach( GTK_TABLE(m_widget), m_text, 0, 1, 0, 1,
(GtkAttachOptions)(GTK_FILL | GTK_EXPAND | GTK_SHRINK),
(GtkAttachOptions)(GTK_FILL | GTK_EXPAND | GTK_SHRINK),
0, 0);
/* always wrap words */
gtk_text_set_word_wrap( GTK_TEXT(m_text), TRUE );
#if (GTK_MINOR_VERSION > 2)
/* put the horizontal scrollbar in the lower left hand corner */
if (bHasHScrollbar)
{
GtkWidget *hscrollbar = gtk_hscrollbar_new(GTK_TEXT(m_text)->hadj);
GTK_WIDGET_UNSET_FLAGS( hscrollbar, GTK_CAN_FOCUS );
gtk_table_attach(GTK_TABLE(m_widget), hscrollbar, 0, 1, 1, 2,
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK),
GTK_FILL,
0, 0);
gtk_widget_show(hscrollbar);
/* don't wrap lines, otherwise we wouldn't need the scrollbar */
gtk_text_set_line_wrap( GTK_TEXT(m_text), FALSE );
}
#endif
/* finally, put the vertical scrollbar in the upper right corner */
m_vScrollbar = gtk_vscrollbar_new( GTK_TEXT(m_text)->vadj );
GTK_WIDGET_UNSET_FLAGS( m_vScrollbar, GTK_CAN_FOCUS );
gtk_table_attach(GTK_TABLE(m_widget), m_vScrollbar, 1, 2, 0, 1,
GTK_FILL,
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK),
0, 0);
}
else
{
/* a single-line text control: no need for scrollbars */
m_widget =
m_text = gtk_entry_new();
}
wxSize newSize = size;
if (newSize.x == -1) newSize.x = 80;
if (newSize.y == -1) newSize.y = 26;
SetSize( newSize.x, newSize.y );
m_parent->DoAddChild( this );
PostCreation();
if (multi_line)
gtk_widget_show(m_text);
/* we want to be notified about text changes */
gtk_signal_connect( GTK_OBJECT(m_text), "changed",
GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
if (multi_line)
{
gtk_signal_connect(GTK_OBJECT(GTK_TEXT(m_text)->vadj), "changed",
(GtkSignalFunc) gtk_scrollbar_changed_callback, (gpointer) this );
}
if (!value.IsEmpty())
{
gint tmp = 0;
#if GTK_MINOR_VERSION == 0
// if we don't realize it, GTK 1.0.6 dies with a SIGSEGV in
// gtk_editable_insert_text()
gtk_widget_realize(m_text);
#endif // GTK 1.0
#if wxUSE_UNICODE
wxWX2MBbuf val = value.mbc_str();
gtk_editable_insert_text( GTK_EDITABLE(m_text), val, strlen(val), &tmp );
#else // !Unicode
gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &tmp );
#endif // Unicode/!Unicode
if (multi_line)
{
/* bring editable's cursor uptodate. bug in GTK. */
GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
}
}
if (style & wxTE_PASSWORD)
{
if (!multi_line)
gtk_entry_set_visibility( GTK_ENTRY(m_text), FALSE );
}
if (style & wxTE_READONLY)
{
if (!multi_line)
gtk_entry_set_editable( GTK_ENTRY(m_text), FALSE );
}
else
{
if (multi_line)
gtk_text_set_editable( GTK_TEXT(m_text), 1 );
}
SetBackgroundColour( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) );
SetForegroundColour( parent->GetForegroundColour() );
m_cursor = wxCursor( wxCURSOR_IBEAM );
Show( TRUE );
return TRUE;
}
void wxTextCtrl::CalculateScrollbar()
{
if ((m_windowStyle & wxTE_MULTILINE) == 0) return;
GtkAdjustment *adj = GTK_TEXT(m_text)->vadj;
if (adj->upper - adj->page_size < 0.8)
{
if (m_vScrollbarVisible)
{
gtk_widget_hide( m_vScrollbar );
m_vScrollbarVisible = FALSE;
}
}
else
{
if (!m_vScrollbarVisible)
{
gtk_widget_show( m_vScrollbar );
m_vScrollbarVisible = TRUE;
}
}
}
wxString wxTextCtrl::GetValue() const
{
wxCHECK_MSG( m_text != NULL, _T(""), _T("invalid text ctrl") );
wxString tmp;
if (m_windowStyle & wxTE_MULTILINE)
{
gint len = gtk_text_get_length( GTK_TEXT(m_text) );
char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
tmp = wxString(text,*wxConvCurrent);
g_free( text );
}
else
{
tmp = wxString(gtk_entry_get_text( GTK_ENTRY(m_text) ),*wxConvCurrent);
}
return tmp;
}
void wxTextCtrl::SetValue( const wxString &value )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
wxString tmp = _T("");
if (!value.IsNull()) tmp = value;
if (m_windowStyle & wxTE_MULTILINE)
{
gint len = gtk_text_get_length( GTK_TEXT(m_text) );
gtk_editable_delete_text( GTK_EDITABLE(m_text), 0, len );
len = 0;
#if wxUSE_UNICODE
wxWX2MBbuf tmpbuf = tmp.mbc_str();
gtk_editable_insert_text( GTK_EDITABLE(m_text), tmpbuf, strlen(tmpbuf), &len );
#else
gtk_editable_insert_text( GTK_EDITABLE(m_text), tmp.mbc_str(), tmp.Length(), &len );
#endif
}
else
{
gtk_entry_set_text( GTK_ENTRY(m_text), tmp.mbc_str() );
}
}
void wxTextCtrl::WriteText( const wxString &text )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if (text.IsEmpty()) return;
if (m_windowStyle & wxTE_MULTILINE)
{
/* this moves the cursor pos to behind the inserted text */
gint len = GTK_EDITABLE(m_text)->current_pos;
#if wxUSE_UNICODE
wxWX2MBbuf buf = text.mbc_str();
gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len );
#else
gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
#endif
/* bring editable's cursor uptodate. bug in GTK. */
GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
}
else
{
/* this moves the cursor pos to behind the inserted text */
gint len = GTK_EDITABLE(m_text)->current_pos;
#if wxUSE_UNICODE
wxWX2MBbuf buf = text.mbc_str();
gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len );
#else
gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
#endif
/* bring editable's cursor uptodate. bug in GTK. */
GTK_EDITABLE(m_text)->current_pos += text.Len();
/* bring entry's cursor uptodate. bug in GTK. */
gtk_entry_set_position( GTK_ENTRY(m_text), GTK_EDITABLE(m_text)->current_pos );
}
}
void wxTextCtrl::AppendText( const wxString &text )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if (text.IsEmpty()) return;
if (m_windowStyle & wxTE_MULTILINE)
{
bool hasSpecialAttributes = m_font.Ok() ||
m_foregroundColour.Ok() ||
m_backgroundColour.Ok();
if ( hasSpecialAttributes )
{
gtk_text_insert( GTK_TEXT(m_text),
m_font.GetInternalFont(),
m_foregroundColour.GetColor(),
m_backgroundColour.GetColor(),
text.mbc_str(), text.length());
}
else
{
/* we'll insert at the last position */
gint len = gtk_text_get_length( GTK_TEXT(m_text) );
#if wxUSE_UNICODE
wxWX2MBbuf buf = text.mbc_str();
gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len );
#else
gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
#endif
}
/* bring editable's cursor uptodate. bug in GTK. */
GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
}
else
{
gtk_entry_append_text( GTK_ENTRY(m_text), text.mbc_str() );
}
}
wxString wxTextCtrl::GetLineText( long lineNo ) const
{
if (m_windowStyle & wxTE_MULTILINE)
{
gint len = gtk_text_get_length( GTK_TEXT(m_text) );
char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
if (text)
{
wxString buf(_T(""));
long i;
int currentLine = 0;
for (i = 0; currentLine != lineNo && text[i]; i++ )
if (text[i] == '\n')
currentLine++;
// Now get the text
int j;
for (j = 0; text[i] && text[i] != '\n'; i++, j++ )
buf += text[i];
g_free( text );
return buf;
}
else
return wxEmptyString;
}
else
{
if (lineNo == 0) return GetValue();
return wxEmptyString;
}
}
void wxTextCtrl::OnDropFiles( wxDropFilesEvent &WXUNUSED(event) )
{
/* If you implement this, don't forget to update the documentation!
* (file docs/latex/wx/text.tex) */
wxFAIL_MSG( _T("wxTextCtrl::OnDropFiles not implemented") );
}
bool wxTextCtrl::PositionToXY(long pos, long *x, long *y ) const
{
if ( m_windowStyle & wxTE_MULTILINE )
{
wxString text = GetValue();
// cast to prevent warning. But pos really should've been unsigned.
if( (unsigned long)pos > text.Len() )
return FALSE;
*x=0; // First Col
*y=0; // First Line
const wxChar* stop = text.c_str() + pos;
for ( const wxChar *p = text.c_str(); p < stop; p++ )
{
if (*p == _T('\n'))
{
(*y)++;
*x=0;
}
else
(*x)++;
}
}
else // single line control
{
if ( pos <= GTK_ENTRY(m_text)->text_length )
{
*y = 0;
*x = pos;
}
else
{
// index out of bounds
return FALSE;
}
}
return TRUE;
}
long wxTextCtrl::XYToPosition(long x, long y ) const
{
if (!(m_windowStyle & wxTE_MULTILINE)) return 0;
long pos=0;
for( int i=0; i<y; i++ ) pos += GetLineLength(i) + 1; // one for '\n'
pos += x;
return pos;
}
int wxTextCtrl::GetLineLength(long lineNo) const
{
wxString str = GetLineText (lineNo);
return (int) str.Length();
}
int wxTextCtrl::GetNumberOfLines() const
{
if (m_windowStyle & wxTE_MULTILINE)
{
gint len = gtk_text_get_length( GTK_TEXT(m_text) );
char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
if (text)
{
int currentLine = 0;
for (int i = 0; i < len; i++ )
{
if (text[i] == '\n')
currentLine++;
}
g_free( text );
// currentLine is 0 based, add 1 to get number of lines
return currentLine + 1;
}
else
{
return 0;
}
}
else
{
return 1;
}
}
void wxTextCtrl::SetInsertionPoint( long pos )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if (m_windowStyle & wxTE_MULTILINE)
{
/* seems to be broken in GTK 1.0.X:
gtk_text_set_point( GTK_TEXT(m_text), (int)pos ); */
gtk_signal_disconnect_by_func( GTK_OBJECT(m_text),
GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
/* we fake a set_point by inserting and deleting. as the user
isn't supposed to get to know about thos non-sense, we
disconnect so that no events are sent to the user program. */
gint tmp = (gint)pos;
gtk_editable_insert_text( GTK_EDITABLE(m_text), " ", 1, &tmp );
gtk_editable_delete_text( GTK_EDITABLE(m_text), tmp-1, tmp );
gtk_signal_connect( GTK_OBJECT(m_text), "changed",
GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
/* bring editable's cursor uptodate. another bug in GTK. */
GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
}
else
{
gtk_entry_set_position( GTK_ENTRY(m_text), (int)pos );
/* bring editable's cursor uptodate. bug in GTK. */
GTK_EDITABLE(m_text)->current_pos = pos;
}
}
void wxTextCtrl::SetInsertionPointEnd()
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if (m_windowStyle & wxTE_MULTILINE)
SetInsertionPoint(gtk_text_get_length(GTK_TEXT(m_text)));
else
gtk_entry_set_position( GTK_ENTRY(m_text), -1 );
}
void wxTextCtrl::SetEditable( bool editable )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if (m_windowStyle & wxTE_MULTILINE)
gtk_text_set_editable( GTK_TEXT(m_text), editable );
else
gtk_entry_set_editable( GTK_ENTRY(m_text), editable );
}
void wxTextCtrl::DiscardEdits()
{
m_modified = FALSE;
}
void wxTextCtrl::SetSelection( long from, long to )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
}
void wxTextCtrl::ShowPosition( long WXUNUSED(pos) )
{
// SetInsertionPoint( pos );
}
long wxTextCtrl::GetInsertionPoint() const
{
wxCHECK_MSG( m_text != NULL, 0, _T("invalid text ctrl") );
return (long) GTK_EDITABLE(m_text)->current_pos;
}
long wxTextCtrl::GetLastPosition() const
{
wxCHECK_MSG( m_text != NULL, 0, _T("invalid text ctrl") );
int pos = 0;
if (m_windowStyle & wxTE_MULTILINE)
pos = gtk_text_get_length( GTK_TEXT(m_text) );
else
pos = GTK_ENTRY(m_text)->text_length;
return (long)pos;
}
void wxTextCtrl::Remove( long from, long to )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
}
void wxTextCtrl::Replace( long from, long to, const wxString &value )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
if (!value.IsEmpty())
{
gint pos = (gint)from;
#if wxUSE_UNICODE
wxWX2MBbuf buf = value.mbc_str();
gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &pos );
#else
gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &pos );
#endif
}
}
void wxTextCtrl::Cut()
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
#if (GTK_MINOR_VERSION > 0)
gtk_editable_cut_clipboard( GTK_EDITABLE(m_text) );
#else
gtk_editable_cut_clipboard( GTK_EDITABLE(m_text), 0 );
#endif
}
void wxTextCtrl::Copy()
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
#if (GTK_MINOR_VERSION > 0)
gtk_editable_copy_clipboard( GTK_EDITABLE(m_text) );
#else
gtk_editable_copy_clipboard( GTK_EDITABLE(m_text), 0 );
#endif
}
void wxTextCtrl::Paste()
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
#if (GTK_MINOR_VERSION > 0)
gtk_editable_paste_clipboard( GTK_EDITABLE(m_text) );
#else
gtk_editable_paste_clipboard( GTK_EDITABLE(m_text), 0 );
#endif
}
bool wxTextCtrl::CanCopy() const
{
// Can copy if there's a selection
long from, to;
GetSelection(& from, & to);
return (from != to) ;
}
bool wxTextCtrl::CanCut() const
{
// Can cut if there's a selection
long from, to;
GetSelection(& from, & to);
return (from != to) ;
}
bool wxTextCtrl::CanPaste() const
{
return IsEditable() ;
}
// Undo/redo
void wxTextCtrl::Undo()
{
// TODO
wxFAIL_MSG( _T("wxTextCtrl::Undo not implemented") );
}
void wxTextCtrl::Redo()
{
// TODO
wxFAIL_MSG( _T("wxTextCtrl::Redo not implemented") );
}
bool wxTextCtrl::CanUndo() const
{
// TODO
wxFAIL_MSG( _T("wxTextCtrl::CanUndo not implemented") );
return FALSE;
}
bool wxTextCtrl::CanRedo() const
{
// TODO
wxFAIL_MSG( _T("wxTextCtrl::CanRedo not implemented") );
return FALSE;
}
// If the return values from and to are the same, there is no
// selection.
void wxTextCtrl::GetSelection(long* from, long* to) const
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if (!(GTK_EDITABLE(m_text)->has_selection))
{
if (from) *from = 0;
if (to) *to = 0;
return;
}
if (from) *from = (long) GTK_EDITABLE(m_text)->selection_start_pos;
if (to) *to = (long) GTK_EDITABLE(m_text)->selection_end_pos;
}
bool wxTextCtrl::IsEditable() const
{
wxCHECK_MSG( m_text != NULL, FALSE, _T("invalid text ctrl") );
return GTK_EDITABLE(m_text)->editable;
}
bool wxTextCtrl::IsModified() const
{
return m_modified;
}
void wxTextCtrl::Clear()
{
SetValue( _T("") );
}
void wxTextCtrl::OnChar( wxKeyEvent &key_event )
{
wxCHECK_RET( m_text != NULL, _T("invalid text ctrl") );
if ((key_event.KeyCode() == WXK_RETURN) && (m_windowStyle & wxPROCESS_ENTER))
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
event.SetEventObject(this);
if (GetEventHandler()->ProcessEvent(event)) return;
}
key_event.Skip();
}
GtkWidget* wxTextCtrl::GetConnectWidget()
{
return GTK_WIDGET(m_text);
}
bool wxTextCtrl::IsOwnGtkWindow( GdkWindow *window )
{
if (m_windowStyle & wxTE_MULTILINE)
return (window == GTK_TEXT(m_text)->text_area);
else
return (window == GTK_ENTRY(m_text)->text_area);
}
// the font will change for subsequent text insertiongs
bool wxTextCtrl::SetFont( const wxFont &font )
{
wxCHECK_MSG( m_text != NULL, FALSE, _T("invalid text ctrl") );
if ( !wxWindowBase::SetFont(font) )
{
// font didn't change, nothing to do
return FALSE;
}
if ( m_windowStyle & wxTE_MULTILINE )
{
// for compatibility with other ports: the font is a global controls
// characteristic, so change the font globally
wxString value = GetValue();
if ( !value.IsEmpty() )
{
Clear();
AppendText(value);
}
}
return TRUE;
}
bool wxTextCtrl::SetForegroundColour( const wxColour &WXUNUSED(colour) )
{
wxCHECK_MSG( m_text != NULL, FALSE, _T("invalid text ctrl") );
// doesn't work
return FALSE;
}
bool wxTextCtrl::SetBackgroundColour( const wxColour &colour )
{
wxCHECK_MSG( m_text != NULL, FALSE, _T("invalid text ctrl") );
wxControl::SetBackgroundColour( colour );
if (!m_widget->window)
return FALSE;
wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
if (sysbg.Red() == colour.Red() &&
sysbg.Green() == colour.Green() &&
sysbg.Blue() == colour.Blue())
{
return FALSE; // FIXME or TRUE?
}
if (!m_backgroundColour.Ok())
return FALSE;
if (m_windowStyle & wxTE_MULTILINE)
{
GdkWindow *window = GTK_TEXT(m_text)->text_area;
if (!window)
return FALSE;
m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
gdk_window_set_background( window, m_backgroundColour.GetColor() );
gdk_window_clear( window );
}
return TRUE;
}
void wxTextCtrl::ApplyWidgetStyle()
{
if (m_windowStyle & wxTE_MULTILINE)
{
// how ?
}
else
{
SetWidgetStyle();
gtk_widget_set_style( m_text, m_widgetStyle );
}
}
void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
{
Cut();
}
void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
{
Copy();
}
void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
{
Paste();
}
void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
{
Undo();
}
void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
{
Redo();
}
void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
{
event.Enable( CanCut() );
}
void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
{
event.Enable( CanCopy() );
}
void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
{
event.Enable( CanPaste() );
}
void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
{
event.Enable( CanUndo() );
}
void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
{
event.Enable( CanRedo() );
}
void wxTextCtrl::OnInternalIdle()
{
wxCursor cursor = m_cursor;
if (g_globalCursor.Ok()) cursor = g_globalCursor;
if (cursor.Ok() && m_currentGdkCursor != cursor)
{
m_currentGdkCursor = cursor;
GdkWindow *window = (GdkWindow*) NULL;
if (HasFlag(wxTE_MULTILINE))
window = GTK_TEXT(m_text)->text_area;
else
window = GTK_ENTRY(m_text)->text_area;
if (window)
gdk_window_set_cursor( window, cursor.GetCursor() );
if (!g_globalCursor.Ok())
cursor = *wxSTANDARD_CURSOR;
window = m_widget->window;
if (window)
gdk_window_set_cursor( window, cursor.GetCursor() );
}
}