Commit f758fb54 authored by mercury233's avatar mercury233

patch files

parent d0d04c32
// Copyright (C) 2002-2012 Nikolaus Gebhardt // Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h // For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CGUIEditBox.h" #include "CGUIEditBox.h"
#ifdef _IRR_COMPILE_WITH_GUI_ #ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUISkin.h" #include "IGUISkin.h"
#include "IGUIEnvironment.h" #include "IGUIEnvironment.h"
#include "IGUIFont.h" #include "IGUIFont.h"
#include "IVideoDriver.h" #include "IVideoDriver.h"
#include "rect.h" #include "rect.h"
#include "os.h" #include "os.h"
#include "Keycodes.h" #include "Keycodes.h"
/* /*
todo: todo:
optional scrollbars optional scrollbars
ctrl+left/right to select word ctrl+left/right to select word
double click/ctrl click: word select + drag to select whole words, triple click to select line double click/ctrl click: word select + drag to select whole words, triple click to select line
optional? dragging selected text optional? dragging selected text
numerical numerical
*/ */
namespace irr namespace irr
{ {
namespace gui namespace gui
{ {
//! constructor //! constructor
CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border,
IGUIEnvironment* environment, IGUIElement* parent, s32 id, IGUIEnvironment* environment, IGUIElement* parent, s32 id,
const core::rect<s32>& rectangle) const core::rect<s32>& rectangle)
: IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false), : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false),
Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0), Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0), OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0),
Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0), Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false), WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false),
PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER),
CurrentTextRect(0,0,1,1), FrameRect(rectangle) CurrentTextRect(0,0,1,1), FrameRect(rectangle)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CGUIEditBox"); setDebugName("CGUIEditBox");
#endif #endif
Text = text; Text = text;
if (Environment) if (Environment)
Operator = Environment->getOSOperator(); Operator = Environment->getOSOperator();
if (Operator) if (Operator)
Operator->grab(); Operator->grab();
// this element can be tabbed to // this element can be tabbed to
setTabStop(true); setTabStop(true);
setTabOrder(-1); setTabOrder(-1);
calculateFrameRect(); calculateFrameRect();
breakText(); breakText();
calculateScrollPos(); calculateScrollPos();
} }
//! destructor //! destructor
CGUIEditBox::~CGUIEditBox() CGUIEditBox::~CGUIEditBox()
{ {
if (OverrideFont) if (OverrideFont)
OverrideFont->drop(); OverrideFont->drop();
if (Operator) if (Operator)
Operator->drop(); Operator->drop();
} }
//! Sets another skin independent font. //! Sets another skin independent font.
void CGUIEditBox::setOverrideFont(IGUIFont* font) void CGUIEditBox::setOverrideFont(IGUIFont* font)
{ {
if (OverrideFont == font) if (OverrideFont == font)
return; return;
if (OverrideFont) if (OverrideFont)
OverrideFont->drop(); OverrideFont->drop();
OverrideFont = font; OverrideFont = font;
if (OverrideFont) if (OverrideFont)
OverrideFont->grab(); OverrideFont->grab();
breakText(); breakText();
} }
//! Gets the override font (if any) //! Gets the override font (if any)
IGUIFont * CGUIEditBox::getOverrideFont() const IGUIFont * CGUIEditBox::getOverrideFont() const
{ {
return OverrideFont; return OverrideFont;
} }
//! Get the font which is used right now for drawing //! Get the font which is used right now for drawing
IGUIFont* CGUIEditBox::getActiveFont() const IGUIFont* CGUIEditBox::getActiveFont() const
{ {
if ( OverrideFont ) if ( OverrideFont )
return OverrideFont; return OverrideFont;
IGUISkin* skin = Environment->getSkin(); IGUISkin* skin = Environment->getSkin();
if (skin) if (skin)
return skin->getFont(); return skin->getFont();
return 0; return 0;
} }
//! Sets another color for the text. //! Sets another color for the text.
void CGUIEditBox::setOverrideColor(video::SColor color) void CGUIEditBox::setOverrideColor(video::SColor color)
{ {
OverrideColor = color; OverrideColor = color;
OverrideColorEnabled = true; OverrideColorEnabled = true;
} }
video::SColor CGUIEditBox::getOverrideColor() const video::SColor CGUIEditBox::getOverrideColor() const
{ {
return OverrideColor; return OverrideColor;
} }
//! Turns the border on or off //! Turns the border on or off
void CGUIEditBox::setDrawBorder(bool border) void CGUIEditBox::setDrawBorder(bool border)
{ {
Border = border; Border = border;
} }
//! Sets whether to draw the background //! Sets whether to draw the background
void CGUIEditBox::setDrawBackground(bool draw) void CGUIEditBox::setDrawBackground(bool draw)
{ {
Background = draw; Background = draw;
} }
//! Sets if the text should use the overide color or the color in the gui skin. //! Sets if the text should use the overide color or the color in the gui skin.
void CGUIEditBox::enableOverrideColor(bool enable) void CGUIEditBox::enableOverrideColor(bool enable)
{ {
OverrideColorEnabled = enable; OverrideColorEnabled = enable;
} }
bool CGUIEditBox::isOverrideColorEnabled() const bool CGUIEditBox::isOverrideColorEnabled() const
{ {
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return OverrideColorEnabled; return OverrideColorEnabled;
} }
//! Enables or disables word wrap //! Enables or disables word wrap
void CGUIEditBox::setWordWrap(bool enable) void CGUIEditBox::setWordWrap(bool enable)
{ {
WordWrap = enable; WordWrap = enable;
breakText(); breakText();
} }
void CGUIEditBox::updateAbsolutePosition() void CGUIEditBox::updateAbsolutePosition()
{ {
core::rect<s32> oldAbsoluteRect(AbsoluteRect); core::rect<s32> oldAbsoluteRect(AbsoluteRect);
IGUIElement::updateAbsolutePosition(); IGUIElement::updateAbsolutePosition();
if ( oldAbsoluteRect != AbsoluteRect ) if ( oldAbsoluteRect != AbsoluteRect )
{ {
calculateFrameRect(); calculateFrameRect();
breakText(); breakText();
calculateScrollPos(); calculateScrollPos();
} }
} }
//! Checks if word wrap is enabled //! Checks if word wrap is enabled
bool CGUIEditBox::isWordWrapEnabled() const bool CGUIEditBox::isWordWrapEnabled() const
{ {
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return WordWrap; return WordWrap;
} }
//! Enables or disables newlines. //! Enables or disables newlines.
void CGUIEditBox::setMultiLine(bool enable) void CGUIEditBox::setMultiLine(bool enable)
{ {
MultiLine = enable; MultiLine = enable;
breakText(); breakText();
} }
//! Checks if multi line editing is enabled //! Checks if multi line editing is enabled
bool CGUIEditBox::isMultiLineEnabled() const bool CGUIEditBox::isMultiLineEnabled() const
{ {
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return MultiLine; return MultiLine;
} }
void CGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar) void CGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar)
{ {
PasswordBox = passwordBox; PasswordBox = passwordBox;
if (PasswordBox) if (PasswordBox)
{ {
PasswordChar = passwordChar; PasswordChar = passwordChar;
setMultiLine(false); setMultiLine(false);
setWordWrap(false); setWordWrap(false);
BrokenText.clear(); BrokenText.clear();
} }
} }
bool CGUIEditBox::isPasswordBox() const bool CGUIEditBox::isPasswordBox() const
{ {
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return PasswordBox; return PasswordBox;
} }
//! Sets text justification //! Sets text justification
void CGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) void CGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
{ {
HAlign = horizontal; HAlign = horizontal;
VAlign = vertical; VAlign = vertical;
} }
//! called if an event happened. //! called if an event happened.
bool CGUIEditBox::OnEvent(const SEvent& event) bool CGUIEditBox::OnEvent(const SEvent& event)
{ {
if (isEnabled()) if (isEnabled())
{ {
switch(event.EventType) switch(event.EventType)
{ {
case EET_GUI_EVENT: case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{ {
if (event.GUIEvent.Caller == this) if (event.GUIEvent.Caller == this)
{ {
MouseMarking = false; MouseMarking = false;
setTextMarkers(0,0); setTextMarkers(0,0);
} }
} }
break; break;
case EET_KEY_INPUT_EVENT: case EET_KEY_INPUT_EVENT:
if (processKey(event)) if (processKey(event))
return true; return true;
break; break;
case EET_MOUSE_INPUT_EVENT: case EET_MOUSE_INPUT_EVENT:
if (processMouse(event)) if (processMouse(event))
return true; return true;
break; break;
default: default:
break; break;
} }
} }
return IGUIElement::OnEvent(event); return IGUIElement::OnEvent(event);
} }
bool CGUIEditBox::processKey(const SEvent& event) bool CGUIEditBox::processKey(const SEvent& event)
{ {
if (!event.KeyInput.PressedDown) if (!event.KeyInput.PressedDown)
return false; return false;
bool textChanged = false; bool textChanged = false;
s32 newMarkBegin = MarkBegin; s32 newMarkBegin = MarkBegin;
s32 newMarkEnd = MarkEnd; s32 newMarkEnd = MarkEnd;
// control shortcut handling // control shortcut handling
if (event.KeyInput.Control) if (event.KeyInput.Control)
{ {
// german backlash '\' entered with control + '?' // german backlash '\' entered with control + '?'
if ( event.KeyInput.Char == '\\' ) if ( event.KeyInput.Char == '\\' )
{ {
inputChar(event.KeyInput.Char); inputChar(event.KeyInput.Char);
return true; return true;
} }
switch(event.KeyInput.Key) switch(event.KeyInput.Key)
{ {
case KEY_KEY_A: case KEY_KEY_A:
// select all // select all
newMarkBegin = 0; newMarkBegin = 0;
newMarkEnd = Text.size(); newMarkEnd = Text.size();
break; break;
case KEY_KEY_C: case KEY_KEY_C:
// copy to clipboard // copy to clipboard
if (!PasswordBox && Operator && MarkBegin != MarkEnd) if (!PasswordBox && Operator && MarkBegin != MarkEnd)
{ {
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
core::stringc s; const int max_char_size = sizeof(wchar_t) * 3 / 2;
s = Text.subString(realmbgn, realmend - realmbgn).c_str(); int max_size = (realmend - realmbgn)*max_char_size + 1;
Operator->copyToClipboard(s.c_str()); c8 *s = new char[max_size];
} wcstombs(s, Text.subString(realmbgn, realmend-realmbgn).c_str(), max_size);
break; Operator->copyToClipboard(s);
case KEY_KEY_X: }
// cut to the clipboard break;
if (!PasswordBox && Operator && MarkBegin != MarkEnd) case KEY_KEY_X:
{ // cut to the clipboard
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; if (!PasswordBox && Operator && MarkBegin != MarkEnd)
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; {
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
// copy const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
core::stringc sc;
sc = Text.subString(realmbgn, realmend - realmbgn).c_str(); // copy
Operator->copyToClipboard(sc.c_str()); const int max_char_size = sizeof(wchar_t) * 3 / 2;
int max_size = (realmend - realmbgn)*max_char_size + 1;
if (isEnabled()) c8 *s = new char[max_size];
{ wcstombs(s, Text.subString(realmbgn, realmend-realmbgn).c_str(), max_size);
// delete Operator->copyToClipboard(s);
core::stringw s;
s = Text.subString(0, realmbgn); if (isEnabled())
s.append( Text.subString(realmend, Text.size()-realmend) ); {
Text = s; // delete
core::stringw s;
CursorPos = realmbgn; s = Text.subString(0, realmbgn);
newMarkBegin = 0; s.append( Text.subString(realmend, Text.size()-realmend) );
newMarkEnd = 0; Text = s;
textChanged = true;
} CursorPos = realmbgn;
} newMarkBegin = 0;
break; newMarkEnd = 0;
case KEY_KEY_V: textChanged = true;
if ( !isEnabled() ) }
break; }
break;
// paste from the clipboard case KEY_KEY_V:
if (Operator) if ( !isEnabled() )
{ break;
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; // paste from the clipboard
if (Operator)
// add new character {
const c8* p = Operator->getTextFromClipboard(); const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
if (p) const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
{
// TODO: we should have such a function in core::string // add new character
size_t lenOld = strlen(p); const c8* p = Operator->getTextFromClipboard();
wchar_t *ws = new wchar_t[lenOld + 1]; if (p)
size_t len = mbstowcs(ws,p,lenOld); {
ws[len] = 0; // TODO: we should have such a function in core::string
irr::core::stringw widep(ws); size_t lenOld = strlen(p);
delete[] ws; wchar_t *ws = new wchar_t[lenOld + 1];
size_t len = mbstowcs(ws,p,lenOld);
if (MarkBegin == MarkEnd) ws[len] = 0;
{ irr::core::stringw widep(ws);
// insert text delete[] ws;
core::stringw s = Text.subString(0, CursorPos);
s.append(widep); if (MarkBegin == MarkEnd)
s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); {
// insert text
if (!Max || s.size()<=Max) // thx to Fish FH for fix core::stringw s = Text.subString(0, CursorPos);
{ s.append(widep);
Text = s; s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
s = widep;
CursorPos += s.size(); if (!Max || s.size()<=Max) // thx to Fish FH for fix
} {
} Text = s;
else s = widep;
{ CursorPos += s.size();
// replace text }
}
core::stringw s = Text.subString(0, realmbgn); else
s.append(widep); {
s.append( Text.subString(realmend, Text.size()-realmend) ); // replace text
if (!Max || s.size()<=Max) // thx to Fish FH for fix core::stringw s = Text.subString(0, realmbgn);
{ s.append(widep);
Text = s; s.append( Text.subString(realmend, Text.size()-realmend) );
s = widep;
CursorPos = realmbgn + s.size(); if (!Max || s.size()<=Max) // thx to Fish FH for fix
} {
} Text = s;
} s = widep;
CursorPos = realmbgn + s.size();
newMarkBegin = 0; }
newMarkEnd = 0; }
textChanged = true; }
}
break; newMarkBegin = 0;
case KEY_HOME: newMarkEnd = 0;
// move/highlight to start of text textChanged = true;
if (event.KeyInput.Shift) }
{ break;
newMarkEnd = CursorPos; case KEY_HOME:
newMarkBegin = 0; // move/highlight to start of text
CursorPos = 0; if (event.KeyInput.Shift)
} {
else newMarkEnd = CursorPos;
{ newMarkBegin = 0;
CursorPos = 0; CursorPos = 0;
newMarkBegin = 0; }
newMarkEnd = 0; else
} {
break; CursorPos = 0;
case KEY_END: newMarkBegin = 0;
// move/highlight to end of text newMarkEnd = 0;
if (event.KeyInput.Shift) }
{ break;
newMarkBegin = CursorPos; case KEY_END:
newMarkEnd = Text.size(); // move/highlight to end of text
CursorPos = 0; if (event.KeyInput.Shift)
} {
else newMarkBegin = CursorPos;
{ newMarkEnd = Text.size();
CursorPos = Text.size(); CursorPos = 0;
newMarkBegin = 0; }
newMarkEnd = 0; else
} {
break; CursorPos = Text.size();
default: newMarkBegin = 0;
return false; newMarkEnd = 0;
} }
} break;
// default keyboard handling default:
else return false;
switch(event.KeyInput.Key) }
{ }
case KEY_END: // default keyboard handling
{ else
s32 p = Text.size(); switch(event.KeyInput.Key)
if (WordWrap || MultiLine) {
{ case KEY_END:
p = getLineFromPos(CursorPos); {
p = BrokenTextPositions[p] + (s32)BrokenText[p].size(); s32 p = Text.size();
if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' )) if (WordWrap || MultiLine)
p-=1; {
} p = getLineFromPos(CursorPos);
p = BrokenTextPositions[p] + (s32)BrokenText[p].size();
if (event.KeyInput.Shift) if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' ))
{ p-=1;
if (MarkBegin == MarkEnd) }
newMarkBegin = CursorPos;
if (event.KeyInput.Shift)
newMarkEnd = p; {
} if (MarkBegin == MarkEnd)
else newMarkBegin = CursorPos;
{
newMarkBegin = 0; newMarkEnd = p;
newMarkEnd = 0; }
} else
CursorPos = p; {
BlinkStartTime = os::Timer::getTime(); newMarkBegin = 0;
} newMarkEnd = 0;
break; }
case KEY_HOME: CursorPos = p;
{ BlinkStartTime = os::Timer::getTime();
}
s32 p = 0; break;
if (WordWrap || MultiLine) case KEY_HOME:
{ {
p = getLineFromPos(CursorPos);
p = BrokenTextPositions[p]; s32 p = 0;
} if (WordWrap || MultiLine)
{
if (event.KeyInput.Shift) p = getLineFromPos(CursorPos);
{ p = BrokenTextPositions[p];
if (MarkBegin == MarkEnd) }
newMarkBegin = CursorPos;
newMarkEnd = p; if (event.KeyInput.Shift)
} {
else if (MarkBegin == MarkEnd)
{ newMarkBegin = CursorPos;
newMarkBegin = 0; newMarkEnd = p;
newMarkEnd = 0; }
} else
CursorPos = p; {
BlinkStartTime = os::Timer::getTime(); newMarkBegin = 0;
} newMarkEnd = 0;
break; }
case KEY_RETURN: CursorPos = p;
if (MultiLine) BlinkStartTime = os::Timer::getTime();
{ }
inputChar(L'\n'); break;
} case KEY_RETURN:
else if (MultiLine)
{ {
calculateScrollPos(); inputChar(L'\n');
sendGuiEvent( EGET_EDITBOX_ENTER ); }
} else
return true; {
case KEY_LEFT: calculateScrollPos();
sendGuiEvent( EGET_EDITBOX_ENTER );
if (event.KeyInput.Shift) }
{ return true;
if (CursorPos > 0) case KEY_LEFT:
{
if (MarkBegin == MarkEnd) if (event.KeyInput.Shift)
newMarkBegin = CursorPos; {
if (CursorPos > 0)
newMarkEnd = CursorPos-1; {
} if (MarkBegin == MarkEnd)
} newMarkBegin = CursorPos;
else
{ newMarkEnd = CursorPos-1;
newMarkBegin = 0; }
newMarkEnd = 0; }
} else
{
if (CursorPos > 0) CursorPos--; newMarkBegin = 0;
BlinkStartTime = os::Timer::getTime(); newMarkEnd = 0;
break; }
case KEY_RIGHT: if (CursorPos > 0) CursorPos--;
if (event.KeyInput.Shift) BlinkStartTime = os::Timer::getTime();
{ break;
if (Text.size() > (u32)CursorPos)
{ case KEY_RIGHT:
if (MarkBegin == MarkEnd) if (event.KeyInput.Shift)
newMarkBegin = CursorPos; {
if (Text.size() > (u32)CursorPos)
newMarkEnd = CursorPos+1; {
} if (MarkBegin == MarkEnd)
} newMarkBegin = CursorPos;
else
{ newMarkEnd = CursorPos+1;
newMarkBegin = 0; }
newMarkEnd = 0; }
} else
{
if (Text.size() > (u32)CursorPos) CursorPos++; newMarkBegin = 0;
BlinkStartTime = os::Timer::getTime(); newMarkEnd = 0;
break; }
case KEY_UP:
if (MultiLine || (WordWrap && BrokenText.size() > 1) ) if (Text.size() > (u32)CursorPos) CursorPos++;
{ BlinkStartTime = os::Timer::getTime();
s32 lineNo = getLineFromPos(CursorPos); break;
s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd); case KEY_UP:
if (lineNo > 0) if (MultiLine || (WordWrap && BrokenText.size() > 1) )
{ {
s32 cp = CursorPos - BrokenTextPositions[lineNo]; s32 lineNo = getLineFromPos(CursorPos);
if ((s32)BrokenText[lineNo-1].size() < cp) s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
CursorPos = BrokenTextPositions[lineNo-1] + core::max_((u32)1, BrokenText[lineNo-1].size())-1; if (lineNo > 0)
else {
CursorPos = BrokenTextPositions[lineNo-1] + cp; s32 cp = CursorPos - BrokenTextPositions[lineNo];
} if ((s32)BrokenText[lineNo-1].size() < cp)
CursorPos = BrokenTextPositions[lineNo-1] + core::max_((u32)1, BrokenText[lineNo-1].size())-1;
if (event.KeyInput.Shift) else
{ CursorPos = BrokenTextPositions[lineNo-1] + cp;
newMarkBegin = mb; }
newMarkEnd = CursorPos;
} if (event.KeyInput.Shift)
else {
{ newMarkBegin = mb;
newMarkBegin = 0; newMarkEnd = CursorPos;
newMarkEnd = 0; }
} else
{
} newMarkBegin = 0;
else newMarkEnd = 0;
{ }
return false;
} }
break; else
case KEY_DOWN: {
if (MultiLine || (WordWrap && BrokenText.size() > 1) ) return false;
{ }
s32 lineNo = getLineFromPos(CursorPos); break;
s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd); case KEY_DOWN:
if (lineNo < (s32)BrokenText.size()-1) if (MultiLine || (WordWrap && BrokenText.size() > 1) )
{ {
s32 cp = CursorPos - BrokenTextPositions[lineNo]; s32 lineNo = getLineFromPos(CursorPos);
if ((s32)BrokenText[lineNo+1].size() < cp) s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
CursorPos = BrokenTextPositions[lineNo+1] + core::max_((u32)1, BrokenText[lineNo+1].size())-1; if (lineNo < (s32)BrokenText.size()-1)
else {
CursorPos = BrokenTextPositions[lineNo+1] + cp; s32 cp = CursorPos - BrokenTextPositions[lineNo];
} if ((s32)BrokenText[lineNo+1].size() < cp)
CursorPos = BrokenTextPositions[lineNo+1] + core::max_((u32)1, BrokenText[lineNo+1].size())-1;
if (event.KeyInput.Shift) else
{ CursorPos = BrokenTextPositions[lineNo+1] + cp;
newMarkBegin = mb; }
newMarkEnd = CursorPos;
} if (event.KeyInput.Shift)
else {
{ newMarkBegin = mb;
newMarkBegin = 0; newMarkEnd = CursorPos;
newMarkEnd = 0; }
} else
{
} newMarkBegin = 0;
else newMarkEnd = 0;
{ }
return false;
} }
break; else
{
case KEY_BACK: return false;
if ( !isEnabled() ) }
break; break;
if (Text.size()) case KEY_BACK:
{ if ( !isEnabled() )
core::stringw s; break;
if (MarkBegin != MarkEnd) if (Text.size())
{ {
// delete marked text core::stringw s;
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; if (MarkBegin != MarkEnd)
{
s = Text.subString(0, realmbgn); // delete marked text
s.append( Text.subString(realmend, Text.size()-realmend) ); const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
Text = s; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
CursorPos = realmbgn; s = Text.subString(0, realmbgn);
} s.append( Text.subString(realmend, Text.size()-realmend) );
else Text = s;
{
// delete text behind cursor CursorPos = realmbgn;
if (CursorPos>0) }
s = Text.subString(0, CursorPos-1); else
else {
s = L""; // delete text behind cursor
s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); if (CursorPos>0)
Text = s; s = Text.subString(0, CursorPos-1);
--CursorPos; else
} s = L"";
s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
if (CursorPos < 0) Text = s;
CursorPos = 0; --CursorPos;
BlinkStartTime = os::Timer::getTime(); }
newMarkBegin = 0;
newMarkEnd = 0; if (CursorPos < 0)
textChanged = true; CursorPos = 0;
} BlinkStartTime = os::Timer::getTime();
break; newMarkBegin = 0;
case KEY_DELETE: newMarkEnd = 0;
if ( !isEnabled() ) textChanged = true;
break; }
break;
if (Text.size() != 0) case KEY_DELETE:
{ if ( !isEnabled() )
core::stringw s; break;
if (MarkBegin != MarkEnd) if (Text.size() != 0)
{ {
// delete marked text core::stringw s;
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; if (MarkBegin != MarkEnd)
{
s = Text.subString(0, realmbgn); // delete marked text
s.append( Text.subString(realmend, Text.size()-realmend) ); const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
Text = s; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
CursorPos = realmbgn; s = Text.subString(0, realmbgn);
} s.append( Text.subString(realmend, Text.size()-realmend) );
else Text = s;
{
// delete text before cursor CursorPos = realmbgn;
s = Text.subString(0, CursorPos); }
s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) ); else
Text = s; {
} // delete text before cursor
s = Text.subString(0, CursorPos);
if (CursorPos > (s32)Text.size()) s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) );
CursorPos = (s32)Text.size(); Text = s;
}
BlinkStartTime = os::Timer::getTime();
newMarkBegin = 0; if (CursorPos > (s32)Text.size())
newMarkEnd = 0; CursorPos = (s32)Text.size();
textChanged = true;
} BlinkStartTime = os::Timer::getTime();
break; newMarkBegin = 0;
newMarkEnd = 0;
case KEY_ESCAPE: textChanged = true;
case KEY_TAB: }
case KEY_SHIFT: break;
case KEY_F1:
case KEY_F2: case KEY_ESCAPE:
case KEY_F3: case KEY_TAB:
case KEY_F4: case KEY_SHIFT:
case KEY_F5: case KEY_F1:
case KEY_F6: case KEY_F2:
case KEY_F7: case KEY_F3:
case KEY_F8: case KEY_F4:
case KEY_F9: case KEY_F5:
case KEY_F10: case KEY_F6:
case KEY_F11: case KEY_F7:
case KEY_F12: case KEY_F8:
case KEY_F13: case KEY_F9:
case KEY_F14: case KEY_F10:
case KEY_F15: case KEY_F11:
case KEY_F16: case KEY_F12:
case KEY_F17: case KEY_F13:
case KEY_F18: case KEY_F14:
case KEY_F19: case KEY_F15:
case KEY_F20: case KEY_F16:
case KEY_F21: case KEY_F17:
case KEY_F22: case KEY_F18:
case KEY_F23: case KEY_F19:
case KEY_F24: case KEY_F20:
// ignore these keys case KEY_F21:
return false; case KEY_F22:
case KEY_F23:
default: case KEY_F24:
inputChar(event.KeyInput.Char); // ignore these keys
return true; return false;
}
default:
// Set new text markers inputChar(event.KeyInput.Char);
setTextMarkers( newMarkBegin, newMarkEnd ); return true;
}
// break the text if it has changed
if (textChanged) // Set new text markers
{ setTextMarkers( newMarkBegin, newMarkEnd );
breakText();
calculateScrollPos(); // break the text if it has changed
sendGuiEvent(EGET_EDITBOX_CHANGED); if (textChanged)
} {
else breakText();
{ calculateScrollPos();
calculateScrollPos(); sendGuiEvent(EGET_EDITBOX_CHANGED);
} }
else
return true; {
} calculateScrollPos();
}
//! draws the element and its children return true;
void CGUIEditBox::draw() }
{
if (!IsVisible)
return; //! draws the element and its children
void CGUIEditBox::draw()
const bool focus = Environment->hasFocus(this); {
if (!IsVisible)
IGUISkin* skin = Environment->getSkin(); return;
if (!skin)
return; const bool focus = Environment->hasFocus(this);
EGUI_DEFAULT_COLOR bgCol = EGDC_GRAY_EDITABLE; IGUISkin* skin = Environment->getSkin();
if ( isEnabled() ) if (!skin)
bgCol = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE; return;
if (!Border && Background) EGUI_DEFAULT_COLOR bgCol = EGDC_GRAY_EDITABLE;
{ if ( isEnabled() )
skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect); bgCol = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
}
if (!Border && Background)
if (Border) {
{ skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect);
// draw the border }
skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect);
if (Border)
calculateFrameRect(); {
} // draw the border
skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect);
core::rect<s32> localClipRect = FrameRect;
localClipRect.clipAgainst(AbsoluteClippingRect); calculateFrameRect();
}
// draw the text
core::rect<s32> localClipRect = FrameRect;
IGUIFont* font = getActiveFont(); localClipRect.clipAgainst(AbsoluteClippingRect);
s32 cursorLine = 0; // draw the text
s32 charcursorpos = 0;
IGUIFont* font = getActiveFont();
if (font)
{ s32 cursorLine = 0;
if (LastBreakFont != font) s32 charcursorpos = 0;
{
breakText(); if (font)
} {
if (LastBreakFont != font)
// calculate cursor pos {
breakText();
core::stringw *txtLine = &Text; }
s32 startPos = 0;
// calculate cursor pos
core::stringw s, s2;
core::stringw *txtLine = &Text;
// get mark position s32 startPos = 0;
const bool ml = (!PasswordBox && (WordWrap || MultiLine));
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; core::stringw s, s2;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; // get mark position
const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1; const bool ml = (!PasswordBox && (WordWrap || MultiLine));
const s32 lineCount = ml ? BrokenText.size() : 1; const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
// Save the override color information. const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0;
// Then, alter it if the edit box is disabled. const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1;
const bool prevOver = OverrideColorEnabled; const s32 lineCount = ml ? BrokenText.size() : 1;
const video::SColor prevColor = OverrideColor;
// Save the override color information.
if (Text.size()) // Then, alter it if the edit box is disabled.
{ const bool prevOver = OverrideColorEnabled;
if (!isEnabled() && !OverrideColorEnabled) const video::SColor prevColor = OverrideColor;
{
OverrideColorEnabled = true; if (Text.size())
OverrideColor = skin->getColor(EGDC_GRAY_TEXT); {
} if (!isEnabled() && !OverrideColorEnabled)
{
for (s32 i=0; i < lineCount; ++i) OverrideColorEnabled = true;
{ OverrideColor = skin->getColor(EGDC_GRAY_TEXT);
setTextRect(i); }
// clipping test - don't draw anything outside the visible area for (s32 i=0; i < lineCount; ++i)
core::rect<s32> c = localClipRect; {
c.clipAgainst(CurrentTextRect); setTextRect(i);
if (!c.isValid())
continue; // clipping test - don't draw anything outside the visible area
core::rect<s32> c = localClipRect;
// get current line c.clipAgainst(CurrentTextRect);
if (PasswordBox) if (!c.isValid())
{ continue;
if (BrokenText.size() != 1)
{ // get current line
BrokenText.clear(); if (PasswordBox)
BrokenText.push_back(core::stringw()); {
} if (BrokenText.size() != 1)
if (BrokenText[0].size() != Text.size()) {
{ BrokenText.clear();
BrokenText[0] = Text; BrokenText.push_back(core::stringw());
for (u32 q = 0; q < Text.size(); ++q) }
{ if (BrokenText[0].size() != Text.size())
BrokenText[0] [q] = PasswordChar; {
} BrokenText[0] = Text;
} for (u32 q = 0; q < Text.size(); ++q)
txtLine = &BrokenText[0]; {
startPos = 0; BrokenText[0] [q] = PasswordChar;
} }
else }
{ txtLine = &BrokenText[0];
txtLine = ml ? &BrokenText[i] : &Text; startPos = 0;
startPos = ml ? BrokenTextPositions[i] : 0; }
} else
{
txtLine = ml ? &BrokenText[i] : &Text;
// draw normal text startPos = ml ? BrokenTextPositions[i] : 0;
font->draw(txtLine->c_str(), CurrentTextRect, }
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
false, true, &localClipRect);
// draw normal text
// draw mark and marked text font->draw(txtLine->c_str(), CurrentTextRect,
if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount) OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
{ false, true, &localClipRect);
s32 mbegin = 0, mend = 0; // draw mark and marked text
s32 lineStartPos = 0, lineEndPos = txtLine->size(); if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount)
{
if (i == hlineStart)
{ s32 mbegin = 0, mend = 0;
// highlight start is on this line s32 lineStartPos = 0, lineEndPos = txtLine->size();
s = txtLine->subString(0, realmbgn - startPos);
mbegin = font->getDimension(s.c_str()).Width; if (i == hlineStart)
{
// deal with kerning // highlight start is on this line
mbegin += font->getKerningWidth( s = txtLine->subString(0, realmbgn - startPos);
&((*txtLine)[realmbgn - startPos]), mbegin = font->getDimension(s.c_str()).Width;
realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0);
// deal with kerning
lineStartPos = realmbgn - startPos; mbegin += font->getKerningWidth(
} &((*txtLine)[realmbgn - startPos]),
if (i == hlineStart + hlineCount - 1) realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0);
{
// highlight end is on this line lineStartPos = realmbgn - startPos;
s2 = txtLine->subString(0, realmend - startPos); }
mend = font->getDimension(s2.c_str()).Width; if (i == hlineStart + hlineCount - 1)
lineEndPos = (s32)s2.size(); {
} // highlight end is on this line
else s2 = txtLine->subString(0, realmend - startPos);
mend = font->getDimension(txtLine->c_str()).Width; mend = font->getDimension(s2.c_str()).Width;
lineEndPos = (s32)s2.size();
CurrentTextRect.UpperLeftCorner.X += mbegin; }
CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin; else
mend = font->getDimension(txtLine->c_str()).Width;
// draw mark
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect); CurrentTextRect.UpperLeftCorner.X += mbegin;
CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin;
// draw marked text
s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos); // draw mark
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect);
if (s.size())
font->draw(s.c_str(), CurrentTextRect, // draw marked text
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT), s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos);
false, true, &localClipRect);
if (s.size())
} font->draw(s.c_str(), CurrentTextRect,
} OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT),
false, true, &localClipRect);
// Return the override color information to its previous settings.
OverrideColorEnabled = prevOver; }
OverrideColor = prevColor; }
}
// Return the override color information to its previous settings.
// draw cursor OverrideColorEnabled = prevOver;
if ( IsEnabled ) OverrideColor = prevColor;
{ }
if (WordWrap || MultiLine)
{ // draw cursor
cursorLine = getLineFromPos(CursorPos); if ( IsEnabled )
txtLine = &BrokenText[cursorLine]; {
startPos = BrokenTextPositions[cursorLine]; if (WordWrap || MultiLine)
} {
s = txtLine->subString(0,CursorPos-startPos); cursorLine = getLineFromPos(CursorPos);
charcursorpos = font->getDimension(s.c_str()).Width + txtLine = &BrokenText[cursorLine];
font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); startPos = BrokenTextPositions[cursorLine];
}
if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350) s = txtLine->subString(0,CursorPos-startPos);
{ charcursorpos = font->getDimension(s.c_str()).Width +
setTextRect(cursorLine); font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0);
CurrentTextRect.UpperLeftCorner.X += charcursorpos;
if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350)
font->draw(L"_", CurrentTextRect, {
OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), setTextRect(cursorLine);
false, true, &localClipRect); CurrentTextRect.UpperLeftCorner.X += charcursorpos;
}
} font->draw(L"_", CurrentTextRect,
} OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
false, true, &localClipRect);
// draw children }
IGUIElement::draw(); }
} }
// draw children
//! Sets the new caption of this element. IGUIElement::draw();
void CGUIEditBox::setText(const wchar_t* text) }
{
Text = text;
if (u32(CursorPos) > Text.size()) //! Sets the new caption of this element.
CursorPos = Text.size(); void CGUIEditBox::setText(const wchar_t* text)
HScrollPos = 0; {
breakText(); Text = text;
} if (u32(CursorPos) > Text.size())
CursorPos = Text.size();
HScrollPos = 0;
//! Enables or disables automatic scrolling with cursor position breakText();
//! \param enable: If set to true, the text will move around with the cursor position }
void CGUIEditBox::setAutoScroll(bool enable)
{
AutoScroll = enable; //! Enables or disables automatic scrolling with cursor position
} //! \param enable: If set to true, the text will move around with the cursor position
void CGUIEditBox::setAutoScroll(bool enable)
{
//! Checks to see if automatic scrolling is enabled AutoScroll = enable;
//! \return true if automatic scrolling is enabled, false if not }
bool CGUIEditBox::isAutoScrollEnabled() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; //! Checks to see if automatic scrolling is enabled
return AutoScroll; //! \return true if automatic scrolling is enabled, false if not
} bool CGUIEditBox::isAutoScrollEnabled() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
//! Gets the area of the text in the edit box return AutoScroll;
//! \return Returns the size in pixels of the text }
core::dimension2du CGUIEditBox::getTextDimension()
{
core::rect<s32> ret; //! Gets the area of the text in the edit box
//! \return Returns the size in pixels of the text
setTextRect(0); core::dimension2du CGUIEditBox::getTextDimension()
ret = CurrentTextRect; {
core::rect<s32> ret;
for (u32 i=1; i < BrokenText.size(); ++i)
{ setTextRect(0);
setTextRect(i); ret = CurrentTextRect;
ret.addInternalPoint(CurrentTextRect.UpperLeftCorner);
ret.addInternalPoint(CurrentTextRect.LowerRightCorner); for (u32 i=1; i < BrokenText.size(); ++i)
} {
setTextRect(i);
return core::dimension2du(ret.getSize()); ret.addInternalPoint(CurrentTextRect.UpperLeftCorner);
} ret.addInternalPoint(CurrentTextRect.LowerRightCorner);
}
//! Sets the maximum amount of characters which may be entered in the box. return core::dimension2du(ret.getSize());
//! \param max: Maximum amount of characters. If 0, the character amount is }
//! infinity.
void CGUIEditBox::setMax(u32 max)
{ //! Sets the maximum amount of characters which may be entered in the box.
Max = max; //! \param max: Maximum amount of characters. If 0, the character amount is
//! infinity.
if (Text.size() > Max && Max != 0) void CGUIEditBox::setMax(u32 max)
Text = Text.subString(0, Max); {
} Max = max;
if (Text.size() > Max && Max != 0)
//! Returns maximum amount of characters, previously set by setMax(); Text = Text.subString(0, Max);
u32 CGUIEditBox::getMax() const }
{
return Max;
} //! Returns maximum amount of characters, previously set by setMax();
u32 CGUIEditBox::getMax() const
{
bool CGUIEditBox::processMouse(const SEvent& event) return Max;
{ }
switch(event.MouseInput.Event)
{
case irr::EMIE_LMOUSE_LEFT_UP: bool CGUIEditBox::processMouse(const SEvent& event)
if (Environment->hasFocus(this)) {
{ switch(event.MouseInput.Event)
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); {
if (MouseMarking) case irr::EMIE_LMOUSE_LEFT_UP:
{ if (Environment->hasFocus(this))
setTextMarkers( MarkBegin, CursorPos ); {
} CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
MouseMarking = false; if (MouseMarking)
calculateScrollPos(); {
return true; setTextMarkers( MarkBegin, CursorPos );
} }
break; MouseMarking = false;
case irr::EMIE_MOUSE_MOVED: calculateScrollPos();
{ return true;
if (MouseMarking) }
{ break;
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); case irr::EMIE_MOUSE_MOVED:
setTextMarkers( MarkBegin, CursorPos ); {
calculateScrollPos(); if (MouseMarking)
return true; {
} CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
} setTextMarkers( MarkBegin, CursorPos );
break; calculateScrollPos();
case EMIE_LMOUSE_PRESSED_DOWN: return true;
if (!Environment->hasFocus(this)) }
{ }
BlinkStartTime = os::Timer::getTime(); break;
MouseMarking = true; case EMIE_LMOUSE_PRESSED_DOWN:
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); if (!Environment->hasFocus(this))
setTextMarkers(CursorPos, CursorPos ); {
calculateScrollPos(); BlinkStartTime = os::Timer::getTime();
return true; MouseMarking = true;
} CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
else setTextMarkers(CursorPos, CursorPos );
{ calculateScrollPos();
if (!AbsoluteClippingRect.isPointInside( return true;
core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y))) }
{ else
return false; {
} if (!AbsoluteClippingRect.isPointInside(
else core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
{ {
// move cursor return false;
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); }
else
s32 newMarkBegin = MarkBegin; {
if (!MouseMarking) // move cursor
newMarkBegin = CursorPos; CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
MouseMarking = true; s32 newMarkBegin = MarkBegin;
setTextMarkers( newMarkBegin, CursorPos); if (!MouseMarking)
calculateScrollPos(); newMarkBegin = CursorPos;
return true;
} MouseMarking = true;
} setTextMarkers( newMarkBegin, CursorPos);
default: calculateScrollPos();
break; return true;
} }
}
return false; default:
} break;
}
s32 CGUIEditBox::getCursorPos(s32 x, s32 y) return false;
{ }
IGUIFont* font = getActiveFont();
const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; s32 CGUIEditBox::getCursorPos(s32 x, s32 y)
{
core::stringw *txtLine=0; IGUIFont* font = getActiveFont();
s32 startPos=0;
x+=3; const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
for (u32 i=0; i < lineCount; ++i) core::stringw *txtLine=0;
{ s32 startPos=0;
setTextRect(i); x+=3;
if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y)
y = CurrentTextRect.UpperLeftCorner.Y; for (u32 i=0; i < lineCount; ++i)
if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y ) {
y = CurrentTextRect.LowerRightCorner.Y; setTextRect(i);
if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y)
// is it inside this region? y = CurrentTextRect.UpperLeftCorner.Y;
if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y) if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y )
{ y = CurrentTextRect.LowerRightCorner.Y;
// we've found the clicked line
txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text; // is it inside this region?
startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0; if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y)
break; {
} // we've found the clicked line
} txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text;
startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0;
if (x < CurrentTextRect.UpperLeftCorner.X) break;
x = CurrentTextRect.UpperLeftCorner.X; }
}
if ( !txtLine )
return 0; if (x < CurrentTextRect.UpperLeftCorner.X)
x = CurrentTextRect.UpperLeftCorner.X;
s32 idx = font->getCharacterFromPos(txtLine->c_str(), x - CurrentTextRect.UpperLeftCorner.X);
if ( !txtLine )
// click was on or left of the line return 0;
if (idx != -1)
return idx + startPos; s32 idx = font->getCharacterFromPos(txtLine->c_str(), x - CurrentTextRect.UpperLeftCorner.X);
// click was off the right edge of the line, go to end. // click was on or left of the line
return txtLine->size() + startPos; if (idx != -1)
} return idx + startPos;
// click was off the right edge of the line, go to end.
//! Breaks the single text line. return txtLine->size() + startPos;
void CGUIEditBox::breakText() }
{
if ((!WordWrap && !MultiLine))
return; //! Breaks the single text line.
void CGUIEditBox::breakText()
BrokenText.clear(); // need to reallocate :/ {
BrokenTextPositions.set_used(0); if ((!WordWrap && !MultiLine))
return;
IGUIFont* font = getActiveFont();
if (!font) BrokenText.clear(); // need to reallocate :/
return; BrokenTextPositions.set_used(0);
LastBreakFont = font; IGUIFont* font = getActiveFont();
if (!font)
core::stringw line; return;
core::stringw word;
core::stringw whitespace; LastBreakFont = font;
s32 lastLineStart = 0;
s32 size = Text.size(); core::stringw line;
s32 length = 0; core::stringw word;
s32 elWidth = RelativeRect.getWidth() - 6; core::stringw whitespace;
wchar_t c; s32 lastLineStart = 0;
s32 size = Text.size();
for (s32 i=0; i<size; ++i) s32 length = 0;
{ s32 elWidth = RelativeRect.getWidth() - 6;
c = Text[i]; wchar_t c;
bool lineBreak = false;
for (s32 i=0; i<size; ++i)
if (c == L'\r') // Mac or Windows breaks {
{ c = Text[i];
lineBreak = true; bool lineBreak = false;
c = 0;
if (Text[i+1] == L'\n') // Windows breaks if (c == L'\r') // Mac or Windows breaks
{ {
// TODO: I (Michael) think that we shouldn't change the text given by the user for whatever reason. lineBreak = true;
// Instead rework the cursor positioning to be able to handle this (but not in stable release c = 0;
// branch as users might already expect this behavior). if (Text[i+1] == L'\n') // Windows breaks
Text.erase(i+1); {
--size; // TODO: I (Michael) think that we shouldn't change the text given by the user for whatever reason.
if ( CursorPos > i ) // Instead rework the cursor positioning to be able to handle this (but not in stable release
--CursorPos; // branch as users might already expect this behavior).
} Text.erase(i+1);
} --size;
else if (c == L'\n') // Unix breaks if ( CursorPos > i )
{ --CursorPos;
lineBreak = true; }
c = 0; }
} else if (c == L'\n') // Unix breaks
{
// don't break if we're not a multi-line edit box lineBreak = true;
if (!MultiLine) c = 0;
lineBreak = false; }
if (c == L' ' || c == 0 || i == (size-1)) // don't break if we're not a multi-line edit box
{ if (!MultiLine)
// here comes the next whitespace, look if lineBreak = false;
// we can break the last word to the next line
// We also break whitespace, otherwise cursor would vanish beside the right border. if (c == L' ' || c == 0 || i == (size-1))
s32 whitelgth = font->getDimension(whitespace.c_str()).Width; {
s32 worldlgth = font->getDimension(word.c_str()).Width; // here comes the next whitespace, look if
// we can break the last word to the next line
if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0) // We also break whitespace, otherwise cursor would vanish beside the right border.
{ s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
// break to next line s32 worldlgth = font->getDimension(word.c_str()).Width;
length = worldlgth;
BrokenText.push_back(line); if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0)
BrokenTextPositions.push_back(lastLineStart); {
lastLineStart = i - (s32)word.size(); // break to next line
line = word; length = worldlgth;
} BrokenText.push_back(line);
else BrokenTextPositions.push_back(lastLineStart);
{ lastLineStart = i - (s32)word.size();
// add word to line line = word;
line += whitespace; }
line += word; else
length += whitelgth + worldlgth; {
} // add word to line
line += whitespace;
word = L""; line += word;
whitespace = L""; length += whitelgth + worldlgth;
}
if ( c ) word = L"";
whitespace += c; whitespace = L"";
// compute line break
if (lineBreak) if ( c )
{ whitespace += c;
line += whitespace;
line += word; // compute line break
BrokenText.push_back(line); if (lineBreak)
BrokenTextPositions.push_back(lastLineStart); {
lastLineStart = i+1; line += whitespace;
line = L""; line += word;
word = L""; BrokenText.push_back(line);
whitespace = L""; BrokenTextPositions.push_back(lastLineStart);
length = 0; lastLineStart = i+1;
} line = L"";
} word = L"";
else whitespace = L"";
{ length = 0;
// yippee this is a word.. }
word += c; }
} else
} {
// yippee this is a word..
line += whitespace; word += c;
line += word; }
BrokenText.push_back(line); }
BrokenTextPositions.push_back(lastLineStart);
} line += whitespace;
line += word;
// TODO: that function does interpret VAlign according to line-index (indexed line is placed on top-center-bottom) BrokenText.push_back(line);
// but HAlign according to line-width (pixels) and not by row. BrokenTextPositions.push_back(lastLineStart);
// Intuitively I suppose HAlign handling is better as VScrollPos should handle the line-scrolling. }
// But please no one change this without also rewriting (and this time fucking testing!!!) autoscrolling (I noticed this when fixing the old autoscrolling).
void CGUIEditBox::setTextRect(s32 line) // TODO: that function does interpret VAlign according to line-index (indexed line is placed on top-center-bottom)
{ // but HAlign according to line-width (pixels) and not by row.
if ( line < 0 ) // Intuitively I suppose HAlign handling is better as VScrollPos should handle the line-scrolling.
return; // But please no one change this without also rewriting (and this time fucking testing!!!) autoscrolling (I noticed this when fixing the old autoscrolling).
void CGUIEditBox::setTextRect(s32 line)
IGUIFont* font = getActiveFont(); {
if (!font) if ( line < 0 )
return; return;
core::dimension2du d; IGUIFont* font = getActiveFont();
if (!font)
// get text dimension return;
const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
if (WordWrap || MultiLine) core::dimension2du d;
{
d = font->getDimension(BrokenText[line].c_str()); // get text dimension
} const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
else if (WordWrap || MultiLine)
{ {
d = font->getDimension(Text.c_str()); d = font->getDimension(BrokenText[line].c_str());
d.Height = AbsoluteRect.getHeight(); }
} else
d.Height += font->getKerningHeight(); {
d = font->getDimension(Text.c_str());
// justification d.Height = AbsoluteRect.getHeight();
switch (HAlign) }
{ d.Height += font->getKerningHeight();
case EGUIA_CENTER:
// align to h centre // justification
CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2); switch (HAlign)
CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2); {
break; case EGUIA_CENTER:
case EGUIA_LOWERRIGHT: // align to h centre
// align to right edge CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2);
CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width; CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2);
CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth(); break;
break; case EGUIA_LOWERRIGHT:
default: // align to right edge
// align to left edge CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width;
CurrentTextRect.UpperLeftCorner.X = 0; CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth();
CurrentTextRect.LowerRightCorner.X = d.Width; break;
default:
} // align to left edge
CurrentTextRect.UpperLeftCorner.X = 0;
switch (VAlign) CurrentTextRect.LowerRightCorner.X = d.Width;
{
case EGUIA_CENTER: }
// align to v centre
CurrentTextRect.UpperLeftCorner.Y = switch (VAlign)
(FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line; {
break; case EGUIA_CENTER:
case EGUIA_LOWERRIGHT: // align to v centre
// align to bottom edge CurrentTextRect.UpperLeftCorner.Y =
CurrentTextRect.UpperLeftCorner.Y = (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line;
FrameRect.getHeight() - lineCount*d.Height + d.Height*line; break;
break; case EGUIA_LOWERRIGHT:
default: // align to bottom edge
// align to top edge CurrentTextRect.UpperLeftCorner.Y =
CurrentTextRect.UpperLeftCorner.Y = d.Height*line; FrameRect.getHeight() - lineCount*d.Height + d.Height*line;
break; break;
} default:
// align to top edge
CurrentTextRect.UpperLeftCorner.X -= HScrollPos; CurrentTextRect.UpperLeftCorner.Y = d.Height*line;
CurrentTextRect.LowerRightCorner.X -= HScrollPos; break;
CurrentTextRect.UpperLeftCorner.Y -= VScrollPos; }
CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height;
CurrentTextRect.UpperLeftCorner.X -= HScrollPos;
CurrentTextRect += FrameRect.UpperLeftCorner; CurrentTextRect.LowerRightCorner.X -= HScrollPos;
CurrentTextRect.UpperLeftCorner.Y -= VScrollPos;
} CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height;
CurrentTextRect += FrameRect.UpperLeftCorner;
s32 CGUIEditBox::getLineFromPos(s32 pos)
{ }
if (!WordWrap && !MultiLine)
return 0;
s32 CGUIEditBox::getLineFromPos(s32 pos)
s32 i=0; {
while (i < (s32)BrokenTextPositions.size()) if (!WordWrap && !MultiLine)
{ return 0;
if (BrokenTextPositions[i] > pos)
return i-1; s32 i=0;
++i; while (i < (s32)BrokenTextPositions.size())
} {
return (s32)BrokenTextPositions.size() - 1; if (BrokenTextPositions[i] > pos)
} return i-1;
++i;
}
void CGUIEditBox::inputChar(wchar_t c) return (s32)BrokenTextPositions.size() - 1;
{ }
if (!isEnabled())
return;
void CGUIEditBox::inputChar(wchar_t c)
if (c != 0) {
{ if (!isEnabled())
if (Text.size() < Max || Max == 0) return;
{
core::stringw s; if (c != 0)
{
if (MarkBegin != MarkEnd) if (Text.size() < Max || Max == 0)
{ {
// replace marked text core::stringw s;
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; if (MarkBegin != MarkEnd)
{
s = Text.subString(0, realmbgn); // replace marked text
s.append(c); const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
s.append( Text.subString(realmend, Text.size()-realmend) ); const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
Text = s;
CursorPos = realmbgn+1; s = Text.subString(0, realmbgn);
} s.append(c);
else s.append( Text.subString(realmend, Text.size()-realmend) );
{ Text = s;
// add new character CursorPos = realmbgn+1;
s = Text.subString(0, CursorPos); }
s.append(c); else
s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); {
Text = s; // add new character
++CursorPos; s = Text.subString(0, CursorPos);
} s.append(c);
s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
BlinkStartTime = os::Timer::getTime(); Text = s;
setTextMarkers(0, 0); ++CursorPos;
} }
}
breakText(); BlinkStartTime = os::Timer::getTime();
calculateScrollPos(); setTextMarkers(0, 0);
sendGuiEvent(EGET_EDITBOX_CHANGED); }
} }
breakText();
// calculate autoscroll calculateScrollPos();
void CGUIEditBox::calculateScrollPos() sendGuiEvent(EGET_EDITBOX_CHANGED);
{ }
if (!AutoScroll)
return; // calculate autoscroll
void CGUIEditBox::calculateScrollPos()
IGUISkin* skin = Environment->getSkin(); {
if (!skin) if (!AutoScroll)
return; return;
IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
if (!font) IGUISkin* skin = Environment->getSkin();
return; if (!skin)
return;
s32 cursLine = getLineFromPos(CursorPos); IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
if ( cursLine < 0 ) if (!font)
return; return;
setTextRect(cursLine);
const bool hasBrokenText = MultiLine || WordWrap; s32 cursLine = getLineFromPos(CursorPos);
if ( cursLine < 0 )
// Check horizonal scrolling return;
// NOTE: Calculations different to vertical scrolling because setTextRect interprets VAlign relative to line but HAlign not relative to row setTextRect(cursLine);
{ const bool hasBrokenText = MultiLine || WordWrap;
// get cursor position
IGUIFont* font = getActiveFont(); // Check horizonal scrolling
if (!font) // NOTE: Calculations different to vertical scrolling because setTextRect interprets VAlign relative to line but HAlign not relative to row
return; {
// get cursor position
// get cursor area IGUIFont* font = getActiveFont();
irr::u32 cursorWidth = font->getDimension(L"_").Width; if (!font)
core::stringw *txtLine = hasBrokenText ? &BrokenText[cursLine] : &Text; return;
s32 cPos = hasBrokenText ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; // column
s32 cStart = font->getDimension(txtLine->subString(0, cPos).c_str()).Width; // pixels from text-start // get cursor area
s32 cEnd = cStart + cursorWidth; irr::u32 cursorWidth = font->getDimension(L"_").Width;
s32 txtWidth = font->getDimension(txtLine->c_str()).Width; core::stringw *txtLine = hasBrokenText ? &BrokenText[cursLine] : &Text;
s32 cPos = hasBrokenText ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; // column
if ( txtWidth < FrameRect.getWidth() ) s32 cStart = font->getDimension(txtLine->subString(0, cPos).c_str()).Width; // pixels from text-start
{ s32 cEnd = cStart + cursorWidth;
// TODO: Needs a clean left and right gap removal depending on HAlign, similar to vertical scrolling tests for top/bottom. s32 txtWidth = font->getDimension(txtLine->c_str()).Width;
// This check just fixes the case where it was most noticable (text smaller than clipping area).
if ( txtWidth < FrameRect.getWidth() )
HScrollPos = 0; {
setTextRect(cursLine); // TODO: Needs a clean left and right gap removal depending on HAlign, similar to vertical scrolling tests for top/bottom.
} // This check just fixes the case where it was most noticable (text smaller than clipping area).
if ( CurrentTextRect.UpperLeftCorner.X+cStart < FrameRect.UpperLeftCorner.X ) HScrollPos = 0;
{ setTextRect(cursLine);
// cursor to the left of the clipping area }
HScrollPos -= FrameRect.UpperLeftCorner.X-(CurrentTextRect.UpperLeftCorner.X+cStart);
setTextRect(cursLine); if ( CurrentTextRect.UpperLeftCorner.X+cStart < FrameRect.UpperLeftCorner.X )
{
// TODO: should show more characters to the left when we're scrolling left // cursor to the left of the clipping area
// and the cursor reaches the border. HScrollPos -= FrameRect.UpperLeftCorner.X-(CurrentTextRect.UpperLeftCorner.X+cStart);
} setTextRect(cursLine);
else if ( CurrentTextRect.UpperLeftCorner.X+cEnd > FrameRect.LowerRightCorner.X)
{ // TODO: should show more characters to the left when we're scrolling left
// cursor to the right of the clipping area // and the cursor reaches the border.
HScrollPos += (CurrentTextRect.UpperLeftCorner.X+cEnd)-FrameRect.LowerRightCorner.X; }
setTextRect(cursLine); else if ( CurrentTextRect.UpperLeftCorner.X+cEnd > FrameRect.LowerRightCorner.X)
} {
} // cursor to the right of the clipping area
HScrollPos += (CurrentTextRect.UpperLeftCorner.X+cEnd)-FrameRect.LowerRightCorner.X;
// calculate vertical scrolling setTextRect(cursLine);
if (hasBrokenText) }
{ }
irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerningHeight();
// only up to 1 line fits? // calculate vertical scrolling
if ( lineHeight >= (irr::u32)FrameRect.getHeight() ) if (hasBrokenText)
{ {
VScrollPos = 0; irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerningHeight();
setTextRect(cursLine); // only up to 1 line fits?
s32 unscrolledPos = CurrentTextRect.UpperLeftCorner.Y; if ( lineHeight >= (irr::u32)FrameRect.getHeight() )
s32 pivot = FrameRect.UpperLeftCorner.Y; {
switch (VAlign) VScrollPos = 0;
{ setTextRect(cursLine);
case EGUIA_CENTER: s32 unscrolledPos = CurrentTextRect.UpperLeftCorner.Y;
pivot += FrameRect.getHeight()/2; s32 pivot = FrameRect.UpperLeftCorner.Y;
unscrolledPos += lineHeight/2; switch (VAlign)
break; {
case EGUIA_LOWERRIGHT: case EGUIA_CENTER:
pivot += FrameRect.getHeight(); pivot += FrameRect.getHeight()/2;
unscrolledPos += lineHeight; unscrolledPos += lineHeight/2;
break; break;
default: case EGUIA_LOWERRIGHT:
break; pivot += FrameRect.getHeight();
} unscrolledPos += lineHeight;
VScrollPos = unscrolledPos-pivot; break;
setTextRect(cursLine); default:
} break;
else }
{ VScrollPos = unscrolledPos-pivot;
// First 2 checks are necessary when people delete lines setTextRect(cursLine);
setTextRect(0); }
if ( CurrentTextRect.UpperLeftCorner.Y > FrameRect.UpperLeftCorner.Y && VAlign != EGUIA_LOWERRIGHT) else
{ {
// first line is leaving a gap on top // First 2 checks are necessary when people delete lines
VScrollPos = 0; setTextRect(0);
} if ( CurrentTextRect.UpperLeftCorner.Y > FrameRect.UpperLeftCorner.Y && VAlign != EGUIA_LOWERRIGHT)
else if (VAlign != EGUIA_UPPERLEFT) {
{ // first line is leaving a gap on top
u32 lastLine = BrokenTextPositions.empty() ? 0 : BrokenTextPositions.size()-1; VScrollPos = 0;
setTextRect(lastLine); }
if ( CurrentTextRect.LowerRightCorner.Y < FrameRect.LowerRightCorner.Y) else if (VAlign != EGUIA_UPPERLEFT)
{ {
// last line is leaving a gap on bottom u32 lastLine = BrokenTextPositions.empty() ? 0 : BrokenTextPositions.size()-1;
VScrollPos -= FrameRect.LowerRightCorner.Y-CurrentTextRect.LowerRightCorner.Y; setTextRect(lastLine);
} if ( CurrentTextRect.LowerRightCorner.Y < FrameRect.LowerRightCorner.Y)
} {
// last line is leaving a gap on bottom
setTextRect(cursLine); VScrollPos -= FrameRect.LowerRightCorner.Y-CurrentTextRect.LowerRightCorner.Y;
if ( CurrentTextRect.UpperLeftCorner.Y < FrameRect.UpperLeftCorner.Y ) }
{ }
// text above valid area
VScrollPos -= FrameRect.UpperLeftCorner.Y-CurrentTextRect.UpperLeftCorner.Y; setTextRect(cursLine);
setTextRect(cursLine); if ( CurrentTextRect.UpperLeftCorner.Y < FrameRect.UpperLeftCorner.Y )
} {
else if ( CurrentTextRect.LowerRightCorner.Y > FrameRect.LowerRightCorner.Y) // text above valid area
{ VScrollPos -= FrameRect.UpperLeftCorner.Y-CurrentTextRect.UpperLeftCorner.Y;
// text below valid area setTextRect(cursLine);
VScrollPos += CurrentTextRect.LowerRightCorner.Y-FrameRect.LowerRightCorner.Y; }
setTextRect(cursLine); else if ( CurrentTextRect.LowerRightCorner.Y > FrameRect.LowerRightCorner.Y)
} {
} // text below valid area
} VScrollPos += CurrentTextRect.LowerRightCorner.Y-FrameRect.LowerRightCorner.Y;
} setTextRect(cursLine);
}
void CGUIEditBox::calculateFrameRect() }
{ }
FrameRect = AbsoluteRect; }
IGUISkin *skin = 0;
if (Environment) void CGUIEditBox::calculateFrameRect()
skin = Environment->getSkin(); {
if (Border && skin) FrameRect = AbsoluteRect;
{ IGUISkin *skin = 0;
FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; if (Environment)
FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; skin = Environment->getSkin();
FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; if (Border && skin)
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; {
} FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
} FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
//! set text markers FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
void CGUIEditBox::setTextMarkers(s32 begin, s32 end) }
{ }
if ( begin != MarkBegin || end != MarkEnd )
{ //! set text markers
MarkBegin = begin; void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
MarkEnd = end; {
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); if ( begin != MarkBegin || end != MarkEnd )
} {
} MarkBegin = begin;
MarkEnd = end;
//! send some gui event to parent sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) }
{ }
if ( Parent )
{ //! send some gui event to parent
SEvent e; void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
e.EventType = EET_GUI_EVENT; {
e.GUIEvent.Caller = this; if ( Parent )
e.GUIEvent.Element = 0; {
e.GUIEvent.EventType = type; SEvent e;
e.EventType = EET_GUI_EVENT;
Parent->OnEvent(e); e.GUIEvent.Caller = this;
} e.GUIEvent.Element = 0;
} e.GUIEvent.EventType = type;
//! Writes attributes of the element. Parent->OnEvent(e);
void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const }
{ }
// IGUIEditBox::serializeAttributes(out,options);
//! Writes attributes of the element.
out->addBool ("Border", Border); void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
out->addBool ("Background", Background); {
out->addBool ("OverrideColorEnabled", OverrideColorEnabled ); // IGUIEditBox::serializeAttributes(out,options);
out->addColor ("OverrideColor", OverrideColor);
// out->addFont("OverrideFont", OverrideFont); out->addBool ("Border", Border);
out->addInt ("MaxChars", Max); out->addBool ("Background", Background);
out->addBool ("WordWrap", WordWrap); out->addBool ("OverrideColorEnabled", OverrideColorEnabled );
out->addBool ("MultiLine", MultiLine); out->addColor ("OverrideColor", OverrideColor);
out->addBool ("AutoScroll", AutoScroll); // out->addFont("OverrideFont", OverrideFont);
out->addBool ("PasswordBox", PasswordBox); out->addInt ("MaxChars", Max);
core::stringw ch = L" "; out->addBool ("WordWrap", WordWrap);
ch[0] = PasswordChar; out->addBool ("MultiLine", MultiLine);
out->addString("PasswordChar", ch.c_str()); out->addBool ("AutoScroll", AutoScroll);
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addBool ("PasswordBox", PasswordBox);
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); core::stringw ch = L" ";
ch[0] = PasswordChar;
IGUIEditBox::serializeAttributes(out,options); out->addString("PasswordChar", ch.c_str());
} out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
//! Reads attributes of the element IGUIEditBox::serializeAttributes(out,options);
void CGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) }
{
IGUIEditBox::deserializeAttributes(in,options);
//! Reads attributes of the element
setDrawBorder( in->getAttributeAsBool("Border") ); void CGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
setDrawBackground( in->getAttributeAsBool("Background") ); {
setOverrideColor(in->getAttributeAsColor("OverrideColor")); IGUIEditBox::deserializeAttributes(in,options);
enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
setMax(in->getAttributeAsInt("MaxChars")); setDrawBorder( in->getAttributeAsBool("Border") );
setWordWrap(in->getAttributeAsBool("WordWrap")); setDrawBackground( in->getAttributeAsBool("Background") );
setMultiLine(in->getAttributeAsBool("MultiLine")); setOverrideColor(in->getAttributeAsColor("OverrideColor"));
setAutoScroll(in->getAttributeAsBool("AutoScroll")); enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
core::stringw ch = in->getAttributeAsStringW("PasswordChar"); setMax(in->getAttributeAsInt("MaxChars"));
setWordWrap(in->getAttributeAsBool("WordWrap"));
if (!ch.size()) setMultiLine(in->getAttributeAsBool("MultiLine"));
setPasswordBox(in->getAttributeAsBool("PasswordBox")); setAutoScroll(in->getAttributeAsBool("AutoScroll"));
else core::stringw ch = in->getAttributeAsStringW("PasswordChar");
setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]);
if (!ch.size())
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), setPasswordBox(in->getAttributeAsBool("PasswordBox"));
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); else
setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]);
// setOverrideFont(in->getAttributeAsFont("OverrideFont"));
} setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
} // end namespace gui // setOverrideFont(in->getAttributeAsFont("OverrideFont"));
} // end namespace irr }
#endif // _IRR_COMPILE_WITH_GUI_
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
// Copyright (C) 2005-2006 Etienne Petitjean // Copyright (C) 2005-2006 Etienne Petitjean
// Copyright (C) 2007-2012 Christian Stehno // Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h // For conditions of distribution and use, see copyright notice in Irrlicht.h
#include "IrrCompileConfig.h" #include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "CIrrDeviceMacOSX.h" #import "CIrrDeviceMacOSX.h"
@interface AppDelegate : NSObject @interface AppDelegate : NSTextView <NSApplicationDelegate>
{ {
BOOL _quit; BOOL _quit;
irr::CIrrDeviceMacOSX *_device; irr::CIrrDeviceMacOSX *_device;
} }
- (id)initWithDevice:(irr::CIrrDeviceMacOSX *)device; - (id)initWithDevice:(irr::CIrrDeviceMacOSX *)device;
- (BOOL)isQuit; - (BOOL)isQuit;
@end @end
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_ #endif // _IRR_COMPILE_WITH_OSX_DEVICE_
// Copyright (C) 2005-2006 Etienne Petitjean // Copyright (C) 2005-2006 Etienne Petitjean
// Copyright (C) 2007-2012 Christian Stehno // Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h // For conditions of distribution and use, see copyright notice in Irrlicht.h
#import "AppDelegate.h" #import "AppDelegate.h"
#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_
@implementation AppDelegate @implementation AppDelegate
- (id)initWithDevice:(irr::CIrrDeviceMacOSX *)device - (id)initWithDevice:(irr::CIrrDeviceMacOSX *)device
{ {
self = [super init]; self = [super init];
if (self) _device = device; if (self) _device = device;
return (self); return (self);
} }
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{ {
_quit = FALSE; _quit = FALSE;
} }
- (void)orderFrontStandardAboutPanel:(id)sender - (void)orderFrontStandardAboutPanel:(id)sender
{ {
[NSApp orderFrontStandardAboutPanel:sender]; [NSApp orderFrontStandardAboutPanel:sender];
} }
- (void)unhideAllApplications:(id)sender - (void)unhideAllApplications:(id)sender
{ {
[NSApp unhideAllApplications:sender]; [NSApp unhideAllApplications:sender];
} }
- (void)hide:(id)sender - (void)hide:(id)sender
{ {
[NSApp hide:sender]; [NSApp hide:sender];
} }
- (void)hideOtherApplications:(id)sender - (void)hideOtherApplications:(id)sender
{ {
[NSApp hideOtherApplications:sender]; [NSApp hideOtherApplications:sender];
} }
- (void)terminate:(id)sender - (void)terminate:(id)sender
{ {
_quit = TRUE; _quit = TRUE;
} }
- (void)windowWillClose:(id)sender - (void)windowWillClose:(id)sender
{ {
_quit = TRUE; _quit = TRUE;
} }
- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
{ {
if (_device->isResizable()) if (_device->isResizable())
return proposedFrameSize; return proposedFrameSize;
else else
return [window frame].size; return [window frame].size;
} }
- (void)windowDidResize:(NSNotification *)aNotification - (void)windowDidResize:(NSNotification *)aNotification
{ {
NSWindow *window; NSWindow *window;
NSRect frame; NSRect frame;
window = [aNotification object]; window = [aNotification object];
frame = [window frame]; frame = [window frame];
_device->setResize((int)frame.size.width,(int)frame.size.height); _device->setResize((int)frame.size.width,(int)frame.size.height);
} }
- (BOOL)isQuit - (BOOL)isQuit
{ {
return (_quit); return (_quit);
} }
@end
- (void)keyDown:(NSEvent *)event
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_ {
[self interpretKeyEvents:@[event]];
}
- (void)insertText:(id)string
{
[self setString: @""];
if ([string isKindOfClass:[NSAttributedString class]])
{
_device->handleInputEvent([[string string] UTF8String]);
}
else
{
_device->handleInputEvent([string UTF8String]);
}
}
- (void)doCommandBySelector:(SEL)selector
{
_device->processKeyEvent();
}
@end
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_
// Copyright (C) 2005-2006 Etienne Petitjean // Copyright (C) 2005-2006 Etienne Petitjean
// Copyright (C) 2007-2012 Christian Stehno // Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h // For conditions of distribution and use, see copyright notice in Irrlicht.h
#ifndef __C_IRR_DEVICE_MACOSX_H_INCLUDED__ #ifndef __C_IRR_DEVICE_MACOSX_H_INCLUDED__
#define __C_IRR_DEVICE_MACOSX_H_INCLUDED__ #define __C_IRR_DEVICE_MACOSX_H_INCLUDED__
#include "IrrCompileConfig.h" #include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_
#import <AppKit/NSWindow.h> #import <AppKit/NSWindow.h>
#import <AppKit/NSOpenGL.h> #import <AppKit/NSOpenGL.h>
#import <AppKit/NSBitmapImageRep.h> #import <AppKit/NSBitmapImageRep.h>
#include "CIrrDeviceStub.h" #include "CIrrDeviceStub.h"
#include "IrrlichtDevice.h" #include "IrrlichtDevice.h"
#include "IImagePresenter.h" #include "IImagePresenter.h"
#include "IGUIEnvironment.h" #include "IGUIEnvironment.h"
#include "ICursorControl.h" #include "ICursorControl.h"
#include <OpenGL/OpenGL.h> #include <OpenGL/OpenGL.h>
#include <map> #include <map>
namespace irr namespace irr
{ {
class CIrrDeviceMacOSX : public CIrrDeviceStub, video::IImagePresenter class CIrrDeviceMacOSX : public CIrrDeviceStub, video::IImagePresenter
{ {
public: public:
//! constructor //! constructor
CIrrDeviceMacOSX(const SIrrlichtCreationParameters& params); CIrrDeviceMacOSX(const SIrrlichtCreationParameters& params);
//! destructor //! destructor
virtual ~CIrrDeviceMacOSX(); virtual ~CIrrDeviceMacOSX();
//! runs the device. Returns false if device wants to be deleted //! runs the device. Returns false if device wants to be deleted
virtual bool run(); virtual bool run();
//! Cause the device to temporarily pause execution and let other processes to run //! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht // This should bring down processor usage without major performance loss for Irrlicht
virtual void yield(); virtual void yield();
//! Pause execution and let other processes to run for a specified amount of time. //! Pause execution and let other processes to run for a specified amount of time.
virtual void sleep(u32 timeMs, bool pauseTimer); virtual void sleep(u32 timeMs, bool pauseTimer);
//! sets the caption of the window //! sets the caption of the window
virtual void setWindowCaption(const wchar_t* text); virtual void setWindowCaption(const wchar_t* text);
//! returns if window is active. if not, nothing need to be drawn //! returns if window is active. if not, nothing need to be drawn
virtual bool isWindowActive() const; virtual bool isWindowActive() const;
//! Checks if the Irrlicht window has focus //! Checks if the Irrlicht window has focus
virtual bool isWindowFocused() const; virtual bool isWindowFocused() const;
//! Checks if the Irrlicht window is minimized //! Checks if the Irrlicht window is minimized
virtual bool isWindowMinimized() const; virtual bool isWindowMinimized() const;
//! presents a surface in the client area //! presents a surface in the client area
virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0 ); virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0 );
//! notifies the device that it should close itself //! notifies the device that it should close itself
virtual void closeDevice(); virtual void closeDevice();
//! Sets if the window should be resizable in windowed mode. //! Sets if the window should be resizable in windowed mode.
virtual void setResizable(bool resize); virtual void setResizable(bool resize);
//! Returns true if the window is resizable, false if not //! Returns true if the window is resizable, false if not
virtual bool isResizable() const; virtual bool isResizable() const;
//! Minimizes the window if possible //! Minimizes the window if possible
virtual void minimizeWindow(); virtual void minimizeWindow();
//! Maximizes the window if possible. //! Maximizes the window if possible.
virtual void maximizeWindow(); virtual void maximizeWindow();
//! Restore the window to normal size if possible. //! Restore the window to normal size if possible.
virtual void restoreWindow(); virtual void restoreWindow();
//! Activate any joysticks, and generate events for them. //! Activate any joysticks, and generate events for them.
virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo); virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo);
//! \return Returns a pointer to a list with all video modes //! \return Returns a pointer to a list with all video modes
//! supported by the gfx adapter. //! supported by the gfx adapter.
virtual video::IVideoModeList* getVideoModeList(); virtual video::IVideoModeList* getVideoModeList();
//! Get the device type //! Get the device type
virtual E_DEVICE_TYPE getType() const virtual E_DEVICE_TYPE getType() const
{ {
return EIDT_OSX; return EIDT_OSX;
} }
void flush(); void flush();
void setMouseLocation(int x, int y); void setMouseLocation(int x, int y);
void setResize(int width, int height); void setResize(int width, int height);
void setCursorVisible(bool visible); void setCursorVisible(bool visible);
void handleInputEvent(const char *str);
private: void processKeyEvent();
//! create the driver private:
void createDriver();
//! create the driver
//! Implementation of the macos x cursor control void createDriver();
class CCursorControl : public gui::ICursorControl
{ //! Implementation of the macos x cursor control
public: class CCursorControl : public gui::ICursorControl
{
CCursorControl(const core::dimension2d<u32>& wsize, CIrrDeviceMacOSX *device) public:
: WindowSize(wsize), IsVisible(true), InvWindowSize(0.0f, 0.0f), Device(device), UseReferenceRect(false)
{ CCursorControl(const core::dimension2d<u32>& wsize, CIrrDeviceMacOSX *device)
CursorPos.X = CursorPos.Y = 0; : WindowSize(wsize), IsVisible(true), InvWindowSize(0.0f, 0.0f), Device(device), UseReferenceRect(false)
if (WindowSize.Width!=0) {
InvWindowSize.Width = 1.0f / WindowSize.Width; CursorPos.X = CursorPos.Y = 0;
if (WindowSize.Height!=0) if (WindowSize.Width!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height; InvWindowSize.Width = 1.0f / WindowSize.Width;
} if (WindowSize.Height!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height;
//! Changes the visible state of the mouse cursor. }
virtual void setVisible(bool visible)
{ //! Changes the visible state of the mouse cursor.
IsVisible = visible; virtual void setVisible(bool visible)
Device->setCursorVisible(visible); {
} IsVisible = visible;
Device->setCursorVisible(visible);
//! Returns if the cursor is currently visible. }
virtual bool isVisible() const
{ //! Returns if the cursor is currently visible.
return IsVisible; virtual bool isVisible() const
} {
return IsVisible;
//! Sets the new position of the cursor. }
virtual void setPosition(const core::position2d<f32> &pos)
{ //! Sets the new position of the cursor.
setPosition(pos.X, pos.Y); virtual void setPosition(const core::position2d<f32> &pos)
} {
setPosition(pos.X, pos.Y);
//! Sets the new position of the cursor. }
virtual void setPosition(f32 x, f32 y)
{ //! Sets the new position of the cursor.
setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height)); virtual void setPosition(f32 x, f32 y)
} {
setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height));
//! Sets the new position of the cursor. }
virtual void setPosition(const core::position2d<s32> &pos)
{ //! Sets the new position of the cursor.
if (CursorPos.X != pos.X || CursorPos.Y != pos.Y) virtual void setPosition(const core::position2d<s32> &pos)
setPosition(pos.X, pos.Y); {
} if (CursorPos.X != pos.X || CursorPos.Y != pos.Y)
setPosition(pos.X, pos.Y);
//! Sets the new position of the cursor. }
virtual void setPosition(s32 x, s32 y)
{ //! Sets the new position of the cursor.
if (UseReferenceRect) virtual void setPosition(s32 x, s32 y)
{ {
Device->setMouseLocation(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y); if (UseReferenceRect)
} {
else Device->setMouseLocation(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y);
{ }
Device->setMouseLocation(x,y); else
} {
} Device->setMouseLocation(x,y);
}
//! Returns the current position of the mouse cursor. }
virtual const core::position2d<s32>& getPosition()
{ //! Returns the current position of the mouse cursor.
return CursorPos; virtual const core::position2d<s32>& getPosition()
} {
return CursorPos;
//! Returns the current position of the mouse cursor. }
virtual core::position2d<f32> getRelativePosition()
{ //! Returns the current position of the mouse cursor.
if (!UseReferenceRect) virtual core::position2d<f32> getRelativePosition()
{ {
return core::position2d<f32>(CursorPos.X * InvWindowSize.Width, if (!UseReferenceRect)
CursorPos.Y * InvWindowSize.Height); {
} return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
CursorPos.Y * InvWindowSize.Height);
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(), }
CursorPos.Y / (f32)ReferenceRect.getHeight());
} return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
//! Sets an absolute reference rect for calculating the cursor position. }
virtual void setReferenceRect(core::rect<s32>* rect=0)
{ //! Sets an absolute reference rect for calculating the cursor position.
if (rect) virtual void setReferenceRect(core::rect<s32>* rect=0)
{ {
ReferenceRect = *rect; if (rect)
UseReferenceRect = true; {
ReferenceRect = *rect;
// prevent division through zero and uneven sizes UseReferenceRect = true;
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2) // prevent division through zero and uneven sizes
ReferenceRect.LowerRightCorner.Y += 1;
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2) ReferenceRect.LowerRightCorner.Y += 1;
ReferenceRect.LowerRightCorner.X += 1;
} if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
else ReferenceRect.LowerRightCorner.X += 1;
UseReferenceRect = false; }
} else
UseReferenceRect = false;
//! Updates the internal cursor position }
void updateInternalCursorPosition(int x,int y)
{ //! Updates the internal cursor position
CursorPos.X = x; void updateInternalCursorPosition(int x,int y)
CursorPos.Y = y; {
} CursorPos.X = x;
CursorPos.Y = y;
private: }
core::position2d<s32> CursorPos; private:
core::dimension2d<s32> WindowSize;
core::dimension2d<float> InvWindowSize; core::position2d<s32> CursorPos;
core::rect<s32> ReferenceRect; core::dimension2d<s32> WindowSize;
CIrrDeviceMacOSX *Device; core::dimension2d<float> InvWindowSize;
bool IsVisible; core::rect<s32> ReferenceRect;
bool UseReferenceRect; CIrrDeviceMacOSX *Device;
}; bool IsVisible;
bool UseReferenceRect;
bool createWindow(); };
void initKeycodes();
void storeMouseLocation(); bool createWindow();
void postMouseEvent(void *event, irr::SEvent &ievent); void initKeycodes();
void postKeyEvent(void *event, irr::SEvent &ievent, bool pressed); void storeMouseLocation();
void pollJoysticks(); void postMouseEvent(void *event, irr::SEvent &ievent);
void postKeyEvent(void *event, irr::SEvent &ievent, bool pressed);
NSWindow *Window; void pollJoysticks();
CGLContextObj CGLContext;
NSOpenGLContext *OGLContext; NSWindow *Window;
NSBitmapImageRep *SoftwareDriverTarget; CGLContextObj CGLContext;
std::map<int,int> KeyCodes; NSOpenGLContext *OGLContext;
int DeviceWidth; NSBitmapImageRep *SoftwareDriverTarget;
int DeviceHeight; std::map<int,int> KeyCodes;
int ScreenWidth; int DeviceWidth;
int ScreenHeight; int DeviceHeight;
u32 MouseButtonStates; int ScreenWidth;
u32 SoftwareRendererType; int ScreenHeight;
bool IsFullscreen; u32 MouseButtonStates;
bool IsActive; u32 SoftwareRendererType;
bool IsShiftDown; bool IsFullscreen;
bool IsControlDown; bool IsActive;
bool IsResizable; bool IsShiftDown;
}; bool IsControlDown;
bool IsResizable;
};
} // end namespace irr
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_ } // end namespace irr
#endif // __C_IRR_DEVICE_MACOSX_H_INCLUDED__
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_
#endif // __C_IRR_DEVICE_MACOSX_H_INCLUDED__
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright (C) 2005-2006 Etienne Petitjean // Copyright (C) 2005-2006 Etienne Petitjean
// Copyright (C) 2007-2012 Christian Stehno // Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h // For conditions of distribution and use, see copyright notice in Irrlicht.h
#include "OSXClipboard.h" #include "OSXClipboard.h"
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
void OSXCopyToClipboard(const char *text) void OSXCopyToClipboard(const char *text)
{ {
NSString *str; NSString *str;
NSPasteboard *board; NSPasteboard *board;
if ((text != NULL) && (strlen(text) > 0)) if ((text != NULL) && (strlen(text) > 0))
{ {
str = [NSString stringWithCString:text encoding:NSWindowsCP1252StringEncoding]; str = [NSString stringWithUTF8String:text];
board = [NSPasteboard generalPasteboard]; board = [NSPasteboard generalPasteboard];
[board declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:NSApp]; [board declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:NSApp];
[board setString:str forType:NSStringPboardType]; [board setString:str forType:NSStringPboardType];
} }
} }
char* OSXCopyFromClipboard() char* OSXCopyFromClipboard()
{ {
NSString* str; NSString* str;
NSPasteboard* board; NSPasteboard* board;
char* result; char* result;
result = NULL; result = NULL;
board = [NSPasteboard generalPasteboard]; board = [NSPasteboard generalPasteboard];
str = [board stringForType:NSStringPboardType]; str = [board stringForType:NSStringPboardType];
if (str != nil) if (str != nil)
result = (char*)[str cStringUsingEncoding:NSWindowsCP1252StringEncoding]; result = (char*)[str UTF8String];
return (result); return (result);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment