Add wxTextEntry::ForceUpper()
Allow automatically converting lower-case letters entered into wxTextCtrl to upper-case equivalents. Provide generic fallback and implement the method natively for all the major platforms. Also update the text sample to show it in action.
This commit is contained in:
parent
99d9a81e28
commit
69b66e9e2e
@ -90,6 +90,7 @@ All (GUI):
|
||||
- Allow customizing window shown by wxBusyInfo.
|
||||
- Add wxAddRemoveCtrl.
|
||||
- Add wxAppProgressIndicator for MSW (Chaobin Zhang) and OS X (Tobias Taschner).
|
||||
- Add wxTextEntry::ForceUpper().
|
||||
- Add wxEVT_MAGNIFY mouse event (Joost Nieuwenhuijse).
|
||||
- Add wxProcess::Activate().
|
||||
- Fix setting colours of labels in wxSlider.
|
||||
|
@ -21,7 +21,7 @@ typedef struct _GtkEntry GtkEntry;
|
||||
class WXDLLIMPEXP_CORE wxTextEntry : public wxTextEntryBase
|
||||
{
|
||||
public:
|
||||
wxTextEntry() { }
|
||||
wxTextEntry() { m_isUpperCase = false; }
|
||||
|
||||
// implement wxTextEntryBase pure virtual methods
|
||||
virtual void WriteText(const wxString& text) wxOVERRIDE;
|
||||
@ -47,6 +47,7 @@ public:
|
||||
virtual void SetEditable(bool editable) wxOVERRIDE;
|
||||
|
||||
virtual void SetMaxLength(unsigned long len) wxOVERRIDE;
|
||||
virtual void ForceUpper() wxOVERRIDE;
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
virtual bool SetHint(const wxString& hint) wxOVERRIDE;
|
||||
@ -56,6 +57,7 @@ public:
|
||||
// implementation only from now on
|
||||
void SendMaxLenEvent();
|
||||
bool GTKEntryOnInsertText(const char* text);
|
||||
bool GTKIsUpperCase() const { return m_isUpperCase; }
|
||||
|
||||
protected:
|
||||
// This method must be called from the derived class Create() to connect
|
||||
@ -85,7 +87,12 @@ private:
|
||||
|
||||
// implement this to return the associated GtkEntry
|
||||
virtual GtkEntry *GetEntry() const = 0;
|
||||
|
||||
bool m_isUpperCase;
|
||||
};
|
||||
|
||||
// We don't need the generic version.
|
||||
#define wxHAS_NATIVE_TEXT_FORCEUPPER
|
||||
|
||||
#endif // _WX_GTK_TEXTENTRY_H_
|
||||
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
virtual void SetEditable(bool editable);
|
||||
|
||||
virtual void SetMaxLength(unsigned long len);
|
||||
virtual void ForceUpper();
|
||||
|
||||
#if wxUSE_UXTHEME
|
||||
virtual bool SetHint(const wxString& hint);
|
||||
@ -98,5 +99,8 @@ private:
|
||||
#endif // wxUSE_OLE
|
||||
};
|
||||
|
||||
// We don't need the generic version.
|
||||
#define wxHAS_NATIVE_TEXT_FORCEUPPER
|
||||
|
||||
#endif // _WX_MSW_TEXTENTRY_H_
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "wx/combobox.h"
|
||||
#include "wx/osx/private.h"
|
||||
|
||||
@class wxTextEntryFormatter;
|
||||
|
||||
// implementation exposed, so that search control can pull it
|
||||
|
||||
class wxNSTextFieldControl : public wxWidgetCocoaImpl, public wxTextWidgetImpl
|
||||
@ -29,7 +31,10 @@ public :
|
||||
|
||||
virtual bool CanClipMaxLength() const { return true; }
|
||||
virtual void SetMaxLength(unsigned long len);
|
||||
|
||||
|
||||
virtual bool CanForceUpper() { return true; }
|
||||
virtual void ForceUpper();
|
||||
|
||||
virtual wxString GetStringValue() const ;
|
||||
virtual void SetStringValue( const wxString &str) ;
|
||||
virtual void Copy() ;
|
||||
@ -57,6 +62,9 @@ protected :
|
||||
private:
|
||||
// Common part of both ctors.
|
||||
void Init(WXWidget w);
|
||||
|
||||
// Get our formatter, creating it if necessary.
|
||||
wxTextEntryFormatter* GetFormatter();
|
||||
};
|
||||
|
||||
class wxNSTextViewControl : public wxWidgetCocoaImpl, public wxTextWidgetImpl
|
||||
|
@ -655,7 +655,10 @@ public :
|
||||
|
||||
virtual bool CanClipMaxLength() const { return false; }
|
||||
virtual void SetMaxLength(unsigned long WXUNUSED(len)) {}
|
||||
|
||||
|
||||
virtual bool CanForceUpper() { return false; }
|
||||
virtual void ForceUpper() {}
|
||||
|
||||
virtual bool GetStyle( long position, wxTextAttr& style);
|
||||
virtual void SetStyle( long start, long end, const wxTextAttr& style ) ;
|
||||
virtual void Copy() ;
|
||||
|
@ -50,6 +50,8 @@ public:
|
||||
// in a single line text control
|
||||
virtual void SetMaxLength(unsigned long len);
|
||||
|
||||
virtual void ForceUpper();
|
||||
|
||||
// writing text inserts it at the current position;
|
||||
// appending always inserts it at the end
|
||||
virtual void WriteText(const wxString& text);
|
||||
|
@ -138,10 +138,16 @@ public:
|
||||
virtual void SetEditable(bool editable) = 0;
|
||||
|
||||
|
||||
// input restrictions
|
||||
// ------------------
|
||||
|
||||
// set the max number of characters which may be entered in a single line
|
||||
// text control
|
||||
virtual void SetMaxLength(unsigned long WXUNUSED(len)) { }
|
||||
|
||||
// convert any lower-case characters to upper-case on the fly in this entry
|
||||
virtual void ForceUpper();
|
||||
|
||||
|
||||
// hints
|
||||
// -----
|
||||
@ -208,6 +214,10 @@ public:
|
||||
SuppressTextChangedEvents();
|
||||
}
|
||||
|
||||
// change the entry value to be in upper case only, if needed (i.e. if it's
|
||||
// not already the case)
|
||||
void ConvertToUpperCase();
|
||||
|
||||
protected:
|
||||
// flags for DoSetValue(): common part of SetValue() and ChangeValue() and
|
||||
// also used to implement WriteText() in wxMSW
|
||||
|
@ -212,6 +212,17 @@ public:
|
||||
*/
|
||||
virtual void Cut();
|
||||
|
||||
/**
|
||||
Convert all text entered into the control to upper case.
|
||||
|
||||
Call this method to ensure that all text entered into the control is
|
||||
converted on the fly to upper case. If the control is not empty, its
|
||||
existing contents is also converted to upper case.
|
||||
|
||||
@since 3.1.0
|
||||
*/
|
||||
void ForceUpper();
|
||||
|
||||
/**
|
||||
Returns the insertion point, or cursor, position.
|
||||
|
||||
|
@ -1093,6 +1093,10 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
|
||||
wxSize size2 = m_limited->GetSizeFromTextSize(m_limited->GetTextExtent("WWWWWWWW"));
|
||||
m_limited->SetSizeHints(size2, size2);
|
||||
|
||||
wxTextCtrl* upperOnly = new MyTextCtrl(this, wxID_ANY, "Only upper case",
|
||||
wxDefaultPosition, wxDefaultSize);
|
||||
upperOnly->ForceUpper();
|
||||
|
||||
// multi line text controls
|
||||
|
||||
wxString string3L("Read only\nMultiline\nFitted size");
|
||||
@ -1194,6 +1198,7 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
|
||||
column1->Add( m_password, 0, wxALL | wxEXPAND, 10 );
|
||||
column1->Add( m_readonly, 0, wxALL, 10 );
|
||||
column1->Add( m_limited, 0, wxALL, 10 );
|
||||
column1->Add( upperOnly, 0, wxALL, 10 );
|
||||
column1->Add( m_horizontal, 1, wxALL | wxEXPAND, 10 );
|
||||
|
||||
wxBoxSizer *column2 = new wxBoxSizer(wxVERTICAL);
|
||||
|
@ -310,6 +310,66 @@ bool wxTextEntryBase::CanPaste() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// input restrictions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef wxHAS_NATIVE_TEXT_FORCEUPPER
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Poor man's lambda: helper for binding ConvertToUpperCase() to the event
|
||||
struct ForceUpperFunctor
|
||||
{
|
||||
explicit ForceUpperFunctor(wxTextEntryBase* entry)
|
||||
: m_entry(entry)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(wxCommandEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
m_entry->ConvertToUpperCase();
|
||||
}
|
||||
|
||||
wxTextEntryBase* const m_entry;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#endif // !wxHAS_NATIVE_TEXT_FORCEUPPER
|
||||
|
||||
void wxTextEntryBase::ConvertToUpperCase()
|
||||
{
|
||||
const wxString& valueOld = GetValue();
|
||||
const wxString& valueNew = valueOld.Upper();
|
||||
|
||||
if ( valueNew != valueOld )
|
||||
{
|
||||
long from, to;
|
||||
GetSelection(&from, &to);
|
||||
ChangeValue(valueNew);
|
||||
SetSelection(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
void wxTextEntryBase::ForceUpper()
|
||||
{
|
||||
// Do nothing if this method is never called because a native override is
|
||||
// provided: this is just a tiny size-saving optimization, nothing else.
|
||||
#ifndef wxHAS_NATIVE_TEXT_FORCEUPPER
|
||||
wxWindow* const win = GetEditableWindow();
|
||||
wxCHECK_RET( win, wxS("can't be called before creating the window") );
|
||||
|
||||
// Convert the current control contents to upper case
|
||||
ConvertToUpperCase();
|
||||
|
||||
// And ensure that any text entered in the future is converted too
|
||||
win->Bind(wxEVT_TEXT, ForceUpperFunctor(this));
|
||||
#endif // !wxHAS_NATIVE_TEXT_FORCEUPPER
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// hints support
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "wx/gtk/private.h"
|
||||
#include "wx/gtk/private/gtk2-compat.h"
|
||||
#include "wx/gtk/private/string.h"
|
||||
|
||||
// ============================================================================
|
||||
// signal handlers implementation
|
||||
@ -43,8 +44,8 @@ extern "C"
|
||||
void
|
||||
wx_gtk_insert_text_callback(GtkEditable *editable,
|
||||
const gchar * new_text,
|
||||
gint WXUNUSED(new_text_length),
|
||||
gint * WXUNUSED(position),
|
||||
gint new_text_length,
|
||||
gint * position,
|
||||
wxTextEntry *text)
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (editable);
|
||||
@ -78,6 +79,40 @@ wx_gtk_insert_text_callback(GtkEditable *editable,
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have to convert all input to upper-case
|
||||
if ( !handled && text->GTKIsUpperCase() )
|
||||
{
|
||||
const wxGtkString upper(g_utf8_strup(new_text, new_text_length));
|
||||
|
||||
// Use the converted text to generate events
|
||||
if ( !text->GTKEntryOnInsertText(upper) )
|
||||
{
|
||||
// Event not handled, so do insert the text: we have to do it
|
||||
// ourselves to use the upper-case version of it
|
||||
|
||||
// Prevent recursive call to this handler again
|
||||
g_signal_handlers_block_by_func
|
||||
(
|
||||
editable,
|
||||
(gpointer)wx_gtk_insert_text_callback,
|
||||
text
|
||||
);
|
||||
|
||||
gtk_editable_insert_text(editable, upper, strlen(upper), position);
|
||||
|
||||
g_signal_handlers_unblock_by_func
|
||||
(
|
||||
editable,
|
||||
(gpointer)wx_gtk_insert_text_callback,
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
// Don't call the default handler in any case, either the event was
|
||||
// handled in the user code or we've already inserted the text.
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if ( !handled && text->GTKEntryOnInsertText(new_text) )
|
||||
{
|
||||
// If we already handled the new text insertion, don't do it again.
|
||||
@ -386,7 +421,7 @@ void wxTextEntry::SetEditable(bool editable)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// max text length
|
||||
// input restrictions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxTextEntry::SetMaxLength(unsigned long len)
|
||||
@ -411,6 +446,16 @@ void wxTextEntry::SendMaxLenEvent()
|
||||
win->HandleWindowEvent(event);
|
||||
}
|
||||
|
||||
void wxTextEntry::ForceUpper()
|
||||
{
|
||||
if ( !m_isUpperCase )
|
||||
{
|
||||
ConvertToUpperCase();
|
||||
|
||||
m_isUpperCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// IM handling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -898,7 +898,7 @@ void wxTextEntry::SetEditable(bool editable)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// max length
|
||||
// input restrictions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxTextEntry::SetMaxLength(unsigned long len)
|
||||
@ -913,6 +913,15 @@ void wxTextEntry::SetMaxLength(unsigned long len)
|
||||
::SendMessage(GetEditHwnd(), EM_LIMITTEXT, len, 0);
|
||||
}
|
||||
|
||||
void wxTextEntry::ForceUpper()
|
||||
{
|
||||
ConvertToUpperCase();
|
||||
|
||||
const HWND hwnd = GetEditHwnd();
|
||||
const LONG styleOld = ::GetWindowLong(hwnd, GWL_STYLE);
|
||||
::SetWindowLong(hwnd, GWL_STYLE, styleOld | ES_UPPERCASE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// hints
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -116,21 +116,23 @@ protected :
|
||||
|
||||
NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil;
|
||||
|
||||
// a minimal NSFormatter that just avoids getting too long entries
|
||||
@interface wxMaximumLengthFormatter : NSFormatter
|
||||
// an NSFormatter used to implement SetMaxLength() and ForceUpper() methods
|
||||
@interface wxTextEntryFormatter : NSFormatter
|
||||
{
|
||||
int maxLength;
|
||||
wxTextEntry* field;
|
||||
bool forceUpper;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation wxMaximumLengthFormatter
|
||||
@implementation wxTextEntryFormatter
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
maxLength = 0;
|
||||
forceUpper = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -139,6 +141,11 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil;
|
||||
maxLength = maxlen;
|
||||
}
|
||||
|
||||
- (void) forceUpper
|
||||
{
|
||||
forceUpper = true;
|
||||
}
|
||||
|
||||
- (NSString *)stringForObjectValue:(id)anObject
|
||||
{
|
||||
if(![anObject isKindOfClass:[NSString class]])
|
||||
@ -155,12 +162,25 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil;
|
||||
- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
|
||||
originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString **)error
|
||||
{
|
||||
int len = [*partialStringPtr length];
|
||||
if ( maxLength > 0 && len > maxLength )
|
||||
if ( maxLength > 0 )
|
||||
{
|
||||
field->SendMaxLenEvent();
|
||||
return NO;
|
||||
if ( [*partialStringPtr length] > maxLength )
|
||||
{
|
||||
field->SendMaxLenEvent();
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
if ( forceUpper )
|
||||
{
|
||||
NSString* upper = [*partialStringPtr uppercaseString];
|
||||
if ( ![*partialStringPtr isEqual:upper] )
|
||||
{
|
||||
*partialStringPtr = upper;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -869,12 +889,30 @@ void wxNSTextFieldControl::SetStringValue( const wxString &str)
|
||||
[m_textField setStringValue: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
|
||||
}
|
||||
|
||||
wxTextEntryFormatter* wxNSTextFieldControl::GetFormatter()
|
||||
{
|
||||
// We only ever call setFormatter with wxTextEntryFormatter, so the cast is
|
||||
// safe.
|
||||
wxTextEntryFormatter*
|
||||
formatter = (wxTextEntryFormatter*)[m_textField formatter];
|
||||
if ( !formatter )
|
||||
{
|
||||
formatter = [[[wxTextEntryFormatter alloc] init] autorelease];
|
||||
[formatter setTextEntry:GetTextEntry()];
|
||||
[m_textField setFormatter:formatter];
|
||||
}
|
||||
|
||||
return formatter;
|
||||
}
|
||||
|
||||
void wxNSTextFieldControl::SetMaxLength(unsigned long len)
|
||||
{
|
||||
wxMaximumLengthFormatter* formatter = [[[wxMaximumLengthFormatter alloc] init] autorelease];
|
||||
[formatter setMaxLength:len];
|
||||
[formatter setTextEntry:GetTextEntry()];
|
||||
[m_textField setFormatter:formatter];
|
||||
[GetFormatter() setMaxLength:len];
|
||||
}
|
||||
|
||||
void wxNSTextFieldControl::ForceUpper()
|
||||
{
|
||||
[GetFormatter() forceUpper];
|
||||
}
|
||||
|
||||
void wxNSTextFieldControl::Copy()
|
||||
|
@ -81,6 +81,23 @@ void wxTextEntry::SetMaxLength(unsigned long len)
|
||||
m_maxLength = len ;
|
||||
}
|
||||
|
||||
void wxTextEntry::ForceUpper()
|
||||
{
|
||||
wxTextWidgetImpl* const textPeer = GetTextPeer();
|
||||
|
||||
wxCHECK_RET( textPeer, "Must create the control first" );
|
||||
|
||||
if ( textPeer->CanForceUpper() )
|
||||
{
|
||||
ConvertToUpperCase();
|
||||
textPeer->ForceUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxTextEntryBase::ForceUpper();
|
||||
}
|
||||
}
|
||||
|
||||
// Clipboard operations
|
||||
|
||||
void wxTextEntry::Copy()
|
||||
|
Loading…
Reference in New Issue
Block a user