Palmer Truelson 2010-02-23 17:19:58 -08:00
commit 54a95f706f
1604 changed files with 40150 additions and 19622 deletions

View File

@ -171,8 +171,8 @@ if (LINUX)
if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
# linking can be so slow - give us a chance to figure out why
set(CMAKE_CXX_LINK_FLAGS "-Wl,--stats,--no-keep-memory")
# linking can be very memory-hungry, especially the final viewer link
set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
endif (NOT STANDALONE)
endif (VIEWER)

View File

@ -54,7 +54,10 @@ else (STANDALONE)
endif (WINDOWS)
set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/apr-1)
if (LINUX AND VIEWER)
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid)
endif (LINUX AND VIEWER)
if (LINUX)
if (VIEWER)
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid)
endif (VIEWER)
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} rt)
endif (LINUX)
endif (STANDALONE)

View File

@ -38,12 +38,12 @@ else (STANDALONE)
debug libboost_signals-vc80-mt-gd-${BOOST_VERSION})
endif (MSVC71)
elseif (DARWIN)
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt)
set(BOOST_REGEX_LIBRARY boost_regex-mt)
set(BOOST_SIGNALS_LIBRARY boost_signals-mt)
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-xgcc40-mt)
set(BOOST_REGEX_LIBRARY boost_regex-xgcc40-mt)
set(BOOST_SIGNALS_LIBRARY boost_signals-xgcc40-mt)
elseif (LINUX)
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt)
set(BOOST_REGEX_LIBRARY boost_regex-mt)
set(BOOST_SIGNALS_LIBRARY boost_signals-mt)
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-gcc41-mt)
set(BOOST_REGEX_LIBRARY boost_regex-gcc41-mt)
set(BOOST_SIGNALS_LIBRARY boost_signals-gcc41-mt)
endif (WINDOWS)
endif (STANDALONE)

View File

@ -0,0 +1,23 @@
# -*- cmake -*-
if (VIEWER)
set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off")
if (OS_DRAG_DROP)
if (WINDOWS)
add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
endif (WINDOWS)
if (DARWIN)
add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
endif (DARWIN)
if (LINUX)
add_definitions(-DLL_OS_DRAGDROP_ENABLED=0)
endif (LINUX)
endif (OS_DRAG_DROP)
endif (VIEWER)

View File

@ -24,7 +24,6 @@ elseif (LINUX)
gmodule-2.0
dl
gthread-2.0
rt
glib-2.0
)
endif (STANDALONE)

View File

@ -0,0 +1,28 @@
# -*- cmake -*-
include(Prebuilt)
if (STANDALONE)
include(FindPkgConfig)
pkg_check_modules(PULSEAUDIO REQUIRED libpulse-mainloop-glib)
elseif (LINUX)
use_prebuilt_binary(pulseaudio)
set(PULSEAUDIO_FOUND ON FORCE BOOL)
set(PULSEAUDIO_INCLUDE_DIRS
${LIBS_PREBUILT_DIR}/include
)
# We don't need to explicitly link against pulseaudio itself, because
# the viewer probes for the system's copy at runtime.
set(PULSEAUDIO_LIBRARIES
# none needed!
)
endif (STANDALONE)
if (PULSEAUDIO_FOUND)
set(PULSEAUDIO ON CACHE BOOL "Build with PulseAudio support, if available.")
endif (PULSEAUDIO_FOUND)
if (PULSEAUDIO)
add_definitions(-DLL_PULSEAUDIO_ENABLED=1)
endif (PULSEAUDIO)

View File

@ -54,12 +54,5 @@ target_link_libraries(linux-crash-logger
${DB_LIBRARIES}
)
add_custom_command(
OUTPUT linux-crash-logger-stripped
COMMAND strip
ARGS --strip-debug -o linux-crash-logger-stripped linux-crash-logger
DEPENDS linux-crash-logger
)
add_custom_target(linux-crash-logger-strip-target ALL
DEPENDS linux-crash-logger-stripped)
add_custom_target(linux-crash-logger-target ALL
DEPENDS linux-crash-logger)

View File

@ -47,12 +47,5 @@ target_link_libraries(linux-updater
${LLCOMMON_LIBRARIES}
)
add_custom_command(
OUTPUT linux-updater-stripped
COMMAND strip
ARGS --strip-debug -o linux-updater-stripped linux-updater
DEPENDS linux-updater
)
add_custom_target(linux-updater-strip-target ALL
DEPENDS linux-updater-stripped)
add_custom_target(linux-updater-target ALL
DEPENDS linux-updater)

View File

@ -181,6 +181,8 @@ LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &
mFileHandle = LLLFSThread::nullHandle();
#endif
// No default value for mVF, it's an ogg structure?
// Hey, let's zero it anyway, for predictability.
memset(&mVF, 0, sizeof(mVF));
}
LLVorbisDecodeState::~LLVorbisDecodeState()

View File

@ -202,12 +202,12 @@ void LLAudioEngine::updateInternetStream()
}
// virtual
int LLAudioEngine::isInternetStreamPlaying()
LLAudioEngine::LLAudioPlayState LLAudioEngine::isInternetStreamPlaying()
{
if (mStreamingAudioImpl)
return mStreamingAudioImpl->isPlaying();
return (LLAudioEngine::LLAudioPlayState) mStreamingAudioImpl->isPlaying();
return 0; // Stopped
return LLAudioEngine::AUDIO_STOPPED; // Stopped
}

View File

@ -91,6 +91,15 @@ public:
AUDIO_TYPE_COUNT = 4 // last
};
enum LLAudioPlayState
{
// isInternetStreamPlaying() returns an *int*, with
// 0 = stopped, 1 = playing, 2 = paused.
AUDIO_STOPPED = 0,
AUDIO_PLAYING = 1,
AUDIO_PAUSED = 2
};
LLAudioEngine();
virtual ~LLAudioEngine();
@ -156,7 +165,7 @@ public:
void stopInternetStream();
void pauseInternetStream(int pause);
void updateInternetStream(); // expected to be called often
int isInternetStreamPlaying();
LLAudioPlayState isInternetStreamPlaying();
// use a value from 0.0 to 1.0, inclusive
void setInternetStreamGain(F32 vol);
std::string getInternetStreamURL();

View File

@ -181,16 +181,18 @@ void LLCharacter::requestStopMotion( LLMotion* motion)
// updateMotions()
//-----------------------------------------------------------------------------
static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation");
static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim");
void LLCharacter::updateMotions(e_update_t update_type)
{
LLFastTimer t(FTM_UPDATE_ANIMATION);
if (update_type == HIDDEN_UPDATE)
{
LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION);
mMotionController.updateMotionsMinimal();
}
else
{
LLFastTimer t(FTM_UPDATE_ANIMATION);
// unpause if the number of outstanding pause requests has dropped to the initial one
if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1)
{

View File

@ -221,7 +221,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
if (!target.isFinite())
{
llerrs << "Non finite target in editing motion with target distance of " << target_dist <<
" and focus point " << focus_pt << " and pointAtPt: " << *pointAtPt << llendl;
" and focus point " << focus_pt << llendl;
}
mTarget.setPosition( target + mParentJoint.getPosition());

View File

@ -50,6 +50,7 @@ set(llcommon_SOURCE_FILES
lleventdispatcher.cpp
lleventfilter.cpp
llevents.cpp
lleventtimer.cpp
llfasttimer_class.cpp
llfile.cpp
llfindlocale.cpp
@ -164,7 +165,6 @@ set(llcommon_HEADER_FILES
llhttpstatuscodes.h
llindexedqueue.h
llinstancetracker.h
llinstancetracker.h
llkeythrottle.h
lllazy.h
lllistenerwrapper.h

View File

@ -41,7 +41,7 @@
#include "lllivefile.h"
#include "llmemory.h"
#include "llstl.h" // for DeletePointer()
#include "lltimer.h"
#include "lleventtimer.h"
//
// Signal handling

View File

@ -68,7 +68,8 @@ typedef enum e_chat_audible_level
typedef enum e_chat_style
{
CHAT_STYLE_NORMAL,
CHAT_STYLE_IRC
CHAT_STYLE_IRC,
CHAT_STYLE_HISTORY
}EChatStyle;
// A piece of chat

View File

@ -0,0 +1,95 @@
/**
* @file lleventtimer.cpp
* @brief Cross-platform objects for doing timing
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lleventtimer.h"
#include "u64.h"
//////////////////////////////////////////////////////////////////////////////
//
// LLEventTimer Implementation
//
//////////////////////////////////////////////////////////////////////////////
LLEventTimer::LLEventTimer(F32 period)
: mEventTimer()
{
mPeriod = period;
}
LLEventTimer::LLEventTimer(const LLDate& time)
: mEventTimer()
{
mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
}
LLEventTimer::~LLEventTimer()
{
}
//static
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
{
LLInstanceTrackerScopedGuard guard;
for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); )
{
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();
if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
timer.mEventTimer.reset();
if ( timer.tick() )
{
completed_timers.push_back( &timer );
}
}
}
}
if ( completed_timers.size() > 0 )
{
for (std::list<LLEventTimer*>::iterator completed_iter = completed_timers.begin();
completed_iter != completed_timers.end();
completed_iter++ )
{
delete *completed_iter;
}
}
}

View File

@ -0,0 +1,60 @@
/**
* @file lleventtimer.h
* @brief Cross-platform objects for doing timing
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_EVENTTIMER_H
#define LL_EVENTTIMER_H
#include "stdtypes.h"
#include "lldate.h"
#include "llinstancetracker.h"
#include "lltimer.h"
// class for scheduling a function to be called at a given frequency (approximate, inprecise)
class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer>
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();
//function to be called at the supplied frequency
// Normally return FALSE; TRUE will delete the timer after the function returns.
virtual BOOL tick() = 0;
static void updateClass();
protected:
LLTimer mEventTimer;
F32 mPeriod;
};
#endif //LL_EVENTTIMER_H

View File

@ -114,7 +114,11 @@ static timer_tree_dfs_iterator_t end_timer_tree()
class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
{
public:
NamedTimerFactory()
NamedTimerFactory()
: mActiveTimerRoot(NULL),
mTimerRoot(NULL),
mAppTimer(NULL),
mRootFrameState(NULL)
{}
/*virtual */ void initSingleton()
@ -214,9 +218,10 @@ LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
// static
void LLFastTimer::DeclareTimer::updateCachedPointers()
{
DeclareTimer::LLInstanceTrackerScopedGuard guard;
// propagate frame state pointers to timer declarations
for (DeclareTimer::instance_iter it = DeclareTimer::beginInstances();
it != DeclareTimer::endInstances();
for (DeclareTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
// update cached pointer
@ -367,20 +372,23 @@ void LLFastTimer::NamedTimer::buildHierarchy()
if (sCurFrameIndex < 0 ) return;
// set up initial tree
for (instance_iter it = NamedTimer::beginInstances();
it != endInstances();
++it)
{
NamedTimer& timer = *it;
if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
// bootstrap tree construction by attaching to last timer to be on stack
// when this timer was called
if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
timer.setParent(timer.getFrameState().mLastCaller->mTimer);
// no need to push up tree on first use, flag can be set spuriously
timer.getFrameState().mMoveUpTree = false;
NamedTimer& timer = *it;
if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
// bootstrap tree construction by attaching to last timer to be on stack
// when this timer was called
if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
{
timer.setParent(timer.getFrameState().mLastCaller->mTimer);
// no need to push up tree on first use, flag can be set spuriously
timer.getFrameState().mMoveUpTree = false;
}
}
}
@ -482,18 +490,21 @@ void LLFastTimer::NamedTimer::resetFrame()
F64 total_time = 0;
LLSD sd;
for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
it != NamedTimer::endInstances();
++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
total_time = total_time + info.mSelfTimeCounter * iclock_freq;
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
total_time = total_time + info.mSelfTimeCounter * iclock_freq;
}
}
sd["Total"]["Time"] = (LLSD::Real) total_time;
@ -527,21 +538,24 @@ void LLFastTimer::NamedTimer::resetFrame()
DeclareTimer::updateCachedPointers();
// reset for next frame
for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
it != NamedTimer::endInstances();
++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
info.mSelfTimeCounter = 0;
info.mCalls = 0;
info.mLastCaller = NULL;
info.mMoveUpTree = false;
// update parent pointer in timer state struct
if (timer.mParent)
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
info.mParent = &timer.mParent->getFrameState();
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
info.mSelfTimeCounter = 0;
info.mCalls = 0;
info.mLastCaller = NULL;
info.mMoveUpTree = false;
// update parent pointer in timer state struct
if (timer.mParent)
{
info.mParent = &timer.mParent->getFrameState();
}
}
}
@ -571,20 +585,23 @@ void LLFastTimer::NamedTimer::reset()
}
// reset all history
for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
it != NamedTimer::endInstances();
++it)
{
NamedTimer& timer = *it;
if (&timer != NamedTimerFactory::instance().getRootTimer())
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
timer.setParent(NamedTimerFactory::instance().getRootTimer());
NamedTimer& timer = *it;
if (&timer != NamedTimerFactory::instance().getRootTimer())
{
timer.setParent(NamedTimerFactory::instance().getRootTimer());
}
timer.mCountAverage = 0;
timer.mCallAverage = 0;
memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
timer.mCountAverage = 0;
timer.mCallAverage = 0;
memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
sLastFrameIndex = 0;

View File

@ -0,0 +1,20 @@
/**
* @file lllinstancetracker.cpp
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
* Copyright (c) 2009, Linden Research, Inc.
* $/LicenseInfo$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "llinstancetracker.h"
// STL headers
// std headers
// external library headers
// other Linden headers
// llinstancetracker.h is presently header-only. This file exists only because our CMake
// test macro ADD_BUILD_TEST requires it.
int dummy = 0;

View File

@ -98,7 +98,10 @@ private:
mKey = key;
getMap_()[key] = static_cast<T*>(this);
}
void remove_() { getMap_().erase(mKey); }
void remove_()
{
getMap_().erase(mKey);
}
static InstanceMap& getMap_()
{
@ -129,31 +132,65 @@ public:
/// for completeness of analogy with the generic implementation
static T* getInstance(T* k) { return k; }
static key_iter beginKeys() { return getSet_().begin(); }
static key_iter endKeys() { return getSet_().end(); }
static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
static instance_iter endInstances() { return instance_iter(getSet_().end()); }
static S32 instanceCount() { return getSet_().size(); }
// Instantiate this to get access to iterators for this type. It's a 'guard' in the sense
// that it treats deletes of this type as errors as long as there is an instance of
// this class alive in scope somewhere (i.e. deleting while iterating is bad).
class LLInstanceTrackerScopedGuard
{
public:
LLInstanceTrackerScopedGuard()
{
++sIterationNestDepth;
}
~LLInstanceTrackerScopedGuard()
{
--sIterationNestDepth;
}
static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
static instance_iter endInstances() { return instance_iter(getSet_().end()); }
static key_iter beginKeys() { return getSet_().begin(); }
static key_iter endKeys() { return getSet_().end(); }
};
protected:
LLInstanceTracker() { getSet_().insert(static_cast<T*>(this)); }
virtual ~LLInstanceTracker() { getSet_().erase(static_cast<T*>(this)); }
LLInstanceTracker()
{
// it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle.
//llassert(sIterationNestDepth == 0);
getSet_().insert(static_cast<T*>(this));
}
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
llassert(sIterationNestDepth == 0);
getSet_().erase(static_cast<T*>(this));
}
LLInstanceTracker(const LLInstanceTracker& other) { getSet_().insert(static_cast<T*>(this)); }
LLInstanceTracker(const LLInstanceTracker& other)
{
//llassert(sIterationNestDepth == 0);
getSet_().insert(static_cast<T*>(this));
}
static InstanceSet& getSet_() // called after getReady() but before go()
{
if (! sInstances)
{
sInstances = new InstanceSet;
}
return *sInstances;
}
static InstanceSet& getSet_()
{
if (! sInstances)
{
sInstances = new InstanceSet;
}
return *sInstances;
}
static InstanceSet* sInstances;
static S32 sIterationNestDepth;
};
template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;
template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL;
template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
#endif

View File

@ -33,7 +33,7 @@
#include "lllivefile.h"
#include "llframetimer.h"
#include "lltimer.h"
#include "lleventtimer.h"
const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f;

View File

@ -95,7 +95,6 @@ public:
bool notNull() const { return (mPointer != NULL); }
operator Type*() const { return mPointer; }
operator const Type*() const { return mPointer; }
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }

View File

@ -35,6 +35,17 @@
#include "llerror.h"
LLRefCount::LLRefCount(const LLRefCount& other)
: mRef(0)
{
}
LLRefCount& LLRefCount::operator=(const LLRefCount&)
{
// do nothing, since ref count is specific to *this* reference
return *this;
}
LLRefCount::LLRefCount() :
mRef(0)
{

View File

@ -41,22 +41,20 @@
class LL_COMMON_API LLRefCount
{
private:
LLRefCount(const LLRefCount& other); // no implementation
private:
LLRefCount& operator=(const LLRefCount&); // no implementation
protected:
LLRefCount(const LLRefCount& other);
LLRefCount& operator=(const LLRefCount&);
virtual ~LLRefCount(); // use unref()
public:
LLRefCount();
void ref()
void ref() const
{
mRef++;
}
S32 unref()
S32 unref() const
{
llassert(mRef >= 1);
if (0 == --mRef)
@ -67,13 +65,15 @@ public:
return mRef;
}
//NOTE: when passing around a const LLRefCount object, this can return different results
// at different types, since mRef is mutable
S32 getNumRefs() const
{
return mRef;
}
private:
S32 mRef;
mutable S32 mRef;
};
#endif

View File

@ -139,12 +139,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
case LLSD::TypeBoolean:
ostr << pre << "<boolean>";
if(mBoolAlpha ||
#if( LL_WINDOWS || __GNUC__ > 2)
(ostr.flags() & std::ios::boolalpha)
#else
(ostr.flags() & 0x0100)
#endif
)
)
{
ostr << (data.asBoolean() ? "true" : "false");
}
@ -511,12 +507,7 @@ void LLSDXMLParser::Impl::reset()
mSkipping = false;
#if( LL_WINDOWS || __GNUC__ > 2)
mCurrentKey.clear();
#else
mCurrentKey = std::string();
#endif
XML_ParserReset(mParser, "utf-8");
XML_SetUserData(mParser, this);
@ -644,11 +635,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch
LLSD& newElement = map[mCurrentKey];
mStack.push_back(&newElement);
#if( LL_WINDOWS || __GNUC__ > 2)
mCurrentKey.clear();
#else
mCurrentKey = std::string();
#endif
}
else if (mStack.back()->isArray())
{

View File

@ -555,54 +555,3 @@ void secondsToTimecodeString(F32 current_time, std::string& tcstring)
}
//////////////////////////////////////////////////////////////////////////////
//
// LLEventTimer Implementation
//
//////////////////////////////////////////////////////////////////////////////
LLEventTimer::LLEventTimer(F32 period)
: mEventTimer()
{
mPeriod = period;
}
LLEventTimer::LLEventTimer(const LLDate& time)
: mEventTimer()
{
mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
}
LLEventTimer::~LLEventTimer()
{
}
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
for (instance_iter iter = beginInstances(); iter != endInstances(); )
{
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();
if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
timer.mEventTimer.reset();
if ( timer.tick() )
{
completed_timers.push_back( &timer );
}
}
}
if ( completed_timers.size() > 0 )
{
for (std::list<LLEventTimer*>::iterator completed_iter = completed_timers.begin();
completed_iter != completed_timers.end();
completed_iter++ )
{
delete *completed_iter;
}
}
}

View File

@ -39,8 +39,6 @@
#include <limits.h>
#include "stdtypes.h"
#include "lldate.h"
#include "llinstancetracker.h"
#include <string>
#include <list>
@ -171,25 +169,6 @@ LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_dayli
LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
// class for scheduling a function to be called at a given frequency (approximate, inprecise)
class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer>
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();
//function to be called at the supplied frequency
// Normally return FALSE; TRUE will delete the timer after the function returns.
virtual BOOL tick() = 0;
static void updateClass();
protected:
LLTimer mEventTimer;
F32 mPeriod;
};
U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
#endif

View File

@ -343,20 +343,20 @@ public:
/// Instantiate an LLTreeDFSIter to start a depth-first walk. Pass
/// functors to extract the 'child begin' and 'child end' iterators from
/// each node.
LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
mBeginFunc(beginfunc),
mEndFunc(endfunc),
mSkipChildren(false)
LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc)
: mBeginFunc(beginfunc),
mEndFunc(endfunc),
mSkipChildren(false)
{
// Only push back this node if it's non-NULL!
if (node)
mPending.push_back(node);
}
/// Instantiate an LLTreeDFSIter to mark the end of the walk
LLTreeDFSIter() {}
LLTreeDFSIter() : mSkipChildren(false) {}
/// flags iterator logic to skip traversing children of current node on next increment
void skipDescendants(bool skip = true) { mSkipChildren = skip; }
/// flags iterator logic to skip traversing children of current node on next increment
void skipDescendants(bool skip = true) { mSkipChildren = skip; }
private:
/// leverage boost::iterator_facade
@ -405,8 +405,8 @@ private:
func_type mBeginFunc;
/// functor to extract end() child iterator
func_type mEndFunc;
/// flag which controls traversal of children (skip children of current node if true)
bool mSkipChildren;
/// flag which controls traversal of children (skip children of current node if true)
bool mSkipChildren;
};
/**
@ -451,21 +451,21 @@ public:
/// Instantiate an LLTreeDFSPostIter to start a depth-first walk. Pass
/// functors to extract the 'child begin' and 'child end' iterators from
/// each node.
LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
mBeginFunc(beginfunc),
mEndFunc(endfunc),
mSkipAncestors(false)
{
LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc)
: mBeginFunc(beginfunc),
mEndFunc(endfunc),
mSkipAncestors(false)
{
if (! node)
return;
mPending.push_back(typename list_type::value_type(node, false));
makeCurrent();
}
/// Instantiate an LLTreeDFSPostIter to mark the end of the walk
LLTreeDFSPostIter() {}
LLTreeDFSPostIter() : mSkipAncestors(false) {}
/// flags iterator logic to skip traversing ancestors of current node on next increment
void skipAncestors(bool skip = true) { mSkipAncestors = skip; }
/// flags iterator logic to skip traversing ancestors of current node on next increment
void skipAncestors(bool skip = true) { mSkipAncestors = skip; }
private:
/// leverage boost::iterator_facade

View File

@ -188,6 +188,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
: mWorkerThread(workerthread),
mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()),
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mMutex(NULL),
mWorkFlags(0)
{

View File

@ -138,23 +138,29 @@ namespace tut
keys.insert(&one);
keys.insert(&two);
keys.insert(&three);
for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys());
ki != kend; ++ki)
{
ensure_equals("spurious key", keys.erase(*ki), 1);
}
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::key_iter ki(guard.beginKeys()), kend(guard.endKeys());
ki != kend; ++ki)
{
ensure_equals("spurious key", keys.erase(*ki), 1);
}
}
ensure_equals("unreported key", keys.size(), 0);
KeySet instances;
instances.insert(&one);
instances.insert(&two);
instances.insert(&three);
for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances());
ii != iend; ++ii)
{
Unkeyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::instance_iter ii(guard.beginInstances()), iend(guard.endInstances());
ii != iend; ++ii)
{
Unkeyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
}
ensure_equals("unreported instance", instances.size(), 0);
}
} // namespace tut

View File

@ -676,9 +676,6 @@ void LLImageRaw::copy(LLImageRaw* src)
LLImageRaw* dst = this; // Just for clarity.
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
// No scaling needed

View File

@ -54,9 +54,14 @@ S32 LLImageDecodeThread::update(U32 max_time_ms)
{
creation_info& info = *iter;
ImageRequest* req = new ImageRequest(info.handle, info.image,
info.priority, info.discard, info.needs_aux,
info.responder);
addRequest(req);
info.priority, info.discard, info.needs_aux,
info.responder);
bool res = addRequest(req);
if (!res)
{
llerrs << "request added after LLLFSThread::cleanupClass()" << llendl;
}
}
mCreationList.clear();
S32 res = LLQueuedThread::update(max_time_ms);

View File

@ -97,7 +97,8 @@ void info_callback(const char* msg, void*)
}
LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl()
LLImageJ2COJ::LLImageJ2COJ()
: LLImageJ2CImpl()
{
}

View File

@ -51,9 +51,6 @@ protected:
// Divide a by b to the power of 2 and round upwards.
return (a + (1 << b) - 1) >> b;
}
// Temporary variables for in-progress decodes...
LLImageRaw *mRawImagep;
};
#endif

View File

@ -45,7 +45,8 @@ LLCamera::LLCamera() :
mNearPlane(DEFAULT_NEAR_PLANE),
mFarPlane(DEFAULT_FAR_PLANE),
mFixedDistance(-1.f),
mPlaneCount(6)
mPlaneCount(6),
mFrustumCornerDist(0.f)
{
calculateFrustumPlanes();
}
@ -55,7 +56,8 @@ LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_p
LLCoordFrame(),
mViewHeightInPixels(view_height_in_pixels),
mFixedDistance(-1.f),
mPlaneCount(6)
mPlaneCount(6),
mFrustumCornerDist(0.f)
{
mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
@ -648,7 +650,6 @@ void LLCamera::ignoreAgentFrustumPlane(S32 idx)
void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
{
for (int i = 0; i < 8; i++)
{
mAgentFrustum[i] = frust[i];

View File

@ -3822,6 +3822,7 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices,
// Generate the vertex mapping and the list of vertices without
// duplicates. This will crash if there are no vertices.
llassert(num_input_vertices > 0); // check for no vertices!
S32 *vertex_mapping = new S32[num_input_vertices];
LLVector3 *new_vertices = new LLVector3[num_input_vertices];
LLVertexIndexPair *prev_pairp = NULL;

View File

@ -42,11 +42,14 @@
LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 size) : mHost(host)
{
mSize = 0;
mData[0] = '!';
if (size > NET_BUFFER_SIZE)
{
llerrs << "Sending packet > " << NET_BUFFER_SIZE << " of size " << size << llendl;
}
else // we previously relied on llerrs being fatal to not get here...
else
{
if (datap != NULL)
{

View File

@ -1196,6 +1196,7 @@ LLTransferTarget::LLTransferTarget(
mType(type),
mSourceType(source_type),
mID(transfer_id),
mChannelp(NULL),
mGotInfo(FALSE),
mSize(0),
mLastPacketID(-1)

View File

@ -226,7 +226,10 @@ void LLTransferSourceAsset::responderCallback(LLVFS *vfs, const LLUUID& uuid, LL
LLTransferSourceParamsAsset::LLTransferSourceParamsAsset() : LLTransferSourceParams(LLTST_ASSET)
LLTransferSourceParamsAsset::LLTransferSourceParamsAsset()
: LLTransferSourceParams(LLTST_ASSET),
mAssetType(LLAssetType::AT_NONE)
{
}

View File

@ -40,7 +40,12 @@ typedef void (*LLTTFCompleteCallback)(const LLTSCode status, void *user_data);
class LLTransferTargetParamsFile : public LLTransferTargetParams
{
public:
LLTransferTargetParamsFile() : LLTransferTargetParams(LLTTT_FILE) {}
LLTransferTargetParamsFile()
: LLTransferTargetParams(LLTTT_FILE),
mCompleteCallback(NULL),
mUserData(NULL)
{}
void setFilename(const std::string& filename) { mFilename = filename; }
void setCallback(LLTTFCompleteCallback cb, void *user_data) { mCompleteCallback = cb; mUserData = user_data; }

View File

@ -68,7 +68,6 @@ protected:
LLTTVFCompleteCallback mCompleteCallback;
void* mUserDatap;
S32 mErrCode;
LLVFSThread::handle_t mHandle;
};

View File

@ -4,7 +4,7 @@
* @date 2009-02-26
* @brief Tests of llareslistener.h.
*
* $LicenseInfo:firstyear=2009&license=internal$
* $LicenseInfo:firstyear=2009&license=viewergpl$
* Copyright (c) 2009, Linden Research, Inc.
* $/LicenseInfo$
*/

View File

@ -104,6 +104,8 @@ void LLPluginClassMedia::reset()
mSetMediaHeight = -1;
mRequestedMediaWidth = 0;
mRequestedMediaHeight = 0;
mRequestedTextureWidth = 0;
mRequestedTextureHeight = 0;
mFullMediaWidth = 0;
mFullMediaHeight = 0;
mTextureWidth = 0;
@ -469,7 +471,7 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
sendMessage(message);
}
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers)
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
{
bool result = true;
@ -526,6 +528,7 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
message.setValueS32("key", key_code);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
sendMessage(message);
}
@ -544,12 +547,13 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
sendMessage(message);
}
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers)
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
message.setValue("text", text);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
sendMessage(message);
@ -680,13 +684,13 @@ LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type)
// so that we don't expose the llqtwebkit header in viewer code
switch (target_type)
{
case LinkTargetType::LTT_TARGET_NONE:
case LLQtWebKit::LTT_TARGET_NONE:
return LLPluginClassMedia::TARGET_NONE;
case LinkTargetType::LTT_TARGET_BLANK:
case LLQtWebKit::LTT_TARGET_BLANK:
return LLPluginClassMedia::TARGET_BLANK;
case LinkTargetType::LTT_TARGET_EXTERNAL:
case LLQtWebKit::LTT_TARGET_EXTERNAL:
return LLPluginClassMedia::TARGET_EXTERNAL;
default:

View File

@ -114,12 +114,12 @@ public:
KEY_EVENT_REPEAT
}EKeyEventType;
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers);
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
void scrollEvent(int x, int y, MASK modifiers);
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers);
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
void loadURI(const std::string &uri);

View File

@ -304,7 +304,14 @@ void LLPluginMessagePipe::processInput(void)
while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos)
{
// Let the owner process this message
mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
if (mOwner)
{
mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
}
else
{
LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;
}
start = delim + 1;
}

View File

@ -43,6 +43,7 @@ static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will
LLPluginProcessChild::LLPluginProcessChild()
{
mState = STATE_UNINITIALIZED;
mInstance = NULL;
mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
@ -277,14 +278,21 @@ bool LLPluginProcessChild::isDone(void)
void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message)
{
std::string buffer = message.generate();
LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
LLTimer elapsed;
mInstance->sendMessage(buffer);
mCPUElapsed += elapsed.getElapsedTimeF64();
if (mInstance)
{
std::string buffer = message.generate();
LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
LLTimer elapsed;
mInstance->sendMessage(buffer);
mCPUElapsed += elapsed.getElapsedTimeF64();
}
else
{
LL_WARNS("Plugin") << "mInstance == NULL" << LL_ENDL;
}
}
void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message)

View File

@ -89,8 +89,9 @@ private:
STATE_ERROR, // generic bailout state
STATE_DONE // state machine will sit in this state after either error or normal termination.
};
EState mState;
void setState(EState state);
EState mState;
LLHost mLauncherHost;
LLSocket::ptr_t mSocket;

View File

@ -50,6 +50,8 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
mOwner = owner;
mBoundPort = 0;
mState = STATE_UNINITIALIZED;
mSleepTime = 0.0;
mCPUUsage = 0.0;
mDisableTimeout = false;
mDebug = false;

View File

@ -157,14 +157,9 @@ namespace
namespace tut
{
bool llsd_equals(const LLSD& a, const LLSD& b) {
// cheesy, brute force, but it works
return std::string(ll_pretty_print_sd(a)) == std::string(ll_pretty_print_sd(b));
}
void ensure_llsd_equals(const std::string& msg, const LLSD& expected, const LLSD& actual)
{
if (!tut::llsd_equals(expected, actual))
if (!llsd_equals(expected, actual))
{
std::string message = msg;
message += ": actual: ";

View File

@ -63,6 +63,12 @@ LLCubeMap::LLCubeMap()
mTextureCoordStage(0),
mMatrixStage(0)
{
mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
}
LLCubeMap::~LLCubeMap()
@ -75,13 +81,6 @@ void LLCubeMap::initGL()
if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
{
mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
// Not initialized, do stuff.
if (mImages[0].isNull())
{

View File

@ -270,6 +270,14 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
return (F32)mFontBitmapCachep->getMaxCharWidth();
}
F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
{
if (mFTFace == NULL)
return 0.0;
return glyph->mXAdvance;
}
F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
{
if (mFTFace == NULL)
@ -289,6 +297,21 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
return delta.x*(1.f/64.f);
}
F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
{
if (mFTFace == NULL)
return 0.0;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
return delta.x*(1.f/64.f);
}
BOOL LLFontFreetype::hasGlyph(llwchar wch) const
{
llassert(!mIsFallback);
@ -504,8 +527,13 @@ void LLFontFreetype::resetBitmapCache()
mCharGlyphInfoMap.clear();
mFontBitmapCachep->reset();
// Add the empty glyph
addGlyphFromFont(this, 0, 0);
// Adding default glyph is skipped for fallback fonts here as well as in loadFace().
// This if was added as fix for EXT-4971.
if(!mIsFallback)
{
// Add the empty glyph
addGlyphFromFont(this, 0, 0);
}
}
void LLFontFreetype::destroyGL()

View File

@ -128,7 +128,9 @@ public:
};
F32 getXAdvance(llwchar wc) const;
F32 getXAdvance(const LLFontGlyphInfo* glyph) const;
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;

View File

@ -248,11 +248,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
const LLFontGlyphInfo* next_glyph = NULL;
for (i = begin_offset; i < begin_offset + length; i++)
{
llwchar wch = wstr[i];
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
const LLFontGlyphInfo* fgi = next_glyph;
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
}
if (!fgi)
{
llerrs << "Missing Glyph Info" << llendl;
@ -290,7 +297,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, next_char);
next_glyph = mFontFreetype->getGlyphInfo(next_char);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@ -427,14 +435,21 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
F32 cur_x = 0;
const S32 max_index = begin_offset + max_chars;
const LLFontGlyphInfo* next_glyph = NULL;
F32 width_padding = 0.f;
for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
{
llwchar wch = wchars[i];
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
const LLFontGlyphInfo* fgi = next_glyph;
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
}
F32 advance = mFontFreetype->getXAdvance(wch);
F32 advance = mFontFreetype->getXAdvance(fgi);
// for the last character we want to measure the greater of its width and xadvance values
// so keep track of the difference between these values for the each character we measure
@ -451,7 +466,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
&& (next_char < LAST_CHARACTER))
{
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, next_char);
next_glyph = mFontFreetype->getGlyphInfo(next_char);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
cur_x = (F32)llround(cur_x);
@ -484,6 +500,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
// avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
F32 scaled_max_pixels = ceil(max_pixels * sScaleX);
F32 width_padding = 0.f;
LLFontGlyphInfo* next_glyph = NULL;
S32 i;
for (i=0; (i < max_chars); i++)
@ -526,8 +544,13 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
in_word = TRUE;
}
}
LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch);
LLFontGlyphInfo* fgi = next_glyph;
next_glyph = NULL;
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
}
// account for glyphs that run beyond the starting point for the next glyphs
width_padding = llmax( 0.f, // always use positive padding amount
@ -546,7 +569,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if (((i+1) < max_chars) && wchars[i+1])
{
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);
next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@ -593,14 +617,20 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
{
llwchar wch = wchars[i];
F32 char_width = mFontFreetype->getXAdvance(wch);
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
if( scaled_max_pixels < (total_width + char_width) )
// last character uses character width, since the whole character needs to be visible
// other characters just use advance
F32 width = (i == start)
? (F32)(fgi->mWidth + fgi->mXBearing) // use actual width for last character
: fgi->mXAdvance; // use advance for all other characters
if( scaled_max_pixels < (total_width + width) )
{
break;
}
total_width += char_width;
total_width += width;
drawable_chars++;
if( max_chars >= 0 && drawable_chars >= max_chars )
@ -618,7 +648,17 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
total_width = llround(total_width);
}
return start_pos - drawable_chars;
if (drawable_chars == 0)
{
return start_pos; // just draw last character
}
else
{
// if only 1 character is drawable, we want to return start_pos as the first character to draw
// if 2 are drawable, return start_pos and character before start_pos, etc.
return start_pos + 1 - drawable_chars;
}
}
S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round) const
@ -636,6 +676,8 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars);
F32 scaled_max_pixels = max_pixels * sScaleX;
const LLFontGlyphInfo* next_glyph = NULL;
S32 pos;
for (pos = begin_offset; pos < max_index; pos++)
@ -645,7 +687,15 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
{
break; // done
}
F32 char_width = mFontFreetype->getXAdvance(wch);
const LLFontGlyphInfo* glyph = next_glyph;
next_glyph = NULL;
if(!glyph)
{
glyph = mFontFreetype->getGlyphInfo(wch);
}
F32 char_width = mFontFreetype->getXAdvance(glyph);
if (round)
{
@ -671,11 +721,12 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
if (((pos + 1) < max_index)
&& (wchars[(pos + 1)]))
{
llwchar next_char = wchars[pos + 1];
// Kern this puppy.
cur_x += mFontFreetype->getXKerning(wch, next_char);
next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
}
// Round after kerning.
cur_x = llround(cur_x);
}

View File

@ -332,6 +332,8 @@ LLGLManager::LLGLManager() :
mHasFragmentShader(FALSE),
mHasOcclusionQuery(FALSE),
mHasPointParameters(FALSE),
mHasDrawBuffers(FALSE),
mHasTextureRectangle(FALSE),
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
@ -671,7 +673,7 @@ void LLGLManager::initExtensions()
llinfos << "initExtensions() checking shell variables to adjust features..." << llendl;
// Our extension support for the Linux Client is very young with some
// potential driver gotchas, so offer a semi-secret way to turn it off.
if (getenv("LL_GL_NOEXT")) /* Flawfinder: ignore */
if (getenv("LL_GL_NOEXT"))
{
//mHasMultitexture = FALSE; // NEEDED!
mHasARBEnvCombine = FALSE;

View File

@ -70,7 +70,7 @@ hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
// LLGLSL Shader implementation
//===============================
LLGLSLShader::LLGLSLShader()
: mProgramObject(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT)
: mProgramObject(0), mActiveTextureChannels(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE)
{
}

View File

@ -59,6 +59,8 @@ LLPostProcess::LLPostProcess(void) :
mSceneRenderTexture = NULL ;
mNoiseTexture = NULL ;
mTempBloomTexture = NULL ;
noiseTextureScale = 1.0f;
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));

View File

@ -737,8 +737,11 @@ void LLTexUnit::debugTextureUnit(void)
LLRender::LLRender()
: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES),
mMaxAnisotropy(0.f)
: mDirty(false),
mCount(0),
mMode(LLRender::TRIANGLES),
mCurrTextureUnitIndex(0),
mMaxAnisotropy(0.f)
{
mBuffer = new LLVertexBuffer(immediate_mask, 0);
mBuffer->allocateBuffer(4096, 0, TRUE);

View File

@ -215,14 +215,18 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
llassert(mRequestedNumVerts >= 0);
if (start >= (U32) mRequestedNumVerts ||
end >= (U32) mRequestedNumVerts)
end >= (U32) mRequestedNumVerts)
{
llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl;
}
llassert(mRequestedNumIndices >= 0);
if (indices_offset >= (U32) mRequestedNumIndices ||
indices_offset + count > (U32) mRequestedNumIndices)
indices_offset + count > (U32) mRequestedNumIndices)
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
@ -251,8 +255,9 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
llassert(mRequestedNumIndices >= 0);
if (indices_offset >= (U32) mRequestedNumIndices ||
indices_offset + count > (U32) mRequestedNumIndices)
indices_offset + count > (U32) mRequestedNumIndices)
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
@ -281,8 +286,9 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
llassert(mRequestedNumVerts >= 0);
if (first >= (U32) mRequestedNumVerts ||
first + count > (U32) mRequestedNumVerts)
first + count > (U32) mRequestedNumVerts)
{
llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
}
@ -354,7 +360,14 @@ void LLVertexBuffer::clientCopy(F64 max_time)
LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
LLRefCount(),
mNumVerts(0), mNumIndices(0), mUsage(usage), mGLBuffer(0), mGLIndices(0),
mNumVerts(0),
mNumIndices(0),
mRequestedNumVerts(-1),
mRequestedNumIndices(-1),
mUsage(usage),
mGLBuffer(0),
mGLIndices(0),
mMappedData(NULL),
mMappedIndexData(NULL), mLocked(FALSE),
mFinal(FALSE),
@ -600,6 +613,8 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_VERTS);
llassert(nverts >= 0);
if (nverts >= 65535)
{
llwarns << "Vertex buffer overflow!" << llendl;
@ -628,6 +643,9 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
void LLVertexBuffer::updateNumIndices(S32 nindices)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_INDICES);
llassert(nindices >= 0);
mRequestedNumIndices = nindices;
if (!mDynamicSize)
{
@ -668,6 +686,9 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
llassert(newnverts >= 0);
llassert(newnindices >= 0);
mRequestedNumVerts = newnverts;
mRequestedNumIndices = newnindices;

View File

@ -90,6 +90,7 @@ set(llui_SOURCE_FILES
lltextbox.cpp
lltexteditor.cpp
lltextparser.cpp
lltextvalidate.cpp
lltransutil.cpp
lltoggleablemenu.cpp
lltooltip.cpp
@ -182,6 +183,7 @@ set(llui_HEADER_FILES
lltextbox.h
lltexteditor.h
lltextparser.h
lltextvalidate.h
lltoggleablemenu.h
lltooltip.h
lltransutil.h

View File

@ -103,6 +103,13 @@ void LLAccordionCtrl::draw()
LLLocalClipRect clip(local_rect);
LLPanel::draw();
/*
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
gl_rect_2d(0, 0 , width - 1 ,height - 1,LLColor4::green,true);
gl_line_2d(0, 0 , width - 1 ,height - 1,LLColor4::black);
*/
}
@ -338,36 +345,55 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
}
void LLAccordionCtrl::arrange()
void LLAccordionCtrl::arrangeSinge()
{
if( mAccordionTabs.size() == 0)
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
S32 panel_height;
S32 collapsed_height = 0;
for(size_t i=0;i<mAccordionTabs.size();++i)
{
//We do not arrange if we do not have what should be arranged
return;
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
continue;
if(!accordion_tab->isExpanded() )
{
collapsed_height+=mAccordionTabs[i]->getRect().getHeight();
}
}
//Calculate params
S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height;
for(size_t i=0;i<mAccordionTabs.size();++i)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
continue;
if(!accordion_tab->isExpanded() )
{
panel_height = accordion_tab->getRect().getHeight();
}
else
{
panel_height = expanded_height;
}
ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
panel_top-=mAccordionTabs[i]->getRect().getHeight();
}
}
void LLAccordionCtrl::arrangeMultiple()
{
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
if(mAccordionTabs.size() == 1)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
LLRect panel_rect = accordion_tab->getRect();
S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
return;
}
//Calculate params
for(size_t i = 0; i < mAccordionTabs.size(); i++ )
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
@ -415,7 +441,40 @@ void LLAccordionCtrl::arrange()
show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
updateLayout(getRect().getWidth(),getRect().getHeight());
}
void LLAccordionCtrl::arrange()
{
if( mAccordionTabs.size() == 0)
{
//We do not arrange if we do not have what should be arranged
return;
}
if(mAccordionTabs.size() == 1)
{
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
LLRect panel_rect = accordion_tab->getRect();
S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
return;
}
if(mSingleExpansion)
arrangeSinge ();
else
arrangeMultiple ();
}
//---------------------------------------------------------------------------------

View File

@ -105,6 +105,9 @@ public:
void reset ();
private:
void arrangeSinge();
void arrangeMultiple();
// Calc Splitter's height that is necessary to display all child content
S32 calcRecuiredHeight();
S32 getRecuiredHeight() const { return mInnerRect.getHeight(); }

View File

@ -81,10 +81,9 @@ LLButton::Params::Params()
image_pressed_selected("image_pressed_selected"),
image_overlay("image_overlay"),
image_overlay_alignment("image_overlay_alignment", std::string("center")),
image_left_pad("image_left_pad"),
image_right_pad("image_right_pad"),
image_top_pad("image_top_pad"),
image_bottom_pad("image_bottom_pad"),
imgoverlay_label_space("imgoverlay_label_space", 1),
label_color("label_color"),
label_color_selected("label_color_selected"), // requires is_toggle true
label_color_disabled("label_color_disabled"),
@ -144,10 +143,9 @@ LLButton::LLButton(const LLButton::Params& p)
mImageOverlay(p.image_overlay()),
mImageOverlayColor(p.image_overlay_color()),
mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)),
mImageOverlayLeftPad(p.image_left_pad),
mImageOverlayRightPad(p.image_right_pad),
mImageOverlayTopPad(p.image_top_pad),
mImageOverlayBottomPad(p.image_bottom_pad),
mImgOverlayLabelSpace(p.imgoverlay_label_space),
mIsToggle(p.is_toggle),
mScaleImage(p.scale_image),
mDropShadowedText(p.label_shadow),
@ -771,12 +769,7 @@ void LLButton::draw()
center_x++;
}
S32 text_width_delta = overlay_width + 1;
// if image paddings set, they should participate in scaling process
S32 image_size_delta = mImageOverlayTopPad + mImageOverlayBottomPad;
overlay_width = overlay_width - image_size_delta;
overlay_height = overlay_height - image_size_delta;
center_y += (mImageOverlayBottomPad - mImageOverlayTopPad);
// fade out overlay images on disabled buttons
LLColor4 overlay_color = mImageOverlayColor.get();
if (!enabled)
@ -788,10 +781,9 @@ void LLButton::draw()
switch(mImageOverlayAlignment)
{
case LLFontGL::LEFT:
text_left += overlay_width + mImageOverlayRightPad + 1;
text_width -= text_width_delta;
text_left += overlay_width + mImgOverlayLabelSpace;
mImageOverlay->draw(
mLeftHPad,
mLeftHPad,
center_y - (overlay_height / 2),
overlay_width,
overlay_height,
@ -806,10 +798,9 @@ void LLButton::draw()
overlay_color);
break;
case LLFontGL::RIGHT:
text_right -= overlay_width + mImageOverlayLeftPad+ 1;
text_width -= text_width_delta;
text_right -= overlay_width + mImgOverlayLabelSpace;
mImageOverlay->draw(
getRect().getWidth() - mRightHPad - overlay_width,
getRect().getWidth() - mRightHPad - overlay_width,
center_y - (overlay_height / 2),
overlay_width,
overlay_height,

View File

@ -107,11 +107,14 @@ public:
Optional<S32> pad_bottom; // under text label
//image overlay paddings
Optional<S32> image_left_pad;
Optional<S32> image_right_pad;
Optional<S32> image_top_pad;
Optional<S32> image_bottom_pad;
/**
* Space between image_overlay and label
*/
Optional<S32> imgoverlay_label_space;
// callbacks
Optional<CommitCallbackParam> click_callback, // alias -> commit_callback
mouse_down_callback,
@ -192,10 +195,6 @@ public:
void setLeftHPad( S32 pad ) { mLeftHPad = pad; }
void setRightHPad( S32 pad ) { mRightHPad = pad; }
void setImageOverlayLeftPad( S32 pad ) { mImageOverlayLeftPad = pad; }
S32 getImageOverlayLeftPad() const { return mImageOverlayLeftPad; }
void setImageOverlayRightPad( S32 pad ) { mImageOverlayRightPad = pad; }
S32 getImageOverlayRightPad() const { return mImageOverlayRightPad; }
void setImageOverlayTopPad( S32 pad ) { mImageOverlayTopPad = pad; }
S32 getImageOverlayTopPad() const { return mImageOverlayTopPad; }
void setImageOverlayBottomPad( S32 pad ) { mImageOverlayBottomPad = pad; }
@ -258,6 +257,8 @@ public:
void setForcePressedState(bool b) { mForcePressedState = b; }
void setAutoResize(bool auto_resize) { mAutoResize = auto_resize; }
protected:
LLPointer<LLUIImage> getImageUnselected() const { return mImageUnselected; }
LLPointer<LLUIImage> getImageSelected() const { return mImageSelected; }
@ -328,11 +329,14 @@ private:
S32 mRightHPad;
S32 mBottomVPad; // under text label
S32 mImageOverlayLeftPad;
S32 mImageOverlayRightPad;
S32 mImageOverlayTopPad;
S32 mImageOverlayBottomPad;
/*
* Space between image_overlay and label
*/
S32 mImgOverlayLabelSpace;
F32 mHoverGlowStrength;
F32 mCurGlowStrength;

View File

@ -244,23 +244,6 @@ void LLConsole::draw()
}
}
void LLConsole::addLine(const std::string& utf8line)
{
LLWString wline = utf8str_to_wstring(utf8line);
addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f));
}
void LLConsole::addLine(const LLWString& wline)
{
addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f));
}
void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color)
{
LLWString wline = utf8str_to_wstring(utf8line);
addLine(wline, size, color);
}
//Generate highlight color segments for this paragraph. Pass in default color of paragraph.
void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color)
{
@ -317,7 +300,8 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, b
S32 paragraph_offset = 0; //Offset into the paragraph text.
// Wrap lines that are longer than the view is wide.
while( paragraph_offset < (S32)mParagraphText.length() )
while( paragraph_offset < (S32)mParagraphText.length() &&
mParagraphText[paragraph_offset] != 0)
{
S32 skip_chars; // skip '\n'
// Figure out if a word-wrapped line fits here.
@ -383,21 +367,45 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, b
//Pass in the string and the default color for this block of text.
LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width)
: mParagraphText(str), mAddTime(add_time), mMaxWidth(-1)
: mParagraphText(str), mAddTime(add_time), mMaxWidth(-1)
{
makeParagraphColorSegments(color);
updateLines( screen_width, font );
}
void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color)
// called once per frame regardless of console visibility
// static
void LLConsole::updateClass()
{
Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() );
mParagraphs.push_back ( paragraph );
LLInstanceTrackerScopedGuard guard;
for (instance_iter it = guard.beginInstances(); it != guard.endInstances(); ++it)
{
it->update();
}
}
void LLConsole::update()
{
{
LLMutexLock lock(&mMutex);
while (!mLines.empty())
{
mParagraphs.push_back(
Paragraph( mLines.front(),
LLColor4::white,
mTimer.getElapsedTimeF32(),
mFont,
(F32)getRect().getWidth()));
mLines.pop_front();
}
}
// remove old paragraphs which can't possibly be visible any more. ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called! (i.e. the console isn't visible)
while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines)))
{
mParagraphs.pop_front();
}
while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines)))
{
mParagraphs.pop_front();
}
}

View File

@ -40,7 +40,7 @@
class LLSD;
class LLConsole : public LLFixedBuffer, public LLUICtrl
class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker<LLConsole>
{
public:
typedef enum e_font_size
@ -68,6 +68,9 @@ protected:
friend class LLUICtrlFactory;
public:
// call once per frame to pull data out of LLFixedBuffer
static void updateClass();
//A paragraph color segment defines the color of text in a line
//of text that was received for console display. It has no
//notion of line wraps, screen position, or the text it contains.
@ -139,14 +142,12 @@ public:
// -1 = monospace, 0 means small, font size = 1 means big
void setFontSize(S32 size_index);
void addLine(const std::string& utf8line, F32 size, const LLColor4 &color);
void addLine(const LLWString& wline, F32 size, const LLColor4 &color);
// Overrides
/*virtual*/ void draw();
/*virtual*/ void addLine(const std::string& utf8line);
/*virtual*/ void addLine(const LLWString& line);
private:
void update();
F32 mLinePersistTime; // Age at which to stop drawing.
F32 mFadeTime; // Age at which to start fading
const LLFontGL* mFont;

View File

@ -95,7 +95,7 @@ void LLDockableFloater::toggleInstance(const LLSD& sdname)
LLDockableFloater* instance =
dynamic_cast<LLDockableFloater*> (LLFloaterReg::findInstance(name));
// if floater closed or docked
if (instance == NULL || instance != NULL && instance->isDocked())
if (instance == NULL || (instance && instance->isDocked()))
{
LLFloaterReg::toggleInstance(name, key);
// restore button toggle state
@ -223,10 +223,10 @@ void LLDockableFloater::draw()
LLFloater::draw();
}
void LLDockableFloater::setDockControl(LLDockControl* dockControl)
void LLDockableFloater::setDockControl(LLDockControl* dockControl, bool docked /* = true */)
{
mDockControl.reset(dockControl);
setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
setDocked(docked && mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
}
const LLUIImagePtr& LLDockableFloater::getDockTongue()

View File

@ -127,7 +127,7 @@ private:
void resetInstance();
protected:
void setDockControl(LLDockControl* dockControl);
void setDockControl(LLDockControl* dockControl, bool docked = true);
const LLUIImagePtr& getDockTongue();
private:

View File

@ -162,7 +162,9 @@ bool LLDockControl::isDockVisible()
{
case LEFT: // to keep compiler happy
break;
case BOTTOM:
case TOP:
{
// check is dock inside parent rect
LLRect dockParentRect =
mDockWidget->getParent()->calcScreenRect();
@ -173,6 +175,9 @@ bool LLDockControl::isDockVisible()
}
break;
}
default:
break;
}
}
}
@ -254,6 +259,42 @@ void LLDockControl::moveDockable()
}
mDockTongueY = dockRect.mTop;
break;
case BOTTOM:
x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
y = dockRect.mBottom;
// unique docking used with dock tongue, so add tongue height o the Y coordinate
if (use_tongue)
{
y -= mDockTongue->getHeight();
}
// check is dockable inside root view rect
if (x < rootRect.mLeft)
{
x = rootRect.mLeft;
}
if (x + dockableRect.getWidth() > rootRect.mRight)
{
x = rootRect.mRight - dockableRect.getWidth();
}
// calculate dock tongue position
dockParentRect = mDockWidget->getParent()->calcScreenRect();
if (dockRect.getCenterX() < dockParentRect.mLeft)
{
mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
}
else if (dockRect.getCenterX() > dockParentRect.mRight)
{
mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
}
else
{
mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
}
mDockTongueY = dockRect.mBottom - mDockTongue->getHeight();
break;
}

View File

@ -47,8 +47,9 @@ class LLDockControl
public:
enum DocAt
{
TOP
,LEFT
TOP,
LEFT,
BOTTOM
};
public:

View File

@ -42,8 +42,6 @@ static const LLDefaultChildRegistry::Register<LLFlatListView> flat_list_view("fl
const LLSD SELECTED_EVENT = LLSD().with("selected", true);
const LLSD UNSELECTED_EVENT = LLSD().with("selected", false);
static const std::string COMMENT_TEXTBOX = "comment_text";
//forward declaration
bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2);
@ -51,7 +49,8 @@ LLFlatListView::Params::Params()
: item_pad("item_pad"),
allow_select("allow_select"),
multi_select("multi_select"),
keep_one_selected("keep_one_selected")
keep_one_selected("keep_one_selected"),
no_items_text("no_items_text")
{};
void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
@ -295,19 +294,6 @@ void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/)
void LLFlatListView::setNoItemsCommentText(const std::string& comment_text)
{
if (NULL == mNoItemsCommentTextbox)
{
LLRect comment_rect = getRect();
comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight());
comment_rect.stretch(-getBorderWidth());
LLTextBox::Params text_p;
text_p.name(COMMENT_TEXTBOX);
text_p.border_visible(false);
text_p.rect(comment_rect);
text_p.follows.flags(FOLLOWS_ALL);
mNoItemsCommentTextbox = LLUICtrlFactory::create<LLTextBox>(text_p, this);
}
mNoItemsCommentTextbox->setValue(comment_text);
}
@ -361,7 +347,6 @@ bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value)
// PROTECTED STUFF
//////////////////////////////////////////////////////////////////////////
LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
: LLScrollContainer(p)
, mItemComparator(NULL)
@ -398,6 +383,25 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
params.bevel_style(LLViewBorder::BEVEL_IN);
mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params);
mItemsPanel->addChild( mSelectedItemsBorder );
{
// create textbox for "No Items" comment text
LLTextBox::Params text_p = p.no_items_text;
if (!text_p.rect.isProvided())
{
LLRect comment_rect = getRect();
comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight());
comment_rect.stretch(-getBorderWidth());
text_p.rect(comment_rect);
}
text_p.border_visible(false);
if (!text_p.follows.isProvided())
{
text_p.follows.flags(FOLLOWS_ALL);
}
mNoItemsCommentTextbox = LLUICtrlFactory::create<LLTextBox>(text_p, this);
}
};
// virtual
@ -861,7 +865,11 @@ void LLFlatListView::notifyParentItemsRectChanged()
// take into account comment text height if exists
if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible())
{
// top text padding inside the textbox is included into the height
comment_height = mNoItemsCommentTextbox->getTextPixelHeight();
// take into account a distance from parent's top border to textbox's top
comment_height += getRect().getHeight() - mNoItemsCommentTextbox->getRect().mTop;
}
LLRect req_rect = getItemsRect();
@ -892,6 +900,10 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const
{
if (visible)
{
/*
// *NOTE: MA 2010-02-04
// Deprecated after params of the comment text box were moved into widget (flat_list_view.xml)
// can be removed later if nothing happened.
// We have to update child rect here because of issues with rect after reshaping while creating LLTextbox
// It is possible to have invalid LLRect if Flat List is in LLAccordionTab
LLRect comment_rect = getLocalRect();
@ -903,6 +915,7 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const
LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border");
comment_rect.stretch(-scroll_border->getBorderWidth());
mNoItemsCommentTextbox->setRect(comment_rect);
*/
}
mNoItemsCommentTextbox->setVisible(visible);
}

View File

@ -35,8 +35,8 @@
#include "llpanel.h"
#include "llscrollcontainer.h"
#include "lltextbox.h"
class LLTextBox;
/**
* LLFlatListView represents a flat list ui control that operates on items in a form of LLPanel's.
@ -108,6 +108,9 @@ public:
/** padding between items */
Optional<U32> item_pad;
/** textbox with info message when list is empty*/
Optional<LLTextBox::Params> no_items_text;
Params();
};

View File

@ -1565,43 +1565,34 @@ void LLFloater::draw()
// draw background
if( isBackgroundVisible() )
{
drawShadow(this);
S32 left = LLPANEL_BORDER_WIDTH;
S32 top = getRect().getHeight() - LLPANEL_BORDER_WIDTH;
S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH;
S32 bottom = LLPANEL_BORDER_WIDTH;
static LLUICachedControl<S32> shadow_offset_S32 ("DropShadowFloater", 0);
static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow");
LLColor4 shadow_color = shadow_color_cached;
F32 shadow_offset = (F32)shadow_offset_S32;
if (!isBackgroundOpaque())
{
shadow_offset *= 0.2f;
shadow_color.mV[VALPHA] *= 0.5f;
}
gl_drop_shadow(left, top, right, bottom,
shadow_color % alpha,
llround(shadow_offset));
LLUIImage* image = NULL;
LLColor4 color;
LLColor4 overlay_color;
if (isBackgroundOpaque())
{
// NOTE: image may not be set
image = getBackgroundImage();
color = getBackgroundColor();
overlay_color = getBackgroundImageOverlay();
}
else
{
image = getTransparentImage();
color = getTransparentColor();
overlay_color = getTransparentImageOverlay();
}
if (image)
{
// We're using images for this floater's backgrounds
image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha);
image->draw(getLocalRect(), overlay_color % alpha);
}
else
{
@ -1650,24 +1641,8 @@ void LLFloater::draw()
}
else
{
//FIXME: get rid of this hack
// draw children
LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
BOOL focused_child_visible = FALSE;
if (focused_child && focused_child->getParent() == this)
{
focused_child_visible = focused_child->getVisible();
focused_child->setVisible(FALSE);
}
// don't call LLPanel::draw() since we've implemented custom background rendering
LLView::draw();
if (focused_child_visible)
{
focused_child->setVisible(TRUE);
}
drawChild(focused_child);
}
// update tearoff button for torn off floaters
@ -1682,6 +1657,29 @@ void LLFloater::draw()
}
}
void LLFloater::drawShadow(LLPanel* panel)
{
F32 alpha = panel->getDrawContext().mAlpha;
S32 left = LLPANEL_BORDER_WIDTH;
S32 top = panel->getRect().getHeight() - LLPANEL_BORDER_WIDTH;
S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH;
S32 bottom = LLPANEL_BORDER_WIDTH;
static LLUICachedControl<S32> shadow_offset_S32 ("DropShadowFloater", 0);
static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow");
LLColor4 shadow_color = shadow_color_cached;
F32 shadow_offset = (F32)shadow_offset_S32;
if (!panel->isBackgroundOpaque())
{
shadow_offset *= 0.2f;
shadow_color.mV[VALPHA] *= 0.5f;
}
gl_drop_shadow(left, top, right, bottom,
shadow_color % alpha,
llround(shadow_offset));
}
void LLFloater::setCanMinimize(BOOL can_minimize)
{
// if removing minimize/restore button programmatically,
@ -2392,10 +2390,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
LLRect new_rect;
new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height);
floater->reshape( new_width, new_height, TRUE );
floater->setRect(new_rect);
floater->setShape(new_rect);
floater->translateIntoRect( getLocalRect(), false );
if (floater->followsRight())
{
floater->translate(old_width - new_width, 0);
}
if (floater->followsTop())
{
floater->translate(0, old_height - new_height);
}
}
}
@ -2579,6 +2584,8 @@ void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list)
view->pushVisible(visible);
}
}
LLFloaterReg::blockShowFloaters(true);
}
void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
@ -2596,6 +2603,8 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
view->popVisible();
}
}
LLFloaterReg::blockShowFloaters(false);
}
void LLFloater::setInstanceName(const std::string& name)

View File

@ -222,6 +222,7 @@ public:
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 mask);
virtual void draw();
virtual void drawShadow(LLPanel* panel);
virtual void onOpen(const LLSD& key) {}
virtual void onClose(bool app_quitting) {}

View File

@ -34,6 +34,7 @@
#include "llfloaterreg.h"
//#include "llagent.h"
#include "llfloater.h"
#include "llmultifloater.h"
#include "llfloaterreglistener.h"
@ -45,6 +46,7 @@ LLFloaterReg::instance_list_t LLFloaterReg::sNullInstanceList;
LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
std::map<std::string,std::string> LLFloaterReg::sGroupMap;
bool LLFloaterReg::sBlockShowFloaters = false;
static LLFloaterRegListener sFloaterRegListener;
@ -217,6 +219,8 @@ LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::str
//static
LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
{
if( sBlockShowFloaters )
return 0;//
LLFloater* instance = getInstance(name, key);
if (instance)
{

View File

@ -75,6 +75,7 @@ private:
static instance_map_t sInstanceMap;
static build_map_t sBuildMap;
static std::map<std::string,std::string> sGroupMap;
static bool sBlockShowFloaters;
public:
// Registration
@ -152,6 +153,8 @@ public:
{
return dynamic_cast<T*>(showInstance(name, key, focus));
}
static void blockShowFloaters(bool value) { sBlockShowFloaters = value;}
};

View File

@ -218,6 +218,86 @@ void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
llassert(0);
}
}
LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
{
if(other.mOwner)
{
copyData(other.mData, other.mLength);
}
else
{
mOwner = false;
mLength = other.mLength;
mData = other.mData;
}
}
LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str)
{
copyData(str.data(), str.size());
}
LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length):
mData(start), mLength(length), mOwner(false)
{
}
LLKeywords::WStringMapIndex::~WStringMapIndex()
{
if(mOwner)
delete[] mData;
}
void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length)
{
llwchar *data = new llwchar[length];
memcpy((void*)data, (const void*)start, length * sizeof(llwchar));
mOwner = true;
mLength = length;
mData = data;
}
bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const
{
// NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not.
// The comparison only needs to strictly order all possible strings, and be stable.
bool result = false;
const llwchar* self_iter = mData;
const llwchar* self_end = mData + mLength;
const llwchar* other_iter = other.mData;
const llwchar* other_end = other.mData + other.mLength;
while(true)
{
if(other_iter >= other_end)
{
// We've hit the end of other.
// This covers two cases: other being shorter than self, or the strings being equal.
// In either case, we want to return false.
result = false;
break;
}
else if(self_iter >= self_end)
{
// self is shorter than other.
result = true;
break;
}
else if(*self_iter != *other_iter)
{
// The current character differs. The strings are not equal.
result = *self_iter < *other_iter;
break;
}
self_iter++;
other_iter++;
}
return result;
}
LLColor3 LLKeywords::readColor( const std::string& s )
{
@ -429,7 +509,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_len = p - cur;
if( seg_len > 0 )
{
LLWString word( cur, 0, seg_len );
WStringMapIndex word( cur, seg_len );
word_token_map_t::iterator map_iter = mWordTokenMap.find(word);
if( map_iter != mWordTokenMap.end() )
{

View File

@ -92,8 +92,33 @@ public:
const std::string& key,
const LLColor3& color,
const std::string& tool_tip = LLStringUtil::null);
// This class is here as a performance optimization.
// The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
// This worked, but caused a performance bottleneck due to memory allocation and string copies
// because it's not possible to search such a map without creating an LLWString.
// Using this class as the map index instead allows us to search using segments of an existing
// text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments().
class WStringMapIndex
{
public:
// copy constructor
WStringMapIndex(const WStringMapIndex& other);
// constructor from a string (copies the string's data into the new object)
WStringMapIndex(const LLWString& str);
// constructor from pointer and length
// NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object!
WStringMapIndex(const llwchar *start, size_t length);
~WStringMapIndex();
bool operator<(const WStringMapIndex &other) const;
private:
void copyData(const llwchar *start, size_t length);
const llwchar *mData;
size_t mLength;
bool mOwner;
};
typedef std::map<LLWString, LLKeywordToken*> word_token_map_t;
typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
typedef word_token_map_t::const_iterator keyword_iterator_t;
keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
keyword_iterator_t end() const { return mWordTokenMap.end(); }

View File

@ -816,7 +816,10 @@ void LLLayoutStack::calcMinExtents()
//static
void LLLayoutStack::updateClass()
{
for (LLLayoutStack::instance_iter it = beginInstances(); it != endInstances(); ++it)
LLInstanceTrackerScopedGuard guard;
for (LLLayoutStack::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
it->updateLayout();
}

View File

@ -55,6 +55,7 @@
#include "llui.h"
#include "lluictrlfactory.h"
#include "llclipboard.h"
#include "llmenugl.h"
//
// Imported globals
@ -70,7 +71,7 @@ const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing
const F32 AUTO_SCROLL_TIME = 0.05f;
const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval?
const std::string PASSWORD_ASTERISK( "\xE2\x97\x8F" ); // U+25CF BLACK CIRCLE
const std::string PASSWORD_ASTERISK( "\xE2\x80\xA2" ); // U+2022 BULLET
static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor");
@ -82,19 +83,6 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>(
// Member functions
//
void LLLineEditor::PrevalidateNamedFuncs::declareValues()
{
declare("ascii", LLLineEditor::prevalidateASCII);
declare("float", LLLineEditor::prevalidateFloat);
declare("int", LLLineEditor::prevalidateInt);
declare("positive_s32", LLLineEditor::prevalidatePositiveS32);
declare("non_negative_s32", LLLineEditor::prevalidateNonNegativeS32);
declare("alpha_num", LLLineEditor::prevalidateAlphaNum);
declare("alpha_num_space", LLLineEditor::prevalidateAlphaNumSpace);
declare("ascii_printable_no_pipe", LLLineEditor::prevalidateASCIIPrintableNoPipe);
declare("ascii_printable_no_space", LLLineEditor::prevalidateASCIIPrintableNoSpace);
}
LLLineEditor::Params::Params()
: max_length_bytes("max_length", 254),
keystroke_callback("keystroke_callback"),
@ -164,7 +152,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mTentativeFgColor(p.text_tentative_color()),
mHighlightColor(p.highlight_color()),
mPreeditBgColor(p.preedit_bg_color()),
mGLFont(p.font)
mGLFont(p.font),
mContextMenuHandle()
{
llassert( mMaxLengthBytes > 0 );
@ -191,6 +180,12 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
setCursor(mText.length());
setPrevalidate(p.prevalidate_callback());
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
("menu_text_editor.xml",
LLMenuGL::sMenuContainer,
LLMenuHolderGL::child_registry_t::instance());
setContextMenu(menu);
}
LLLineEditor::~LLLineEditor()
@ -422,12 +417,16 @@ void LLLineEditor::setCursor( S32 pos )
S32 old_cursor_pos = getCursor();
mCursorPos = llclamp( pos, 0, mText.length());
// position of end of next character after cursor
S32 pixels_after_scroll = findPixelNearestPos();
if( pixels_after_scroll > mTextRightEdge )
{
S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos);
S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mTextRightEdge - mTextLeftEdge + width_chars_to_left)));
S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), getCursor());
// character immediately to left of cursor should be last one visible (SCROLL_INCREMENT_ADD will scroll in more characters)
// or first character if cursor is at beginning
S32 new_last_visible_char = llmax(0, getCursor() - 1);
S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), new_last_visible_char);
if (old_cursor_pos == last_visible_char)
{
mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD));
@ -663,6 +662,16 @@ BOOL LLLineEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
return TRUE;
}
BOOL LLLineEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
setFocus(TRUE);
if (!LLUICtrl::handleRightMouseDown(x, y, mask))
{
showContextMenu(x, y);
}
return TRUE;
}
BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@ -1962,51 +1971,12 @@ void LLLineEditor::setRect(const LLRect& rect)
}
}
void LLLineEditor::setPrevalidate(LLLinePrevalidateFunc func)
void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func)
{
mPrevalidateFunc = func;
updateAllowingLanguageInput();
}
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
// static
BOOL LLLineEditor::prevalidateFloat(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
// May be a comma or period, depending on the locale
llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint();
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
// static
BOOL LLLineEditor::postvalidateFloat(const std::string &str)
{
@ -2066,223 +2036,6 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str)
return success;
}
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
// static
BOOL LLLineEditor::prevalidateInt(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
// static
BOOL LLLineEditor::prevalidatePositiveS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
BOOL success = TRUE;
if(0 < len)
{
if(('-' == trimmed[0]) || ('0' == trimmed[0]))
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val <= 0)
{
success = FALSE;
}
}
return success;
}
BOOL LLLineEditor::prevalidateNonNegativeS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
BOOL success = TRUE;
if(0 < len)
{
if('-' == trimmed[0])
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val < 0)
{
success = FALSE;
}
}
return success;
}
BOOL LLLineEditor::prevalidateAlphaNum(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if( !LLStringOps::isAlnum((char)str[len]) )
{
rv = FALSE;
break;
}
}
return rv;
}
// static
BOOL LLLineEditor::prevalidateAlphaNumSpace(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len])))
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for most names of things stored on the server, due to old file-formats
// that used the pipe (|) for multiline text storage. Examples include
// inventory item names, parcel names, object names, etc.
// static
BOOL LLLineEditor::prevalidateASCIIPrintableNoPipe(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| wc == '|')
{
rv = FALSE;
break;
}
if(!(wc == ' '
|| LLStringOps::isAlnum((char)wc)
|| LLStringOps::isPunct((char)wc) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for avatar names
// static
BOOL LLLineEditor::prevalidateASCIIPrintableNoSpace(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| LLStringOps::isSpace(wc))
{
rv = FALSE;
break;
}
if( !(LLStringOps::isAlnum((char)str[len]) ||
LLStringOps::isPunct((char)str[len]) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
// static
BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
while(len--)
{
if (str[len] < 0x20 || str[len] > 0x7f)
{
rv = FALSE;
break;
}
}
return rv;
}
void LLLineEditor::onMouseCaptureLost()
{
endSelection();
@ -2560,3 +2313,25 @@ LLWString LLLineEditor::getConvertedText() const
}
return text;
}
void LLLineEditor::showContextMenu(S32 x, S32 y)
{
LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
if (menu)
{
gEditMenuHandler = this;
S32 screen_x, screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
menu->show(screen_x, screen_y);
}
}
void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
{
if (new_context_menu)
mContextMenuHandle = new_context_menu->getHandle();
else
mContextMenuHandle.markDead();
}

View File

@ -51,26 +51,18 @@
#include "llviewborder.h"
#include "llpreeditor.h"
#include <boost/function.hpp>
#include "lltextvalidate.h"
class LLFontGL;
class LLLineEditorRollback;
class LLButton;
typedef boost::function<BOOL (const LLWString &wstr)> LLLinePrevalidateFunc;
class LLContextMenu;
class LLLineEditor
: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor
{
public:
struct PrevalidateNamedFuncs
: public LLInitParam::TypeValuesHelper<LLLinePrevalidateFunc, PrevalidateNamedFuncs>
{
static void declareValues();
};
typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t;
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
@ -80,7 +72,7 @@ public:
Optional<keystroke_callback_t> keystroke_callback;
Optional<LLLinePrevalidateFunc, PrevalidateNamedFuncs> prevalidate_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
Optional<LLViewBorder::Params> border;
@ -113,6 +105,7 @@ protected:
LLLineEditor(const Params&);
friend class LLUICtrlFactory;
friend class LLFloaterEditUI;
void showContextMenu(S32 x, S32 y);
public:
virtual ~LLLineEditor();
@ -122,6 +115,7 @@ public:
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask);
/*virtual*/ BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
/*virtual*/ void onMouseCaptureLost();
@ -204,6 +198,8 @@ public:
const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); }
const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); }
const LLFontGL* getFont() const { return mGLFont; }
void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; }
void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
void setPassDelete(BOOL b) { mPassDelete = b; }
@ -231,17 +227,7 @@ public:
void setTextPadding(S32 left, S32 right);
// Prevalidation controls which keystrokes can affect the editor
void setPrevalidate( LLLinePrevalidateFunc func );
static BOOL prevalidateFloat(const LLWString &str );
static BOOL prevalidateInt(const LLWString &str );
static BOOL prevalidatePositiveS32(const LLWString &str);
static BOOL prevalidateNonNegativeS32(const LLWString &str);
static BOOL prevalidateAlphaNum(const LLWString &str );
static BOOL prevalidateAlphaNumSpace(const LLWString &str );
static BOOL prevalidateASCIIPrintableNoPipe(const LLWString &str);
static BOOL prevalidateASCIIPrintableNoSpace(const LLWString &str);
static BOOL prevalidateASCII(const LLWString &str);
void setPrevalidate( LLTextValidate::validate_func_t func );
static BOOL postvalidateFloat(const std::string &str);
// line history support:
@ -249,7 +235,9 @@ public:
void updateHistory(); // stores current line in history
void setReplaceNewlinesWithSpaces(BOOL replace);
void setContextMenu(LLContextMenu* new_context_menu);
private:
// private helper methods
@ -319,7 +307,7 @@ protected:
S32 mLastSelectionStart;
S32 mLastSelectionEnd;
LLLinePrevalidateFunc mPrevalidateFunc;
LLTextValidate::validate_func_t mPrevalidateFunc;
LLFrameTimer mKeystrokeTimer;
LLTimer mTripleClickTimer;
@ -348,6 +336,8 @@ protected:
std::vector<S32> mPreeditPositions;
LLPreeditor::standouts_t mPreeditStandouts;
LLHandle<LLView> mContextMenuHandle;
private:
// Instances that by default point to the statics but can be overidden in XML.
LLPointer<LLUIImage> mBgImage;

View File

@ -657,11 +657,38 @@ LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void )
// Class LLMenuItemTearOffGL
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p)
: LLMenuItemGL(p),
mParentHandle(p.parent_floater_handle)
: LLMenuItemGL(p)
{
}
// Returns the first floater ancestor if there is one
LLFloater* LLMenuItemTearOffGL::getParentFloater()
{
LLView* parent_view = getMenu();
while (parent_view)
{
if (dynamic_cast<LLFloater*>(parent_view))
{
return dynamic_cast<LLFloater*>(parent_view);
}
bool parent_is_menu = dynamic_cast<LLMenuGL*>(parent_view) && !dynamic_cast<LLMenuBarGL*>(parent_view);
if (parent_is_menu)
{
// use menu parent
parent_view = dynamic_cast<LLMenuGL*>(parent_view)->getParentMenuItem();
}
else
{
// just use regular view parent
parent_view = parent_view->getParent();
}
}
return NULL;
}
void LLMenuItemTearOffGL::onCommit()
{
@ -680,7 +707,7 @@ void LLMenuItemTearOffGL::onCommit()
getMenu()->needsArrange();
LLFloater* parent_floater = mParentHandle.get();
LLFloater* parent_floater = getParentFloater();
LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu());
if (tear_off_menu)
@ -1671,7 +1698,6 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
mSpilloverMenu(NULL),
mJumpKey(p.jump_key),
mCreateJumpKeys(p.create_jump_keys),
mParentFloaterHandle(p.parent_floater),
mNeedsArrange(FALSE),
mShortcutPad(p.shortcut_pad)
{
@ -1699,7 +1725,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
void LLMenuGL::initFromParams(const LLMenuGL::Params& p)
{
LLUICtrl::initFromParams(p);
setCanTearOff(p.can_tear_off, p.parent_floater);
setCanTearOff(p.can_tear_off);
}
// Destroys the object
@ -1711,12 +1737,11 @@ LLMenuGL::~LLMenuGL( void )
mJumpKeys.clear();
}
void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle )
void LLMenuGL::setCanTearOff(BOOL tear_off)
{
if (tear_off && mTearOffItem == NULL)
{
LLMenuItemTearOffGL::Params p;
p.parent_floater_handle = parent_floater_handle;
mTearOffItem = LLUICtrlFactory::create<LLMenuItemTearOffGL>(p);
addChildInBack(mTearOffItem);
}
@ -2233,7 +2258,6 @@ void LLMenuGL::createSpilloverBranch()
LLMenuGL::Params p;
p.name("More");
p.label("More"); // *TODO: Translate
p.parent_floater(mParentFloaterHandle);
p.bg_color(mBackgroundColor);
p.bg_visible(true);
p.can_tear_off(false);
@ -3941,7 +3965,6 @@ BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)
item = LLUICtrlFactory::create<LLContextMenuBranch>(p);
LLMenuGL::sMenuContainer->addChild(item->getBranch());
item->setFont( LLFontGL::getFontSansSerif() );
return append( item );
}

View File

@ -355,7 +355,6 @@ class LLMenuGL
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<LLHandle<LLFloater> > parent_floater;
Optional<KEY> jump_key;
Optional<bool> horizontal_layout,
can_tear_off,
@ -430,7 +429,7 @@ public:
void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; }
const LLUIColor& getBackgroundColor() const { return mBackgroundColor; }
void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>());
void setCanTearOff(BOOL tear_off);
// add a separator to this menu
virtual BOOL addSeparator();
@ -553,7 +552,6 @@ private:
class LLMenuItemTearOffGL* mTearOffItem;
class LLMenuItemBranchGL* mSpilloverBranch;
LLMenuGL* mSpilloverMenu;
LLHandle<LLFloater> mParentFloaterHandle;
KEY mJumpKey;
BOOL mCreateJumpKeys;
S32 mShortcutPad;
@ -814,7 +812,6 @@ class LLMenuItemTearOffGL : public LLMenuItemGL
public:
struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
{
Optional<LLHandle<LLFloater> > parent_floater_handle;
Params()
{
name = "tear off";
@ -823,13 +820,12 @@ public:
};
LLMenuItemTearOffGL( const Params& );
virtual void onCommit(void);
virtual void draw(void);
virtual U32 getNominalHeight() const;
private:
LLHandle<LLFloater> mParentHandle;
LLFloater* getParentFloater();
};

View File

@ -92,14 +92,6 @@ void LLMultiFloater::draw()
}
else
{
for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
{
mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
}
}
LLFloater::draw();
}
}

View File

@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
params.font(p.font);
params.max_length_bytes(MAX_STRING_LENGTH);
params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
params.prevalidate_callback(&LLLineEditor::prevalidateFloat);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );
@ -330,9 +330,14 @@ void LLMultiSliderCtrl::updateText()
// static
void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata)
{
LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
llassert(ctrl);
if (!ctrl)
return;
LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
llassert(self);
if (!self) // cast failed - wrong type! :O
return;
BOOL success = FALSE;
F32 val = self->mCurValue;

View File

@ -371,7 +371,7 @@ private:
// this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT
// for anything real!
LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mTemporaryResponder(false) {}
LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {}
void cancel();

View File

@ -80,6 +80,8 @@ LLPanel::Params::Params()
background_opaque("background_opaque", false),
bg_opaque_color("bg_opaque_color"),
bg_alpha_color("bg_alpha_color"),
bg_opaque_image_overlay("bg_opaque_image_overlay"),
bg_alpha_image_overlay("bg_alpha_image_overlay"),
bg_opaque_image("bg_opaque_image"),
bg_alpha_image("bg_alpha_image"),
min_width("min_width", 100),
@ -103,6 +105,8 @@ LLPanel::LLPanel(const LLPanel::Params& p)
mBgOpaque(p.background_opaque),
mBgOpaqueColor(p.bg_opaque_color()),
mBgAlphaColor(p.bg_alpha_color()),
mBgOpaqueImageOverlay(p.bg_opaque_image_overlay),
mBgAlphaImageOverlay(p.bg_alpha_image_overlay),
mBgOpaqueImage(p.bg_opaque_image()),
mBgAlphaImage(p.bg_alpha_image()),
mDefaultBtn(NULL),
@ -199,7 +203,7 @@ void LLPanel::draw()
// opaque, in-front look
if (mBgOpaqueImage.notNull())
{
mBgOpaqueImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
mBgOpaqueImage->draw( local_rect, mBgOpaqueImageOverlay % alpha );
}
else
{
@ -212,7 +216,7 @@ void LLPanel::draw()
// transparent, in-back look
if (mBgAlphaImage.notNull())
{
mBgAlphaImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
mBgAlphaImage->draw( local_rect, mBgAlphaImageOverlay % alpha );
}
else
{
@ -397,6 +401,12 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
if (!panelp)
{
panelp = LLUICtrlFactory::getInstance()->createFactoryPanel(name);
llassert(panelp);
if (!panelp)
{
return NULL; // :(
}
}
}
@ -414,7 +424,7 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
panelp->mCommitCallbackRegistrar.popScope();
panelp->mEnableCallbackRegistrar.popScope();
if (panelp && !panelp->getFactoryMap().empty())
if (!panelp->getFactoryMap().empty())
{
LLUICtrlFactory::instance().popFactoryFunctions();
}
@ -475,6 +485,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
setTransparentColor(p.bg_alpha_color().get());
mBgOpaqueImage = p.bg_opaque_image();
mBgAlphaImage = p.bg_alpha_image();
mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
}
static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
@ -936,7 +948,7 @@ LLPanel *LLPanel::childGetVisiblePanelWithHelp()
return ::childGetVisiblePanelWithHelp(this);
}
void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
void LLPanel::childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) )
{
LLLineEditor* child = findChild<LLLineEditor>(id);
if (child)

View File

@ -77,7 +77,9 @@ public:
background_opaque;
Optional<LLUIColor> bg_opaque_color,
bg_alpha_color;
bg_alpha_color,
bg_opaque_image_overlay,
bg_alpha_image_overlay;
// opaque image is for "panel in foreground" look
Optional<LLUIImage*> bg_opaque_image,
bg_alpha_image;
@ -137,6 +139,8 @@ public:
const LLColor4& getTransparentColor() const { return mBgAlphaColor; }
LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; }
LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; }
LLColor4 getBackgroundImageOverlay() { return mBgOpaqueImageOverlay; }
LLColor4 getTransparentImageOverlay() { return mBgAlphaImageOverlay; }
void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
BOOL isBackgroundVisible() const { return mBgVisible; }
void setBackgroundOpaque(BOOL b) { mBgOpaque = b; }
@ -226,7 +230,7 @@ public:
std::string childGetText(const std::string& id) const { return childGetValue(id).asString(); }
// LLLineEditor
void childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) );
void childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) );
// LLButton
void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value = NULL);
@ -262,6 +266,8 @@ private:
BOOL mBgOpaque; // use opaque color or image
LLUIColor mBgOpaqueColor;
LLUIColor mBgAlphaColor;
LLUIColor mBgOpaqueImageOverlay;
LLUIColor mBgAlphaImageOverlay;
LLPointer<LLUIImage> mBgOpaqueImage; // "panel in front" look
LLPointer<LLUIImage> mBgAlphaImage; // "panel in back" look
LLViewBorder* mBorder;

View File

@ -124,7 +124,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
{
// Make sure the mouse in still over the application. We don't want to make the parent
// so big that we can't see the resize handle any more.
S32 screen_x;
S32 screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
@ -136,9 +136,10 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
if( resizing_view )
{
// undock floater when user resize it
if (((LLFloater*)getParent())->isDocked())
LLFloater* floater_parent = dynamic_cast<LLFloater*>(getParent());
if (floater_parent && floater_parent->isDocked())
{
((LLFloater*)getParent())->setDocked(false, false);
floater_parent->setDocked(false, false);
}
// Resize the parent
@ -146,61 +147,68 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
LLRect scaled_rect = orig_rect;
S32 delta_x = screen_x - mDragLastScreenX;
S32 delta_y = screen_y - mDragLastScreenY;
if(delta_x == 0 && delta_y == 0)
return FALSE;
LLCoordGL mouse_dir;
// use hysteresis on mouse motion to preserve user intent when mouse stops moving
mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
mLastMouseScreenX = screen_x;
mLastMouseScreenY = screen_y;
mLastMouseDir = mouse_dir;
S32 new_width = orig_rect.getWidth();
S32 new_height = orig_rect.getHeight();
S32 new_pos_x = orig_rect.mLeft;
S32 new_pos_y = orig_rect.mTop;
S32 x_multiple = 1;
S32 y_multiple = 1;
switch( mCorner )
{
case LEFT_TOP:
new_width-=delta_x;
new_height+=delta_y;
new_pos_x+=delta_x;
new_pos_y+=delta_y;
x_multiple = -1;
y_multiple = 1;
break;
case LEFT_BOTTOM:
new_width-=delta_x;
new_height-=delta_y;
new_pos_x+=delta_x;
x_multiple = -1;
y_multiple = -1;
break;
case RIGHT_TOP:
new_width+=delta_x;
new_height+=delta_y;
new_pos_y+=delta_y;
x_multiple = 1;
y_multiple = 1;
break;
case RIGHT_BOTTOM:
new_width+=delta_x;
new_height-=delta_y;
x_multiple = 1;
y_multiple = -1;
break;
}
S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
if( new_width < mMinWidth )
{
new_width = mMinWidth;
delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
}
S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
if( new_height < mMinHeight )
{
new_height = mMinHeight;
delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
}
switch( mCorner )
{
case LEFT_TOP:
scaled_rect.translate(delta_x, 0);
break;
case LEFT_BOTTOM:
scaled_rect.translate(delta_x, delta_y);
break;
case RIGHT_TOP:
break;
case RIGHT_BOTTOM:
scaled_rect.translate(0, delta_y);
break;
}
new_width = llmax(new_width,mMinWidth);
new_height = llmax(new_height,mMinHeight);
LLRect::tCoordType screen_width = resizing_view->getParent()->getSnapRect().getWidth();
LLRect::tCoordType screen_height = resizing_view->getParent()->getSnapRect().getHeight();
new_width = llmin(new_width, screen_width);
new_height = llmin(new_height, screen_height);
// temporarily set new parent rect
scaled_rect.setLeftTopAndSize(new_pos_x,new_pos_y,new_width,new_height);
scaled_rect.mRight = scaled_rect.mLeft + new_width;
scaled_rect.mTop = scaled_rect.mBottom + new_height;
resizing_view->setRect(scaled_rect);
LLView* snap_view = NULL;
@ -251,11 +259,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
resizing_view->setRect(orig_rect);
// translate and scale to new shape
resizing_view->reshape(scaled_rect.getWidth(),scaled_rect.getHeight());
resizing_view->setRect(scaled_rect);
//set shape to handle dependent floaters...
resizing_view->handleReshape(scaled_rect, false);
resizing_view->setShape(scaled_rect, true);
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = resizing_view->getRect();

View File

@ -71,8 +71,9 @@ static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
// local structures & classes.
struct SortScrollListItem
{
SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders)
SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal)
: mSortOrders(sort_orders)
, mSortSignal(sort_signal)
{}
bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
@ -85,12 +86,20 @@ struct SortScrollListItem
S32 col_idx = it->first;
BOOL sort_ascending = it->second;
S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column?
const LLScrollListCell *cell1 = i1->getColumn(col_idx);
const LLScrollListCell *cell2 = i2->getColumn(col_idx);
S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column?
if (cell1 && cell2)
{
sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
if(mSortSignal)
{
sort_result = order * (*mSortSignal)(col_idx,i1, i2);
}
else
{
sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
}
if (sort_result != 0)
{
break; // we have a sort order!
@ -100,8 +109,10 @@ struct SortScrollListItem
return sort_result < 0;
}
typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
const LLScrollListCtrl::sort_signal_t* mSortSignal;
const sort_order_t& mSortOrders;
};
@ -169,6 +180,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mOnSortChangedCallback( NULL ),
mHighlightedItem(-1),
mBorder(NULL),
mSortCallback(NULL),
mPopupMenu(NULL),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
@ -309,6 +321,8 @@ bool LLScrollListCtrl::preProcessChildNode(LLXMLNodePtr child)
LLScrollListCtrl::~LLScrollListCtrl()
{
delete mSortCallback;
std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
if( gEditMenuHandler == this )
@ -540,7 +554,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
std::stable_sort(
mItemList.begin(),
mItemList.end(),
SortScrollListItem(single_sort_column));
SortScrollListItem(single_sort_column,mSortCallback));
// ADD_SORTED just sorts by first column...
// this might not match user sort criteria, so flag list as being in unsorted state
@ -1388,6 +1402,8 @@ void LLScrollListCtrl::drawItems()
LLGLSUIDefault gls_ui;
F32 alpha = getDrawContext().mAlpha;
{
LLLocalClipRect clip(mItemListRect);
@ -1463,7 +1479,7 @@ void LLScrollListCtrl::drawItems()
bg_color = mBgReadOnlyColor.get();
}
item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding);
item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding);
cur_y -= mLineHeight;
}
@ -2393,7 +2409,7 @@ void LLScrollListCtrl::updateSort() const
std::stable_sort(
mItemList.begin(),
mItemList.end(),
SortScrollListItem(mSortColumns));
SortScrollListItem(mSortColumns,mSortCallback));
mSorted = true;
}
@ -2409,7 +2425,7 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending)
std::stable_sort(
mItemList.begin(),
mItemList.end(),
SortScrollListItem(sort_column));
SortScrollListItem(sort_column,mSortCallback));
}
void LLScrollListCtrl::dirtyColumns()

View File

@ -73,6 +73,32 @@ public:
// *TODO: Add callbacks to Params
typedef boost::function<void (void)> callback_t;
template<typename T> struct maximum
{
typedef T result_type;
template<typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
// If there are no slots to call, just return the
// default-constructed value
if(first == last ) return T();
T max_value = *first++;
while (first != last) {
if (max_value < *first)
max_value = *first;
++first;
}
return max_value;
}
};
//typedef boost::signals2::signal<void (S32,const LLScrollListItem*,const LLScrollListItem*),maximum<S32>> sort_signal_t;
//typedef boost::signals2::signal<void (S32,const LLScrollListItem*,const LLScrollListItem*)> sort_signal_t;
typedef boost::signals2::signal<S32 (S32,const LLScrollListItem*,const LLScrollListItem*),maximum<S32> > sort_signal_t;
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@ -362,6 +388,13 @@ public:
void setNeedsSort(bool val = true) { mSorted = !val; }
void dirtyColumns(); // some operation has potentially affected column layout or ordering
boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb )
{
if (!mSortCallback) mSortCallback = new sort_signal_t();
return mSortCallback->connect(cb);
}
protected:
// "Full" interface: use this when you're creating a list that has one or more of the following:
// * contains icons
@ -474,6 +507,8 @@ private:
typedef std::pair<S32, BOOL> sort_column_t;
std::vector<sort_column_t> mSortColumns;
sort_signal_t* mSortCallback;
}; // end class LLScrollListCtrl
#endif // LL_SCROLLLISTCTRL_H

View File

@ -60,6 +60,7 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
line_editor_params.keystroke_callback(boost::bind(&LLSearchEditor::handleKeystroke, this));
mSearchEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_params);
mSearchEditor->setPassDelete(TRUE);
addChild(mSearchEditor);
if (p.search_button_visible)
@ -79,10 +80,12 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
if (p.clear_button_visible)
{
// Set up clear button.
S32 clr_btn_width = getRect().getHeight(); // button is square, and as tall as search editor
LLRect clear_btn_rect(getRect().getWidth() - clr_btn_width, getRect().getHeight(), getRect().getWidth(), 0);
LLButton::Params clr_btn_params(p.clear_button);
clr_btn_params.name(std::string("clear button"));
S32 clr_btn_top = clr_btn_params.rect.bottom + clr_btn_params.rect.height;
S32 clr_btn_right = getRect().getWidth() - clr_btn_params.pad_right;
S32 clr_btn_left = clr_btn_right - clr_btn_params.rect.width;
LLRect clear_btn_rect(clr_btn_left, clr_btn_top, clr_btn_right, p.clear_button.rect.bottom);
clr_btn_params.rect(clear_btn_rect) ;
clr_btn_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
clr_btn_params.tab_stop(false);
@ -153,7 +156,7 @@ void LLSearchEditor::setFocus( BOOL b )
void LLSearchEditor::onClearButtonClick(const LLSD& data)
{
setText(LLStringUtil::null);
mSearchEditor->doDelete(); // force keystroke callback
mSearchEditor->onCommit(); // force keystroke callback
}
void LLSearchEditor::handleKeystroke()

View File

@ -141,7 +141,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
line_p.rect.setIfNotProvided(text_rect);
line_p.font.setIfNotProvided(p.font);
line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit);
line_p.prevalidate_callback(&LLLineEditor::prevalidateFloat);
line_p.prevalidate_callback(&LLTextValidate::validateFloat);
mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p);
mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this ));

View File

@ -127,7 +127,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
}
params.max_length_bytes(MAX_STRING_LENGTH);
params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
params.prevalidate_callback(&LLLineEditor::prevalidateFloat);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));
@ -270,13 +270,19 @@ void LLSpinCtrl::clear()
mbHasBeenSet = FALSE;
}
void LLSpinCtrl::updateLabelColor()
{
if( mLabelBox )
{
mLabelBox->setColor( getEnabled() ? mTextEnabledColor.get() : mTextDisabledColor.get() );
}
}
void LLSpinCtrl::updateEditor()
{
LLLocale locale(LLLocale::USER_LOCALE);
// Don't display very small negative values as -0.000
// Don't display very small negative valu es as -0.000
F32 displayed_value = clamp_precision((F32)getValue().asReal(), mPrecision);
// if( S32( displayed_value * pow( 10, mPrecision ) ) == 0 )
@ -339,10 +345,7 @@ void LLSpinCtrl::setEnabled(BOOL b)
{
LLView::setEnabled( b );
mEditor->setEnabled( b );
if( mLabelBox )
{
mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
}
updateLabelColor();
}
@ -390,6 +393,7 @@ void LLSpinCtrl::setLabel(const LLStringExplicit& label)
{
llwarns << "Attempting to set label on LLSpinCtrl constructed without one " << getName() << llendl;
}
updateLabelColor();
}
void LLSpinCtrl::setAllowEdit(BOOL allow_edit)

View File

@ -81,8 +81,8 @@ public:
virtual void setPrecision(S32 precision);
void setLabel(const LLStringExplicit& label);
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }
void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; }
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; updateLabelColor(); }
void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; updateLabelColor();}
void setAllowEdit(BOOL allow_edit);
virtual void onTabInto();
@ -103,6 +103,7 @@ public:
void onDownBtn(const LLSD& data);
private:
void updateLabelColor();
void updateEditor();
void reportInvalidData();

View File

@ -59,11 +59,12 @@ public:
void setColor(const LLColor4 &color) { mColor = color; }
const LLColor4& getReadOnlyColor() const { return mReadOnlyColor; }
void setReadOnlyColor(const LLColor4& color) { mReadOnlyColor = color; }
BOOL isVisible() const;
void setVisible(BOOL is_visible);
LLFontGL::ShadowType getShadowType() { return mDropShadow; }
LLFontGL::ShadowType getShadowType() const { return mDropShadow; }
void setFont(const LLFontGL* font);
const LLFontGL* getFont() const;
@ -116,5 +117,6 @@ private:
};
typedef LLPointer<LLStyle> LLStyleSP;
typedef LLPointer<const LLStyle> LLStyleConstSP;
#endif // LL_LLSTYLE_H

View File

@ -35,7 +35,6 @@
#include "lltabcontainer.h"
#include "llfocusmgr.h"
#include "llbutton.h"
#include "lllocalcliprect.h"
#include "llrect.h"
#include "llresizehandle.h"
@ -96,6 +95,95 @@ public:
//----------------------------------------------------------------------------
//============================================================================
/*
* @file lltabcontainer.cpp
* @brief class implements LLButton with LLIconCtrl on it
*/
class LLCustomButtonIconCtrl : public LLButton
{
public:
struct Params
: public LLInitParam::Block<Params, LLButton::Params>
{
// LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value
Optional<S32> icon_ctrl_pad;
Params():
icon_ctrl_pad("icon_ctrl_pad", 1)
{}
};
protected:
friend class LLUICtrlFactory;
LLCustomButtonIconCtrl(const Params& p):
LLButton(p),
mIcon(NULL),
mIconAlignment(LLFontGL::HCENTER),
mIconCtrlPad(p.icon_ctrl_pad)
{}
public:
void updateLayout()
{
LLRect button_rect = getRect();
LLRect icon_rect = mIcon->getRect();
S32 icon_size = button_rect.getHeight() - 2*mIconCtrlPad;
switch(mIconAlignment)
{
case LLFontGL::LEFT:
icon_rect.setLeftTopAndSize(button_rect.mLeft + mIconCtrlPad, button_rect.mTop - mIconCtrlPad,
icon_size, icon_size);
setLeftHPad(icon_size + mIconCtrlPad * 2);
break;
case LLFontGL::HCENTER:
icon_rect.setLeftTopAndSize(button_rect.mRight - (button_rect.getWidth() + mIconCtrlPad - icon_size)/2, button_rect.mTop - mIconCtrlPad,
icon_size, icon_size);
setRightHPad(icon_size + mIconCtrlPad * 2);
break;
case LLFontGL::RIGHT:
icon_rect.setLeftTopAndSize(button_rect.mRight - mIconCtrlPad - icon_size, button_rect.mTop - mIconCtrlPad,
icon_size, icon_size);
setRightHPad(icon_size + mIconCtrlPad * 2);
break;
default:
break;
}
mIcon->setRect(icon_rect);
}
void setIcon(LLIconCtrl* icon, LLFontGL::HAlign alignment = LLFontGL::LEFT)
{
if(icon)
{
if(mIcon)
{
removeChild(mIcon);
mIcon->die();
}
mIcon = icon;
mIconAlignment = alignment;
addChild(mIcon);
updateLayout();
}
}
LLIconCtrl* getIconCtrl() const
{
return mIcon;
}
private:
LLIconCtrl* mIcon;
LLFontGL::HAlign mIconAlignment;
S32 mIconCtrlPad;
};
//============================================================================
struct LLPlaceHolderPanel : public LLPanel
{
// create dummy param block to register with "placeholder" nane
@ -127,7 +215,11 @@ LLTabContainer::Params::Params()
tab_padding_right("tab_padding_right"),
first_tab("first_tab"),
middle_tab("middle_tab"),
last_tab("last_tab")
last_tab("last_tab"),
use_custom_icon_ctrl("use_custom_icon_ctrl", false),
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
use_ellipses("use_ellipses"),
font_halign("halign")
{
name(std::string("tab_container"));
mouse_opaque = false;
@ -162,7 +254,10 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mFont(p.font),
mFirstTabParams(p.first_tab),
mMiddleTabParams(p.middle_tab),
mLastTabParams(p.last_tab)
mLastTabParams(p.last_tab),
mCustomIconCtrlUsed(p.use_custom_icon_ctrl),
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
mUseTabEllipses(p.use_ellipses)
{
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
@ -801,6 +896,10 @@ void LLTabContainer::update_images(LLTabTuple* tuple, TabParams params, LLTabCon
void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
LLPanel* child = panel.panel();
llassert(child);
if (!child) return;
const std::string& label = panel.label.isProvided()
? panel.label()
: panel.panel()->getLabel();
@ -905,6 +1004,11 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLTextBox* textbox = NULL;
LLButton* btn = NULL;
LLCustomButtonIconCtrl::Params custom_btn_params;
{
custom_btn_params.icon_ctrl_pad(mTabIconCtrlPad);
}
LLButton::Params normal_btn_params;
if (placeholder)
{
@ -924,7 +1028,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
if (mIsVertical)
{
LLButton::Params p;
LLButton::Params& p = (mCustomIconCtrlUsed)?
custom_btn_params:normal_btn_params;
p.name(std::string("vert tab button"));
p.rect(btn_rect);
p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
@ -942,11 +1048,22 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
p.pad_left(indent);
}
btn = LLUICtrlFactory::create<LLButton>(p);
if(mCustomIconCtrlUsed)
{
btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
}
else
{
btn = LLUICtrlFactory::create<LLButton>(p);
}
}
else
{
LLButton::Params p;
LLButton::Params& p = (mCustomIconCtrlUsed)?
custom_btn_params:normal_btn_params;
p.name(std::string(child->getName()) + " tab");
p.rect(btn_rect);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
@ -980,7 +1097,14 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
}
++ btn = LLUICtrlFactory::create<LLButton>(p);
if(mCustomIconCtrlUsed)
{
btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
}
else
{
btn = LLUICtrlFactory::create<LLButton>(p);
}
}
}
@ -1373,8 +1497,8 @@ BOOL LLTabContainer::setTab(S32 which)
{
LLTabTuple* tuple = *iter;
BOOL is_selected = ( tuple == selected_tuple );
tuple->mButton->setUseEllipses(TRUE);
tuple->mButton->setHAlign(LLFontGL::LEFT);
tuple->mButton->setUseEllipses(mUseTabEllipses);
tuple->mButton->setHAlign(mFontHalign);
tuple->mTabPanel->setVisible( is_selected );
// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
tuple->mButton->setToggleState( is_selected );
@ -1484,7 +1608,7 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
if( tuple )
{
tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color);
reshape_tuple(tuple);
reshapeTuple(tuple);
}
}
@ -1494,31 +1618,48 @@ void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const L
if( tuple )
{
tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color);
reshape_tuple(tuple);
reshapeTuple(tuple);
}
}
void LLTabContainer::reshape_tuple(LLTabTuple* tuple)
void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
{
LLTabTuple* tuple = getTabByPanel(child);
LLCustomButtonIconCtrl* button;
if(tuple)
{
button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
if(button)
{
button->setIcon(icon);
reshapeTuple(tuple);
}
}
}
void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
{
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
static LLUICachedControl<S32> image_left_padding ("UIButtonImageLeftPadding", 4);
static LLUICachedControl<S32> image_right_padding ("UIButtonImageRightPadding", 4);
static LLUICachedControl<S32> image_top_padding ("UIButtonImageTopPadding", 2);
static LLUICachedControl<S32> image_bottom_padding ("UIButtonImageBottomPadding", 2);
if (!mIsVertical)
{
tuple->mButton->setImageOverlayLeftPad(image_left_padding);
tuple->mButton->setImageOverlayRightPad(image_right_padding);
tuple->mButton->setImageOverlayTopPad(image_top_padding);
tuple->mButton->setImageOverlayBottomPad(image_bottom_padding);
S32 image_overlay_width = 0;
if(mCustomIconCtrlUsed)
{
LLCustomButtonIconCtrl* button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
LLIconCtrl* icon_ctrl = button->getIconCtrl();
image_overlay_width = icon_ctrl ? icon_ctrl->getRect().getWidth() : 0;
}
else
{
image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
}
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
tuple->mPadding = image_overlay_width;
tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),

View File

@ -36,6 +36,8 @@
#include "llpanel.h"
#include "lltextbox.h"
#include "llframetimer.h"
#include "lliconctrl.h"
#include "llbutton.h"
class LLTabTuple;
@ -90,6 +92,26 @@ public:
middle_tab,
last_tab;
/**
* Tab label horizontal alignment
*/
Optional<LLFontGL::HAlign> font_halign;
/**
* Tab label ellipses
*/
Optional<bool> use_ellipses;
/**
* Use LLCustomButtonIconCtrl or LLButton in LLTabTuple
*/
Optional<bool> use_custom_icon_ctrl;
/**
* Paddings for LLIconCtrl in case of LLCustomButtonIconCtrl usage(use_custom_icon_ctrl = true)
*/
Optional<S32> tab_icon_ctrl_pad;
Params();
};
@ -173,6 +195,7 @@ public:
void setTabPanelFlashing(LLPanel* child, BOOL state);
void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
void setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);
void setTabImage(LLPanel* child, LLIconCtrl* icon);
void setTitle( const std::string& title );
const std::string getPanelTitle(S32 index);
@ -228,7 +251,7 @@ private:
// updates tab button images given the tuple, tab position and the corresponding params
void update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos);
void reshape_tuple(LLTabTuple* tuple);
void reshapeTuple(LLTabTuple* tuple);
// Variables
@ -278,6 +301,10 @@ private:
TabParams mFirstTabParams;
TabParams mMiddleTabParams;
TabParams mLastTabParams;
bool mCustomIconCtrlUsed;
S32 mTabIconCtrlPad;
bool mUseTabEllipses;
};
#endif // LL_TABCONTAINER_H

View File

@ -185,7 +185,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mWriteableBgColor(p.bg_writeable_color),
mReadOnlyBgColor(p.bg_readonly_color),
mFocusBgColor(p.bg_focus_color),
mReflowNeeded(FALSE),
mReflowIndex(S32_MAX),
mCursorPos( 0 ),
mScrollNeeded(FALSE),
mDesiredXPixel(-1),
@ -292,9 +292,13 @@ bool LLTextBase::truncate()
return did_truncate;
}
LLStyle::Params LLTextBase::getDefaultStyle()
LLStyle::Params LLTextBase::getDefaultStyleParams()
{
return LLStyle::Params().color(mFgColor.get()).readonly_color(mReadOnlyFgColor.get()).font(mDefaultFont).drop_shadow(mFontShadow);
return LLStyle::Params()
.color(LLUIColor(&mFgColor))
.readonly_color(LLUIColor(&mReadOnlyFgColor))
.font(mDefaultFont)
.drop_shadow(mFontShadow);
}
void LLTextBase::onValueChange(S32 start, S32 end)
@ -308,7 +312,6 @@ void LLTextBase::drawSelectionBackground()
// Draw selection even if we don't have keyboard focus for search/replace
if( hasSelection() && !mLineInfoList.empty())
{
LLWString text = getWText();
std::vector<LLRect> selection_rects;
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
@ -407,7 +410,7 @@ void LLTextBase::drawCursor()
&& gFocusMgr.getAppHasFocus()
&& !mReadOnly)
{
LLWString wtext = getWText();
const LLWString &wtext = getWText();
const llwchar* text = wtext.c_str();
LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
@ -493,7 +496,6 @@ void LLTextBase::drawCursor()
void LLTextBase::drawText()
{
LLWString text = getWText();
const S32 text_len = getLength();
if( text_len <= 0 )
{
@ -620,7 +622,8 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
else
{
// create default editable segment to hold new text
default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), pos, pos + insert_len, *this);
LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
default_segment = new LLNormalTextSegment( sp, pos, pos + insert_len, *this);
}
// shift remaining segments to right
@ -657,7 +660,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
}
onValueChange(pos, pos + insert_len);
needsReflow();
needsReflow(pos);
return insert_len;
}
@ -717,7 +720,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
createDefaultSegment();
onValueChange(pos, pos);
needsReflow();
needsReflow(pos);
return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
}
@ -733,7 +736,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
getViewModel()->setDisplay(text);
onValueChange(pos, pos + 1);
needsReflow();
needsReflow(pos);
return 1;
}
@ -744,7 +747,8 @@ void LLTextBase::createDefaultSegment()
// ensures that there is always at least one segment
if (mSegments.empty())
{
LLTextSegmentPtr default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this);
LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this);
mSegments.insert(default_segment);
default_segment->linkToDocument(this);
}
@ -758,15 +762,18 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
}
segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart());
S32 reflow_start_index = 0;
if (cur_seg_iter == mSegments.end())
{
mSegments.insert(segment_to_insert);
segment_to_insert->linkToDocument(this);
reflow_start_index = segment_to_insert->getStart();
}
else
{
LLTextSegmentPtr cur_segmentp = *cur_seg_iter;
reflow_start_index = cur_segmentp->getStart();
if (cur_segmentp->getStart() < segment_to_insert->getStart())
{
S32 old_segment_end = cur_segmentp->getEnd();
@ -774,7 +781,8 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
cur_segmentp->setEnd(segment_to_insert->getStart());
// advance to next segment
// insert remainder of old segment
LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this);
LLStyleConstSP sp = cur_segmentp->getStyle();
LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( sp, segment_to_insert->getStart(), old_segment_end, *this);
mSegments.insert(cur_seg_iter, remainder_segment);
remainder_segment->linkToDocument(this);
// insert new segment before remainder of old segment
@ -824,7 +832,7 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
}
// layout potentially changed
needsReflow();
needsReflow(reflow_start_index);
}
BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
@ -1010,16 +1018,6 @@ void LLTextBase::draw()
void LLTextBase::setColor( const LLColor4& c )
{
mFgColor = c;
//textsegments have own style property ,
//so we have to update it also to apply changes, EXT-4433
for(segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); it++)
{
LLTextSegment* segment = it->get();
if(segment)
{
segment->setColor(mFgColor);
}
}
}
//virtual
@ -1028,6 +1026,16 @@ void LLTextBase::setReadOnlyColor(const LLColor4 &c)
mReadOnlyFgColor = c;
}
//virtual
void LLTextBase::handleVisibilityChange( BOOL new_visibility )
{
if(!new_visibility && mPopupMenu)
{
mPopupMenu->hide();
}
LLUICtrl::handleVisibilityChange(new_visibility);
}
//virtual
void LLTextBase::setValue(const LLSD& value )
{
@ -1079,15 +1087,16 @@ S32 LLTextBase::getLeftOffset(S32 width)
static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
void LLTextBase::reflow(S32 start_index)
void LLTextBase::reflow()
{
LLFastTimer ft(FTM_TEXT_REFLOW);
updateSegments();
while(mReflowNeeded)
while(mReflowIndex < S32_MAX)
{
mReflowNeeded = false;
S32 start_index = mReflowIndex;
mReflowIndex = S32_MAX;
// shrink document to minimum size (visible portion of text widget)
// to force inlined widgets with follows set to shrink
@ -1119,7 +1128,6 @@ void LLTextBase::reflow(S32 start_index)
S32 line_start_index = 0;
const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin
S32 remaining_pixels = text_available_width;
LLWString text(getWText());
S32 line_count = 0;
// find and erase line info structs starting at start_index and going to end of document
@ -1129,6 +1137,7 @@ void LLTextBase::reflow(S32 start_index)
line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
line_start_index = iter->mDocIndexStart;
line_count = iter->mLineNum;
cur_top = iter->mRect.mTop;
getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
mLineInfoList.erase(iter, mLineInfoList.end());
}
@ -1436,10 +1445,10 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i
}
// Finds the text segment (if any) at the give local screen position
LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line)
{
// Find the cursor position at the requested local screen position
S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
S32 offset = getDocIndexFromLocalCoord( x, y, FALSE, hit_past_end_of_line);
segment_set_t::iterator seg_iter = getSegIterContaining(offset);
if (seg_iter != mSegments.end())
{
@ -1521,16 +1530,7 @@ std::string LLTextBase::getText() const
void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
style_params.fillFrom(getDefaultStyle());
if (!style_params.font.isProvided())
{
style_params.font = mDefaultFont;
}
if (!style_params.drop_shadow.isProvided())
{
style_params.drop_shadow = mFontShadow;
}
style_params.fillFrom(getDefaultStyleParams());
S32 part = (S32)LLTextParser::WHOLE;
if(mParseHTML)
@ -1547,13 +1547,7 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
LLStyle::Params link_params = style_params;
link_params.color = match.getColor();
link_params.readonly_color = match.getColor();
// apply font name from requested style_params
std::string font_name = LLFontGL::nameFromFont(style_params.font());
std::string font_size = LLFontGL::sizeFromFont(style_params.font());
link_params.font.name(font_name);
link_params.font.size(font_size);
link_params.font.style("UNDERLINE");
link_params.link_href = match.getUrl();
// output the text before the Url
@ -1581,8 +1575,10 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
{
LLStyle::Params icon;
icon.image = image;
// HACK: fix spacing of images and remove the fixed char spacing
appendAndHighlightText(" ", prepend_newline, part, icon);
// Text will be replaced during rendering with the icon,
// but string cannot be empty or the segment won't be
// added (or drawn).
appendAndHighlightText(" ", prepend_newline, part, icon);
prepend_newline = false;
}
}
@ -1630,9 +1626,15 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
}
}
void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& stylep)
void LLTextBase::needsReflow(S32 index)
{
if (new_text.empty()) return;
lldebugs << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << llendl;
mReflowIndex = llmin(mReflowIndex, index);
}
void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& style_params)
{
if (new_text.empty()) return;
// Save old state
S32 selection_start = mSelectionStart;
@ -1650,7 +1652,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
if (mParseHighlights && highlight)
{
LLStyle::Params highlight_params = stylep;
LLStyle::Params highlight_params(style_params);
LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part);
for (S32 i = 0; i < pieces.size(); i++)
@ -1670,7 +1672,8 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
}
S32 cur_length = getLength();
LLTextSegmentPtr segmentp = new LLNormalTextSegment(new LLStyle(highlight_params), cur_length, cur_length + wide_text.size(), *this);
LLStyleConstSP sp(new LLStyle(highlight_params));
LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
segment_vec_t segments;
segments.push_back(segmentp);
insertStringNoUndo(cur_length, wide_text, &segments);
@ -1694,7 +1697,8 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
segment_vec_t segments;
S32 segment_start = old_length;
S32 segment_end = old_length + wide_text.size();
segments.push_back(new LLNormalTextSegment(new LLStyle(stylep), segment_start, segment_end, *this ));
LLStyleConstSP sp(new LLStyle(style_params));
segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this ));
insertStringNoUndo(getLength(), wide_text, &segments);
}
@ -1738,7 +1742,7 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
for (it = mSegments.begin(); it != mSegments.end(); ++it)
{
LLTextSegment *seg = *it;
const LLStyleSP style = seg->getStyle();
LLStyleConstSP style = seg->getStyle();
// update segment start/end length in case we replaced text earlier
S32 seg_length = seg->getEnd() - seg->getStart();
@ -1775,7 +1779,7 @@ void LLTextBase::setWText(const LLWString& text)
setText(wstring_to_utf8str(text));
}
LLWString LLTextBase::getWText() const
const LLWString& LLTextBase::getWText() const
{
return getViewModel()->getDisplay();
}
@ -1784,7 +1788,7 @@ LLWString LLTextBase::getWText() const
// will be put to its right. If round is false, the cursor will always be put to the
// character's left.
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
{
// Figure out which line we're nearest to.
LLRect visible_region = getVisibleDocumentRect();
@ -1813,7 +1817,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
S32 text_width, text_height;
segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
if (local_x < start_x + text_width // cursor to left of right edge of text
|| segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) // or this segment wraps to next line
|| (hit_past_end_of_line && (segmentp->getEnd() >= line_iter->mDocIndexEnd - 1))) // or this segment wraps to next line
{
// Figure out which character we're nearest to.
S32 offset;
@ -2231,9 +2235,9 @@ bool LLTextSegment::canEdit() const { return false; }
void LLTextSegment::unlinkFromDocument(LLTextBase*) {}
void LLTextSegment::linkToDocument(LLTextBase*) {}
const LLColor4& LLTextSegment::getColor() const { return LLColor4::white; }
void LLTextSegment::setColor(const LLColor4 &color) {}
const LLStyleSP LLTextSegment::getStyle() const {static LLStyleSP sp(new LLStyle()); return sp; }
void LLTextSegment::setStyle(const LLStyleSP &style) {}
//void LLTextSegment::setColor(const LLColor4 &color) {}
LLStyleConstSP LLTextSegment::getStyle() const {static LLStyleConstSP sp(new LLStyle()); return sp; }
void LLTextSegment::setStyle(LLStyleConstSP style) {}
void LLTextSegment::setToken( LLKeywordToken* token ) {}
LLKeywordToken* LLTextSegment::getToken() const { return NULL; }
void LLTextSegment::setToolTip( const std::string &msg ) {}
@ -2258,7 +2262,7 @@ BOOL LLTextSegment::hasMouseCapture() { return FALSE; }
// LLNormalTextSegment
//
LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor )
LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor )
: LLTextSegment(start, end),
mStyle( style ),
mToken(NULL),
@ -2269,7 +2273,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32
LLUIImagePtr image = mStyle->getImage();
if (image.notNull())
{
mImageLoadedConnection = image->addLoadedCallback(boost::bind(&LLTextBase::needsReflow, &mEditor));
mImageLoadedConnection = image->addLoadedCallback(boost::bind(&LLTextBase::needsReflow, &mEditor, start));
}
}
@ -2295,14 +2299,21 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
{
if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
{
// ...for images, only render the image, not the underlying text,
// which is only a placeholder space
LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
// Center the image vertically
S32 image_bottom = draw_rect.getCenterY() - (style_image_height/2);
// Text is drawn from the top of the draw_rect downward
S32 text_center = draw_rect.mTop - (mFontHeight / 2);
// Align image to center of text
S32 image_bottom = text_center - (style_image_height / 2);
image->draw(draw_rect.mLeft, image_bottom,
style_image_width, style_image_height, color);
const S32 IMAGE_HPAD = 3;
return draw_rect.mLeft + style_image_width + IMAGE_HPAD;
}
return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect);
@ -2332,8 +2343,6 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
LLColor4 color = (mEditor.getReadOnly() ? mStyle->getReadOnlyColor() : mStyle->getColor()) % alpha;
font = mStyle->getFont();
if( selection_start > seg_start )
{
// Draw normally
@ -2393,8 +2402,12 @@ BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
return TRUE;
// Only process the click if it's actually in this segment, not to the right of the end-of-line.
if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
{
LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
return TRUE;
}
}
return FALSE;
}
@ -2403,8 +2416,12 @@ BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
return TRUE;
// Only process the click if it's actually in this segment, not to the right of the end-of-line.
if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
{
mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
return TRUE;
}
}
return FALSE;
}
@ -2413,8 +2430,12 @@ BOOL LLNormalTextSegment::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
// eat mouse down event on hyperlinks, so we get the mouse up
return TRUE;
// Only process the click if it's actually in this segment, not to the right of the end-of-line.
if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
{
// eat mouse down event on hyperlinks, so we get the mouse up
return TRUE;
}
}
return FALSE;
@ -2424,8 +2445,12 @@ BOOL LLNormalTextSegment::handleMouseUp(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
{
LLUrlAction::clickAction(getStyle()->getLinkHREF());
return TRUE;
// Only process the click if it's actually in this segment, not to the right of the end-of-line.
if(mEditor.getSegmentAtLocalPos(x, y, false) == this)
{
LLUrlAction::clickAction(getStyle()->getLinkHREF());
return TRUE;
}
}
return FALSE;
@ -2470,7 +2495,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
if (num_chars > 0)
{
height = mFontHeight;
LLWString text = mEditor.getWText();
const LLWString &text = mEditor.getWText();
// if last character is a newline, then return true, forcing line break
llwchar last_char = text[mStart + first_char + num_chars - 1];
if (last_char == '\n')
@ -2497,7 +2522,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
{
LLWString text = mEditor.getWText();
const LLWString &text = mEditor.getWText();
return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
(F32)segment_local_x_coord,
F32_MAX,
@ -2507,12 +2532,12 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,
S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
LLWString text = mEditor.getWText();
const LLWString &text = mEditor.getWText();
LLUIImagePtr image = mStyle->getImage();
if( image.notNull())
{
num_pixels -= image->getWidth();
num_pixels = llmax(0, num_pixels - image->getWidth());
}
// search for newline and if found, truncate there

View File

@ -48,6 +48,7 @@
class LLContextMenu;
class LLTextSegment;
class LLNormalTextSegment;
typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
@ -61,6 +62,9 @@ class LLTextBase
protected LLEditMenuHandler
{
public:
friend class LLTextSegment;
friend class LLNormalTextSegment;
struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams>
{
Alternative<F32> multiple;
@ -122,6 +126,7 @@ public:
/*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; }
/*virtual*/ void setColor( const LLColor4& c );
virtual void setReadOnlyColor(const LLColor4 &c);
virtual void handleVisibilityChange( BOOL new_visibility );
/*virtual*/ void setValue(const LLSD& value );
/*virtual*/ LLTextViewModel* getViewModel() const;
@ -145,11 +150,11 @@ public:
// wide-char versions
void setWText(const LLWString& text);
LLWString getWText() const;
const LLWString& getWText() const;
void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
// force reflow of text
void needsReflow() { mReflowNeeded = TRUE; }
void needsReflow(S32 index = 0);
S32 getLength() const { return getWText().length(); }
S32 getLineCount() const { return mLineInfoList.size(); }
@ -164,7 +169,7 @@ public:
S32 getVPad() { return mVPad; }
S32 getHPad() { return mHPad; }
S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line = true) const;
LLRect getLocalRectFromDocIndex(S32 pos) const;
LLRect getDocRectFromDocIndex(S32 pos) const;
@ -185,7 +190,6 @@ public:
bool scrolledToEnd();
const LLFontGL* getDefaultFont() const { return mDefaultFont; }
LLStyle::Params getDefaultStyle();
public:
// Fired when a URL link is clicked
@ -275,14 +279,15 @@ protected:
// manage segments
void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y );
LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true);
segment_set_t::iterator getSegIterContaining(S32 index);
segment_set_t::const_iterator getSegIterContaining(S32 index) const;
void clearSegments();
void createDefaultSegment();
virtual void updateSegments();
void insertSegment(LLTextSegmentPtr segment_to_insert);
LLStyle::Params getDefaultStyleParams();
// manage lines
S32 getLineStart( S32 line ) const;
S32 getLineEnd( S32 line ) const;
@ -291,7 +296,7 @@ protected:
S32 getFirstVisibleLine() const;
std::pair<S32, S32> getVisibleLines(bool fully_visible = false);
S32 getLeftOffset(S32 width);
void reflow(S32 start_index = 0);
void reflow();
// cursor
void updateCursorXPos();
@ -361,7 +366,7 @@ protected:
class LLScrollContainer* mScroller;
// transient state
bool mReflowNeeded; // need to reflow text because of change to text contents or display region
S32 mReflowIndex; // index at which to start reflow. S32_MAX indicates no reflow needed.
bool mScrollNeeded; // need to change scroll region because of change to cursor position
S32 mScrollIndex; // index of first character to keep visible in scroll region
@ -389,9 +394,9 @@ public:
virtual void linkToDocument(class LLTextBase* editor);
virtual const LLColor4& getColor() const;
virtual void setColor(const LLColor4 &color);
virtual const LLStyleSP getStyle() const;
virtual void setStyle(const LLStyleSP &style);
//virtual void setColor(const LLColor4 &color);
virtual LLStyleConstSP getStyle() const;
virtual void setStyle(LLStyleConstSP style);
virtual void setToken( LLKeywordToken* token );
virtual LLKeywordToken* getToken() const;
virtual void setToolTip(const std::string& tooltip);
@ -427,7 +432,7 @@ protected:
class LLNormalTextSegment : public LLTextSegment
{
public:
LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor );
LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
~LLNormalTextSegment();
@ -437,9 +442,8 @@ public:
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
/*virtual*/ bool canEdit() const { return true; }
/*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
/*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
/*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
/*virtual*/ void setStyle(const LLStyleSP &style) { mStyle = style; }
/*virtual*/ LLStyleConstSP getStyle() const { return mStyle; }
/*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; }
/*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
/*virtual*/ LLKeywordToken* getToken() const { return mToken; }
/*virtual*/ BOOL getToolTip( std::string& msg ) const;
@ -457,7 +461,7 @@ protected:
protected:
class LLTextBase& mEditor;
LLStyleSP mStyle;
LLStyleConstSP mStyle;
S32 mFontHeight;
LLKeywordToken* mToken;
std::string mTooltip;

Some files were not shown because too many files have changed in this diff Show More