Added cFont::SelectSubStringFromCursor, cFont::GetCursorPos.

Added support for string selection, copy and paste for cUITextBox, cUITextInput
and cUITextEdit.
This commit is contained in:
Martín Lucas Golini
2013-12-18 02:49:39 -03:00
parent 725f29cf40
commit e7c1084f62
24 changed files with 485 additions and 164 deletions

View File

@@ -127,6 +127,12 @@ class EE_API cFont {
/** Finds the closest cursor position to the point position */
Int32 FindClosestCursorPosFromPoint( const String & Text, const eeVector2i& pos );
/** Simulates a selection request and return the initial and end cursor position when the selection worked. Otherwise both parameters will be -1. */
void SelectSubStringFromCursor( const String& Text, const Int32& CurPos, Int32& InitCur, Int32& EndCur );
/** @return The cursor position inside the string */
eeVector2i GetCursorPos( const String& Text, const Uint32& Pos );
protected:
Uint32 mType;
std::string mFontName;

View File

@@ -13,7 +13,8 @@ class EE_API cUITextBox : public cUIComplexControl {
cUIComplexControl::CreateParams(),
Font( NULL ),
FontColor( 0, 0, 0, 255 ),
FontShadowColor( 255, 255, 255, 150 )
FontShadowColor( 255, 255, 255, 150 ),
FontSelectionBackColor( 150, 150, 150, 150 )
{
cUITheme * Theme = cUIThemeManager::instance()->DefaultTheme();
@@ -32,6 +33,7 @@ class EE_API cUITextBox : public cUIComplexControl {
cFont * Font;
eeColorA FontColor;
eeColorA FontShadowColor;
eeColorA FontSelectionBackColor;
};
cUITextBox( const cUITextBox::CreateParams& Params );
@@ -62,6 +64,10 @@ class EE_API cUITextBox : public cUIComplexControl {
void ShadowColor( const eeColorA& color );
const eeColorA& SelectionBackColor() const;
void SelectionBackColor( const eeColorA& color );
virtual void OnTextChanged();
virtual void OnFontChanged();
@@ -83,13 +89,20 @@ class EE_API cUITextBox : public cUIComplexControl {
const eeVector2f& AlignOffset() const;
virtual void ShrinkText( const Uint32& MaxWidth );
bool IsTextSelectionEnabled() const;
protected:
cTextCache * mTextCache;
String mString;
eeColorA mFontColor;
eeColorA mFontShadowColor;
eeColorA mFontSelectionBackColor;
eeVector2f mAlignOffset;
eeRecti mPadding;
Int32 mSelCurInit;
Int32 mSelCurEnd;
virtual void DrawSelection();
virtual void OnSizeChange();
@@ -98,6 +111,17 @@ class EE_API cUITextBox : public cUIComplexControl {
virtual void AutoSize();
virtual void AutoAlign();
virtual Uint32 OnFocusLoss();
virtual Uint32 OnMouseDoubleClick( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnMouseClick( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnMouseDown( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnKeyDown( const cUIEventKey &Event );
};
}}

View File

@@ -73,8 +73,14 @@ class EE_API cUITextInput : public cUITextBox {
virtual Uint32 OnMouseClick( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnMouseDoubleClick( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnMouseExit( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnMouseDown( const eeVector2i& Pos, const Uint32 Flags );
virtual Uint32 OnKeyDown( const cUIEventKey &Event );
virtual Uint32 OnFocus();
virtual Uint32 OnFocusLoss();

View File

@@ -112,11 +112,11 @@ class EE_API cUITheme : protected tResourceManager<cUISkin> {
virtual cUITextBox * CreateTextBox( const String& Text = "", cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_SIZE );
virtual cUITextEdit * CreateTextEdit( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_PADDING | UI_CLIP_ENABLE | UI_AUTO_SIZE, UI_SCROLLBAR_MODE HScrollBar = UI_SCROLLBAR_AUTO, UI_SCROLLBAR_MODE VScrollBar = UI_SCROLLBAR_AUTO, bool WordWrap = true );
virtual cUITextEdit * CreateTextEdit( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_AUTO_PADDING | UI_CLIP_ENABLE | UI_AUTO_SIZE | UI_TEXT_SELECTION_ENABLED, UI_SCROLLBAR_MODE HScrollBar = UI_SCROLLBAR_AUTO, UI_SCROLLBAR_MODE VScrollBar = UI_SCROLLBAR_AUTO, bool WordWrap = true );
virtual cUITextInput * CreateTextInput( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING, bool SupportFreeEditing = true, Uint32 MaxLength = 256 );
virtual cUITextInput * CreateTextInput( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_TEXT_SELECTION_ENABLED, bool SupportFreeEditing = true, Uint32 MaxLength = 256 );
virtual cUITextInputPassword * CreateTextInputPassword( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING, bool SupportFreeEditing = true, Uint32 MaxLength = 256 );
virtual cUITextInputPassword * CreateTextInputPassword( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_TEXT_SELECTION_ENABLED, bool SupportFreeEditing = true, Uint32 MaxLength = 256 );
virtual cUITooltip * CreateTooltip( cUIControl * TooltipOf, cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS_CENTERED | UI_AUTO_PADDING | UI_AUTO_SIZE );
@@ -124,9 +124,9 @@ class EE_API cUITheme : protected tResourceManager<cUISkin> {
virtual cUISlider * CreateSlider( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS, bool VerticalSlider = false, bool AllowHalfSliderOut = true, bool ExpandBackground = false );
virtual cUISpinBox * CreateSpinBox( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_SIZE, eeFloat DefaultValue = 0.f, bool AllowDotsInNumbers = true );
virtual cUISpinBox * CreateSpinBox( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_SIZE | UI_TEXT_SELECTION_ENABLED, eeFloat DefaultValue = 0.f, bool AllowDotsInNumbers = true );
virtual cUIComboBox * CreateComboBox( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING, Uint32 MinNumVisibleItems = 6, bool PopUpToMainControl = false, cUIListBox * ListBox = NULL );
virtual cUIComboBox * CreateComboBox( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_TEXT_SELECTION_ENABLED, Uint32 MinNumVisibleItems = 6, bool PopUpToMainControl = false, cUIListBox * ListBox = NULL );
virtual cUIDropDownList * CreateDropDownList( cUIControl * Parent = NULL, const eeSize& Size = eeSize(), const eeVector2i& Pos = eeVector2i(), const Uint32& Flags = UI_CONTROL_DEFAULT_FLAGS | UI_CLIP_ENABLE | UI_AUTO_PADDING, Uint32 MinNumVisibleItems = 6, bool PopUpToMainControl = false, cUIListBox * ListBox = NULL );

View File

@@ -20,6 +20,7 @@ enum UI_CONTROL_FLAGS_VALUES {
UI_CTRL_FLAG_SKIN_OWNER = (1<<11),
UI_CTRL_FLAG_TOUCH_DRAGGING = (1<<12),
UI_CTRL_FLAG_DISABLED_BY_MODAL_WINDOW = (1<<13),
UI_CTRL_FLAG_SELECTING = (1<<14),
UI_CTRL_FLAG_FREE_USE = (1<<31)
};
@@ -60,7 +61,8 @@ enum UI_FLAGS {
UI_ANCHOR_LEFT = (1 << 21),
UI_ANCHOR_RIGHT = (1 << 22),
UI_AUTO_FIT = (1 << 23),
UI_TOUCH_DRAG_ENABLED = (1 << 24)
UI_TOUCH_DRAG_ENABLED = (1 << 24),
UI_TEXT_SELECTION_ENABLED = (1 << 25)
};
enum UI_CONTROL_TYPES {

View File

@@ -380,6 +380,15 @@ Int32 cFont::FindClosestCursorPosFromPoint( const String& Text, const eeVector2i
}
if ( pos.x <= Width && pos.x >= lWidth && pos.y <= Height && pos.y >= lHeight ) {
if ( i + 1 < tSize ) {
Int32 curDist = eeabs( pos.x - lWidth );
Int32 nextDist = eeabs( pos.x - ( lWidth + mGlyphs[CharID].Advance ) );
if ( nextDist < curDist ) {
return i + 1;
}
}
return i;
}
@@ -401,6 +410,71 @@ Int32 cFont::FindClosestCursorPosFromPoint( const String& Text, const eeVector2i
return -1;
}
eeVector2i cFont::GetCursorPos( const String& Text, const Uint32& Pos ) {
eeFloat Width = 0, Height = GetFontHeight();
Int32 CharID;
Int32 tGlyphSize = mGlyphs.size();
std::size_t tSize = ( Pos < Text.size() ) ? Pos : Text.size();
for (std::size_t i = 0; i < tSize; ++i) {
CharID = static_cast<Int32>( Text.at(i) );
if ( CharID >= 0 && CharID < tGlyphSize ) {
Width += mGlyphs[CharID].Advance;
if ( CharID == '\t' ) {
Width += mGlyphs[CharID].Advance * 3;
}
if ( CharID == '\n' ) {
Width = 0;
Height += GetFontHeight();
}
}
}
return eeVector2i( Width, Height );
}
static bool IsStopSelChar( Uint32 c ) {
return ( !String::IsCharacter( c ) && !String::IsNumber( c ) ) ||
' ' == c ||
'.' == c ||
',' == c ||
';' == c ||
':' == c ||
'\n' == c ||
'"' == c ||
'\'' == c;
}
void cFont::SelectSubStringFromCursor( const String& Text, const Int32& CurPos, Int32& InitCur, Int32& EndCur ) {
InitCur = 0;
EndCur = Text.size();
for ( std::size_t i = CurPos; i < Text.size(); i++ ) {
if ( IsStopSelChar( Text[i] ) ) {
EndCur = i;
break;
}
}
if ( 0 == CurPos ) {
InitCur = 0;
}
for ( Int32 i = CurPos; i >= 0; i-- ) {
if ( IsStopSelChar( Text[i] ) ) {
InitCur = i + 1;
break;
}
}
if ( InitCur == EndCur ) {
InitCur = EndCur = -1;
}
}
void cFont::CacheWidth() {
mTextCache.Cache();
}

View File

@@ -7,6 +7,9 @@ namespace HaikuTTF {
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
class hkMutexImpl {

View File

@@ -8,7 +8,10 @@
#if defined( EE_COMPILER_MSVC )
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#endif

View File

@@ -9,6 +9,9 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#endif

View File

@@ -8,17 +8,11 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
//Get around Windows hackery
#ifdef max
# undef max
#endif
#ifdef min
# undef min
#endif
#include <ctime>
namespace EE { namespace System { namespace Platform {

View File

@@ -8,6 +8,9 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
namespace EE { namespace System { namespace Platform {

View File

@@ -6,6 +6,12 @@
#if EE_PLATFORM == EE_PLATFORM_WIN
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
namespace EE { namespace System { namespace Private {

View File

@@ -27,6 +27,9 @@
#if EE_PLATFORM == EE_PLATFORM_MACOSX
#include <CoreFoundation/CoreFoundation.h>
#elif EE_PLATFORM == EE_PLATFORM_WIN
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#undef GetDiskFreeSpace
#undef GetTempPath
@@ -145,6 +148,14 @@ static std::string GetWindowsVersion() {
os += "Windows Server 2012";
}
}
if ( osvi.dwMinorVersion == 3 ) {
if( osvi.wProductType == VER_NT_WORKSTATION ) {
os += "Windows 8.1";
} else {
os += "Windows Server 2012 R2";
}
}
}
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) {

View File

@@ -66,7 +66,7 @@ cUICommonDialog::cUICommonDialog( const cUICommonDialog::CreateParams& Params )
cUITextInput::CreateParams TInputParams;
TInputParams.Parent( Container() );
TInputParams.Flags = UI_AUTO_PADDING | UI_CLIP_ENABLE | UI_ANCHOR_RIGHT | UI_ANCHOR_LEFT | UI_ANCHOR_TOP | UI_VALIGN_CENTER;
TInputParams.Flags = UI_AUTO_PADDING | UI_CLIP_ENABLE | UI_ANCHOR_RIGHT | UI_ANCHOR_LEFT | UI_ANCHOR_TOP | UI_VALIGN_CENTER | UI_TEXT_SELECTION_ENABLED;
TInputParams.PosSet( 70, 6 );
TInputParams.SizeSet( Container()->Size().Width() - TInputParams.Pos.x - 42, 22 );
mPath = eeNew( cUITextInput, ( TInputParams ) );

View File

@@ -162,7 +162,7 @@ cUIComboBox * cUIDefaultTheme::CreateComboBox( cUIControl * Parent, const eeSize
ComboParams.ListBox = ListBox;
if ( UseDefaultThemeValues() ) {
ComboParams.Flags |= UI_AUTO_SIZE;
ComboParams.Flags |= UI_AUTO_SIZE | UI_TEXT_SELECTION_ENABLED;
}
cUIComboBox * Ctrl = eeNew( cUIComboBox, ( ComboParams ) );

View File

@@ -19,6 +19,9 @@ cUIDropDownList::cUIDropDownList( cUIDropDownList::CreateParams& Params ) :
if ( Params.Flags & UI_TOUCH_DRAG_ENABLED )
flags |= UI_TOUCH_DRAG_ENABLED;
if ( Params.Flags & UI_TEXT_SELECTION_ENABLED )
flags |= UI_TEXT_SELECTION_ENABLED;
cUITheme * Theme = cUIThemeManager::instance()->DefaultTheme();
if ( NULL != Theme ) {

View File

@@ -17,6 +17,9 @@ cUISpinBox::cUISpinBox( const cUISpinBox::CreateParams& Params ) :
if ( InputParams.Flags & UI_AUTO_SIZE )
InputParams.Flags &= ~UI_AUTO_SIZE;
if ( InputParams.Flags & UI_TEXT_SELECTION_ENABLED )
InputParams.Flags |= UI_TEXT_SELECTION_ENABLED;
InputParams.Flags |= UI_AUTO_PADDING;
mInput = eeNew( cUITextInput, ( InputParams ) );

View File

@@ -3,6 +3,8 @@
#include <eepp/ui/cuithememanager.hpp>
#include <eepp/graphics/ctextcache.hpp>
#include <eepp/graphics/cfont.hpp>
#include <eepp/graphics/cprimitives.hpp>
#include <eepp/window/cclipboard.hpp>
namespace EE { namespace UI {
@@ -10,7 +12,10 @@ cUITextBox::cUITextBox( const cUITextBox::CreateParams& Params ) :
cUIComplexControl( Params ),
mFontColor( Params.FontColor ),
mFontShadowColor( Params.FontShadowColor ),
mAlignOffset( 0.f, 0.f )
mFontSelectionBackColor( Params.FontSelectionBackColor ),
mAlignOffset( 0.f, 0.f ),
mSelCurInit( -1 ),
mSelCurEnd( -1 )
{
mTextCache = eeNew( cTextCache, () );
mTextCache->Font( Params.Font );
@@ -43,6 +48,8 @@ void cUITextBox::Draw() {
if ( mVisible && 0.f != mAlpha ) {
cUIControlAnim::Draw();
DrawSelection();
if ( mTextCache->GetTextWidth() ) {
if ( mFlags & UI_CLIP_ENABLE ) {
cUIManager::instance()->ClipEnable(
@@ -118,6 +125,14 @@ void cUITextBox::ShadowColor( const eeColorA& color ) {
mTextCache->ShadowColor( mFontColor );
}
const eeColorA& cUITextBox::SelectionBackColor() const {
return mFontSelectionBackColor;
}
void cUITextBox::SelectionBackColor( const eeColorA& color ) {
mFontSelectionBackColor = color;
}
void cUITextBox::Alpha( const eeFloat& alpha ) {
cUIControlAnim::Alpha( alpha );
mFontColor.Alpha = (Uint8)alpha;
@@ -173,6 +188,11 @@ void cUITextBox::AutoAlign() {
}
}
Uint32 cUITextBox::OnFocusLoss() {
mSelCurInit = mSelCurEnd = -1;
return 1;
}
void cUITextBox::OnSizeChange() {
AutoShrink();
AutoSize();
@@ -227,4 +247,110 @@ const eeVector2f& cUITextBox::AlignOffset() const {
return mAlignOffset;
}
Uint32 cUITextBox::OnMouseDoubleClick( const eeVector2i& Pos, const Uint32 Flags ) {
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) ) {
eeVector2i controlPos( Pos );
WorldToControl( controlPos );
Int32 curPos = mTextCache->Font()->FindClosestCursorPosFromPoint( mTextCache->Text(), controlPos );
if ( -1 != curPos ) {
mTextCache->Font()->SelectSubStringFromCursor( mTextCache->Text(), curPos, mSelCurInit, mSelCurEnd );
mControlFlags &= ~UI_CTRL_FLAG_SELECTING;
}
}
return cUIComplexControl::OnMouseDoubleClick( Pos, Flags );
}
Uint32 cUITextBox::OnMouseClick( const eeVector2i& Pos, const Uint32 Flags ) {
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) ) {
if ( mSelCurInit == mSelCurEnd ) {
mSelCurInit = mSelCurEnd = -1;
}
mControlFlags &= ~UI_CTRL_FLAG_SELECTING;
}
return 1;
}
Uint32 cUITextBox::OnMouseDown( const eeVector2i& Pos, const Uint32 Flags ) {
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) ) {
eeVector2i controlPos( Pos );
WorldToControl( controlPos );
Int32 curPos = mTextCache->Font()->FindClosestCursorPosFromPoint( mTextCache->Text(), controlPos );
if ( -1 != curPos ) {
if ( -1 == mSelCurInit || !( mControlFlags & UI_CTRL_FLAG_SELECTING ) ) {
mSelCurInit = curPos;
mSelCurEnd = curPos;
} else {
mSelCurEnd = curPos;
}
}
mControlFlags |= UI_CTRL_FLAG_SELECTING;
}
return cUIComplexControl::OnMouseDown( Pos, Flags );
}
Uint32 cUITextBox::OnKeyDown( const cUIEventKey & Event ) {
if ( IsTextSelectionEnabled() ) {
if ( ( Event.Mod() & KEYMOD_LCTRL ) && Event.KeyCode() == KEY_A ) {
mSelCurInit = 0;
mSelCurEnd = mTextCache->Text().size();
} else if ( mSelCurInit >= 0 && mSelCurInit != mSelCurEnd ) {
if ( ( Event.Mod() & KEYMOD_LCTRL ) && ( Event.KeyCode() == KEY_C || Event.KeyCode() == KEY_X ) ) {
Int32 init = eemin( mSelCurInit, mSelCurEnd );
Int32 end = eemax( mSelCurInit, mSelCurEnd );
std::string clipStr( mTextCache->Text().substr( init, end - init ).ToUtf8() );
cUIManager::instance()->GetWindow()->GetClipboard()->SetText( clipStr );
} else if ( !String::IsCharacter( Event.KeyCode() ) ) {
mSelCurInit = mSelCurEnd = -1;
}
}
}
return 1;
}
void cUITextBox::DrawSelection() {
if ( IsTextSelectionEnabled() && mSelCurInit != mSelCurEnd ) {
Int32 init = eemin( mSelCurInit, mSelCurEnd );
Int32 end = eemax( mSelCurInit, mSelCurEnd );
Int32 lastEnd = end;
eeVector2i initPos, endPos;
cPrimitives P;
P.SetColor( mFontSelectionBackColor );
do {
initPos = mTextCache->Font()->GetCursorPos( mTextCache->Text(), init );
lastEnd = mTextCache->Text().find_first_of( '\n', init );
if ( lastEnd < end && -1 != lastEnd ) {
endPos = mTextCache->Font()->GetCursorPos( mTextCache->Text(), lastEnd );
init = lastEnd + 1;
} else {
endPos = mTextCache->Font()->GetCursorPos( mTextCache->Text(), end );
lastEnd = end;
}
P.DrawRectangle( eeRectf( mScreenPos.x + initPos.x + mAlignOffset.x + mPadding.Left,
mScreenPos.y + initPos.y - mTextCache->Font()->GetFontHeight() + mAlignOffset.y + mPadding.Top,
mScreenPos.x + endPos.x + mAlignOffset.x + mPadding.Left,
mScreenPos.y + endPos.y + mAlignOffset.y + mPadding.Top )
);
} while ( end != lastEnd );
}
}
bool cUITextBox::IsTextSelectionEnabled() const {
return 0 != ( mFlags & UI_TEXT_SELECTION_ENABLED );
}
}}

View File

@@ -31,7 +31,7 @@ cUITextEdit::cUITextEdit( cUITextEdit::CreateParams& Params ) :
cUITextInput::CreateParams TIParams;
TIParams.Parent( this );
TIParams.Size = mSize;
TIParams.Flags = UI_VALIGN_TOP | UI_HALIGN_LEFT | extraFlags;
TIParams.Flags = UI_VALIGN_TOP | UI_HALIGN_LEFT | UI_TEXT_SELECTION_ENABLED | extraFlags;
TIParams.MaxLength = 1024 * 1024 * 10;
TIParams.Font = Params.Font;
TIParams.FontColor = Params.FontColor;

View File

@@ -124,10 +124,7 @@ Uint32 cUITextInput::OnFocus() {
Uint32 cUITextInput::OnFocusLoss() {
mTextBuffer.Active( false );
cUITextBox::OnFocusLoss();
return 1;
return cUITextBox::OnFocusLoss();
}
Uint32 cUITextInput::OnPressEnter() {
@@ -238,15 +235,35 @@ Uint32 cUITextInput::OnMouseClick( const eeVector2i& Pos, const Uint32 Flags ) {
if ( -1 != curPos ) {
mTextBuffer.CurPos( curPos );
mShowingWait = true;
mWaitCursorTime = 0.f;
ResetWaitCursor();
}
}
return cUITextBox::OnMouseClick( Pos, Flags );
}
Uint32 cUITextInput::OnMouseDoubleClick( const eeVector2i& Pos, const Uint32 Flags ) {
cUITextBox::OnMouseDoubleClick( Pos, Flags );
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) && mSelCurEnd != -1 ) {
mTextBuffer.CurPos( mSelCurEnd );
ResetWaitCursor();
}
return 1;
}
Uint32 cUITextInput::OnMouseDown( const eeVector2i& Pos, const Uint32 Flags ) {
cUITextBox::OnMouseDown( Pos, Flags );
if ( IsTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) && mSelCurEnd != -1 ) {
mTextBuffer.CurPos( mSelCurEnd );
ResetWaitCursor();
}
return 1;
}
Uint32 cUITextInput::OnMouseExit( const eeVector2i& Pos, const Uint32 Flags ) {
cUIControl::OnMouseExit( Pos, Flags );
@@ -255,4 +272,33 @@ Uint32 cUITextInput::OnMouseExit( const eeVector2i& Pos, const Uint32 Flags ) {
return 1;
}
Uint32 cUITextInput::OnKeyDown( const cUIEventKey & Event ) {
cUITextBox::OnKeyDown( Event );
if ( IsTextSelectionEnabled() ) {
if ( ( Event.Mod() & KEYMOD_LCTRL ) && Event.KeyCode() == KEY_A && 0 == mSelCurInit && (Int32)mTextCache->Text().size() == mSelCurEnd ) {
mTextBuffer.CurPos( mSelCurEnd );
ResetWaitCursor();
}
if ( mSelCurInit >= 0 && mSelCurInit != mSelCurEnd ) {
if ( ( ( Event.Mod() & KEYMOD_LCTRL ) && ( Event.KeyCode() == KEY_X || Event.KeyCode() == KEY_V ) ) ) {
Int32 init = eemin( mSelCurInit, mSelCurEnd );
Int32 end = eemax( mSelCurInit, mSelCurEnd );
String iniStr( mTextCache->Text().substr( 0, init ) );
String endStr( mTextCache->Text().substr( end ) );
Text( iniStr + endStr );
mTextBuffer.CurPos( mSelCurInit );
ResetWaitCursor();
mSelCurInit = mSelCurEnd = -1;
}
}
}
return 1;
}
}}

View File

@@ -23,6 +23,9 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#elif defined( EE_X11_PLATFORM )
#include <X11/Xlib.h>

View File

@@ -2,6 +2,9 @@
#if EE_PLATFORM == EE_PLATFORM_WIN
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <eepp/window/platform/win/cwinimpl.hpp>
@@ -13,204 +16,203 @@ namespace EE { namespace Window { namespace Platform {
cCursorWin::cCursorWin( cTexture * tex, const eeVector2i& hotspot, const std::string& name, cWindow * window ) :
cCursor( tex, hotspot, name, window )
{
Create();
Create();
}
cCursorWin::cCursorWin( cImage * img, const eeVector2i& hotspot, const std::string& name, cWindow * window ) :
cCursor( img, hotspot, name, window )
{
Create();
Create();
}
cCursorWin::cCursorWin( const std::string& path, const eeVector2i& hotspot, const std::string& name, cWindow * window ) :
cCursor( path, hotspot, name, window )
{
Create();
Create();
}
cCursorWin::~cCursorWin() {
if ( NULL != mCursor )
if ( NULL != mCursor )
DestroyIcon( (HCURSOR)mCursor );
}
static BITMAPINFO *get_bitmap_info( cImage * bitmap ) {
BITMAPINFO *bi;
int i;
BITMAPINFO *bi;
int i;
bi = (BITMAPINFO *) eeMalloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256);
bi = (BITMAPINFO *) eeMalloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256);
ZeroMemory(&bi->bmiHeader, sizeof(BITMAPINFOHEADER));
ZeroMemory(&bi->bmiHeader, sizeof(BITMAPINFOHEADER));
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biBitCount = 32;
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biWidth = (int)bitmap->Width();
bi->bmiHeader.biHeight = -((int)bitmap->Height());
bi->bmiHeader.biClrUsed = 256;
bi->bmiHeader.biCompression = BI_RGB;
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biBitCount = 32;
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biWidth = (int)bitmap->Width();
bi->bmiHeader.biHeight = -((int)bitmap->Height());
bi->bmiHeader.biClrUsed = 256;
bi->bmiHeader.biCompression = BI_RGB;
for (i = 0; i < 256; i++) {
bi->bmiColors[i].rgbRed = 0;
bi->bmiColors[i].rgbGreen = 0;
bi->bmiColors[i].rgbBlue = 0;
bi->bmiColors[i].rgbReserved = 0;
}
for (i = 0; i < 256; i++) {
bi->bmiColors[i].rgbRed = 0;
bi->bmiColors[i].rgbGreen = 0;
bi->bmiColors[i].rgbBlue = 0;
bi->bmiColors[i].rgbReserved = 0;
}
return bi;
return bi;
}
static BYTE *get_dib_from_bitmap_32(cImage *bitmap) {
int w, h;
int x, y;
int pitch;
BYTE *pixels;
BYTE *dst;
int w, h;
int x, y;
int pitch;
BYTE *pixels;
BYTE *dst;
w = (int)bitmap->Width();
h = (int)bitmap->Height();
pitch = w * 4;
w = (int)bitmap->Width();
h = (int)bitmap->Height();
pitch = w * 4;
pixels = (BYTE *) eeMalloc(h * pitch);
if (!pixels)
return NULL;
pixels = (BYTE *) eeMalloc(h * pitch);
if (!pixels)
return NULL;
for (y = 0; y < h; y++) {
dst = pixels + y * pitch;
for (y = 0; y < h; y++) {
dst = pixels + y * pitch;
for (x = 0; x < w; x++) {
eeColorA C = bitmap->GetPixel( x, y );
for (x = 0; x < w; x++) {
eeColorA C = bitmap->GetPixel( x, y );
/* BGR */
dst[0] = C.B();
dst[1] = C.G();
dst[2] = C.R();
dst[3] = C.A();
/* BGR */
dst[0] = C.B();
dst[1] = C.G();
dst[2] = C.R();
dst[3] = C.A();
dst += 4;
}
}
dst += 4;
}
}
return pixels;
return pixels;
}
static void local_stretch_blit_to_hdc( cImage *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h) {
const int bitmap_h = (const int)bitmap->Height();
const int bottom_up_src_y = bitmap_h - src_y - src_h;
BYTE *pixels;
BITMAPINFO *bi;
const int bitmap_h = (const int)bitmap->Height();
const int bottom_up_src_y = bitmap_h - src_y - src_h;
BYTE *pixels;
BITMAPINFO *bi;
bi = get_bitmap_info(bitmap);
pixels = get_dib_from_bitmap_32(bitmap);
bi = get_bitmap_info(bitmap);
pixels = get_dib_from_bitmap_32(bitmap);
/* Windows treats all source bitmaps as bottom-up when using StretchDIBits
* unless the source (x,y) is (0,0). To work around this buggy behavior, we
* can use negative heights to reverse the direction of the blits.
*
* See <http://wiki.allegro.cc/StretchDIBits> for a detailed explanation.
*/
if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) {
StretchDIBits( dc, dest_x, dest_h+dest_y-1, dest_w, -dest_h, src_x, bitmap_h - src_y + 1, src_w, -src_h, pixels, bi, DIB_RGB_COLORS, SRCCOPY );
}
else {
StretchDIBits( dc, dest_x, dest_y, dest_w, dest_h, src_x, bottom_up_src_y, src_w, src_h, pixels, bi, DIB_RGB_COLORS, SRCCOPY );
}
/* Windows treats all source bitmaps as bottom-up when using StretchDIBits
* unless the source (x,y) is (0,0). To work around this buggy behavior, we
* can use negative heights to reverse the direction of the blits.
*
* See <http://wiki.allegro.cc/StretchDIBits> for a detailed explanation.
*/
if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) {
StretchDIBits( dc, dest_x, dest_h+dest_y-1, dest_w, -dest_h, src_x, bitmap_h - src_y + 1, src_w, -src_h, pixels, bi, DIB_RGB_COLORS, SRCCOPY );
} else {
StretchDIBits( dc, dest_x, dest_y, dest_w, dest_h, src_x, bottom_up_src_y, src_w, src_h, pixels, bi, DIB_RGB_COLORS, SRCCOPY );
}
eeFree(pixels);
eeFree(bi);
eeFree(pixels);
eeFree(bi);
}
static void local_draw_to_hdc( HDC dc, cImage * bitmap, int x, int y ) {
int w = bitmap->Width();
int h = bitmap->Height();
local_stretch_blit_to_hdc(bitmap, dc, 0, 0, w, h, x, y, w, h);
int w = bitmap->Width();
int h = bitmap->Height();
local_stretch_blit_to_hdc(bitmap, dc, 0, 0, w, h, x, y, w, h);
}
void cCursorWin::Create() {
if ( NULL == mImage && mImage->MemSize() )
return;
int x, y;
int sys_sm_cx, sys_sm_cy;
HDC h_dc;
HDC h_and_dc;
HDC h_xor_dc;
ICONINFO iconinfo;
HBITMAP and_mask;
HBITMAP xor_mask;
HBITMAP hOldAndMaskBitmap;
HBITMAP hOldXorMaskBitmap;
HICON icon;
int x, y;
int sys_sm_cx, sys_sm_cy;
HDC h_dc;
HDC h_and_dc;
HDC h_xor_dc;
ICONINFO iconinfo;
HBITMAP and_mask;
HBITMAP xor_mask;
HBITMAP hOldAndMaskBitmap;
HBITMAP hOldXorMaskBitmap;
HICON icon;
/* Get allowed cursor size - Windows can't make cursors of arbitrary size */
sys_sm_cx = GetSystemMetrics(SM_CXCURSOR);
sys_sm_cy = GetSystemMetrics(SM_CYCURSOR);
/* Get allowed cursor size - Windows can't make cursors of arbitrary size */
sys_sm_cx = GetSystemMetrics(SM_CXCURSOR);
sys_sm_cy = GetSystemMetrics(SM_CYCURSOR);
if ( ( (int)mImage->Width() > sys_sm_cx ) || ( (int)mImage->Height() > sys_sm_cy ) ) {
return;
}
if ( ( (int)mImage->Width() > sys_sm_cx ) || ( (int)mImage->Height() > sys_sm_cy ) ) {
return;
}
/* Create bitmap */
h_dc = GetDC( GetPlatform()->GetHandler() );
h_xor_dc = CreateCompatibleDC(h_dc);
h_and_dc = CreateCompatibleDC(h_dc);
/* Create bitmap */
h_dc = GetDC( GetPlatform()->GetHandler() );
h_xor_dc = CreateCompatibleDC(h_dc);
h_and_dc = CreateCompatibleDC(h_dc);
/* Prepare AND (monochrome) and XOR (colour) mask */
and_mask = CreateBitmap(sys_sm_cx, sys_sm_cy, 1, 1, NULL);
xor_mask = CreateCompatibleBitmap(h_dc, sys_sm_cx, sys_sm_cy);
hOldAndMaskBitmap = (HBITMAP) SelectObject(h_and_dc, and_mask);
hOldXorMaskBitmap = (HBITMAP) SelectObject(h_xor_dc, xor_mask);
/* Prepare AND (monochrome) and XOR (colour) mask */
and_mask = CreateBitmap(sys_sm_cx, sys_sm_cy, 1, 1, NULL);
xor_mask = CreateCompatibleBitmap(h_dc, sys_sm_cx, sys_sm_cy);
hOldAndMaskBitmap = (HBITMAP) SelectObject(h_and_dc, and_mask);
hOldXorMaskBitmap = (HBITMAP) SelectObject(h_xor_dc, xor_mask);
/* Create transparent cursor */
for (y = 0; y < sys_sm_cy; y++) {
for (x = 0; x < sys_sm_cx; x++) {
SetPixel(h_and_dc, x, y, WINDOWS_RGB(255, 255, 255));
SetPixel(h_xor_dc, x, y, WINDOWS_RGB(0, 0, 0));
}
}
/* Create transparent cursor */
for (y = 0; y < sys_sm_cy; y++) {
for (x = 0; x < sys_sm_cx; x++) {
SetPixel(h_and_dc, x, y, WINDOWS_RGB(255, 255, 255));
SetPixel(h_xor_dc, x, y, WINDOWS_RGB(0, 0, 0));
}
}
local_draw_to_hdc( h_xor_dc, mImage, 0, 0 );
local_draw_to_hdc( h_xor_dc, mImage, 0, 0 );
/* Make cursor background transparent */
for (y = 0; y < (int)mImage->Height(); y++) {
for (x = 0; x < (int)mImage->Width(); x++) {
eeColorA C = mImage->GetPixel( x, y );
/* Make cursor background transparent */
for (y = 0; y < (int)mImage->Height(); y++) {
for (x = 0; x < (int)mImage->Width(); x++) {
eeColorA C = mImage->GetPixel( x, y );
if ( C.A() != 0 ) {
/* Don't touch XOR value */
SetPixel( h_and_dc, x, y, 0 );
} else {
/* No need to touch AND value */
SetPixel( h_xor_dc, x, y, WINDOWS_RGB( 0, 0, 0 ) );
}
}
}
if ( C.A() != 0 ) {
/* Don't touch XOR value */
SetPixel( h_and_dc, x, y, 0 );
} else {
/* No need to touch AND value */
SetPixel( h_xor_dc, x, y, WINDOWS_RGB( 0, 0, 0 ) );
}
}
}
SelectObject(h_and_dc, hOldAndMaskBitmap);
SelectObject(h_xor_dc, hOldXorMaskBitmap);
DeleteDC(h_and_dc);
DeleteDC(h_xor_dc);
ReleaseDC( GetPlatform()->GetHandler() , h_dc );
SelectObject(h_and_dc, hOldAndMaskBitmap);
SelectObject(h_xor_dc, hOldXorMaskBitmap);
DeleteDC(h_and_dc);
DeleteDC(h_xor_dc);
ReleaseDC( GetPlatform()->GetHandler() , h_dc );
iconinfo.fIcon = false;
iconinfo.xHotspot = mHotSpot.x;
iconinfo.yHotspot = mHotSpot.y;
iconinfo.hbmMask = and_mask;
iconinfo.hbmColor = xor_mask;
iconinfo.fIcon = false;
iconinfo.xHotspot = mHotSpot.x;
iconinfo.yHotspot = mHotSpot.y;
iconinfo.hbmMask = and_mask;
iconinfo.hbmColor = xor_mask;
icon = CreateIconIndirect(&iconinfo);
icon = CreateIconIndirect(&iconinfo);
DeleteObject(and_mask);
DeleteObject(xor_mask);
DeleteObject(and_mask);
DeleteObject(xor_mask);
mCursor = (void*)icon;
}
cWinImpl * cCursorWin::GetPlatform() {
return reinterpret_cast<cWinImpl*>( mWindow->GetPlatform() );
return reinterpret_cast<cWinImpl*>( mWindow->GetPlatform() );
}
void * cCursorWin::GetCursor() const {
return mCursor;
return mCursor;
}
}}}

View File

@@ -5,6 +5,9 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#undef CreateWindow

View File

@@ -326,7 +326,7 @@ void cEETest::CreateUI() {
InputParams.Parent( C );
InputParams.PosSet( 20, 216 );
InputParams.Size = eeSize( 200, 22 );
InputParams.Flags = UI_VALIGN_CENTER | UI_HALIGN_LEFT | UI_CLIP_ENABLE | UI_AUTO_PADDING;
InputParams.Flags = UI_VALIGN_CENTER | UI_HALIGN_LEFT | UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_TEXT_SELECTION_ENABLED;
cUITextInput * Input = eeNew( cUITextInput, ( InputParams ) );
Input->Visible( true );
Input->Enabled( true );
@@ -459,7 +459,7 @@ void cEETest::CreateUI() {
ComboParams.Parent( C );
ComboParams.PosSet( 20, 80 );
ComboParams.Size = eeSize( 100, 1 );
ComboParams.Flags = UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_VALIGN_CENTER | UI_HALIGN_LEFT | UI_AUTO_SIZE | UI_TOUCH_DRAG_ENABLED;
ComboParams.Flags = UI_CLIP_ENABLE | UI_AUTO_PADDING | UI_VALIGN_CENTER | UI_HALIGN_LEFT | UI_AUTO_SIZE | UI_TOUCH_DRAG_ENABLED | UI_TEXT_SELECTION_ENABLED;
cUIComboBox * mComboBox = eeNew( cUIComboBox, ( ComboParams ) );
mComboBox->Visible( true );
mComboBox->Enabled( true );
@@ -515,7 +515,7 @@ void cEETest::CreateUI() {
TEParams.Parent( C );
TEParams.PosSet( 5, 245 );
TEParams.Size = eeSize( 315, 130 );
TEParams.Flags = UI_AUTO_PADDING | UI_CLIP_ENABLE;
TEParams.Flags = UI_AUTO_PADDING | UI_CLIP_ENABLE | UI_TEXT_SELECTION_ENABLED;
cUITextEdit * TextEdit = eeNew( cUITextEdit, ( TEParams ) );
TextEdit->Visible( true );
TextEdit->Enabled( true );
@@ -659,11 +659,11 @@ void cEETest::CreateDecoratedWindow() {
TEdit->Text( mBuda );
TabWidget->Add( "TextEdit", TEdit );
cUITextBox * Txt = mTheme->CreateTextInput( TabWidget, eeSize(), eeVector2i(), UI_AUTO_PADDING | UI_AUTO_SHRINK_TEXT );
cUITextBox * Txt = mTheme->CreateTextInput( TabWidget, eeSize(), eeVector2i(), UI_AUTO_PADDING | UI_AUTO_SHRINK_TEXT | UI_TEXT_SELECTION_ENABLED );
Txt->Text( mBuda );
TabWidget->Add( "TextInput", Txt );
TabWidget->Add( "TextBox", mTheme->CreateTextBox( mBuda, TabWidget, eeSize(), eeVector2i(), UI_AUTO_PADDING | UI_AUTO_SHRINK_TEXT ) );
TabWidget->Add( "TextBox", mTheme->CreateTextBox( mBuda, TabWidget, eeSize(), eeVector2i(), UI_AUTO_PADDING | UI_AUTO_SHRINK_TEXT | UI_TEXT_SELECTION_ENABLED ) );
CreateWinMenu();
}