From 138bf1132262c479dbbd5c95195db46b1efd065f Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Mon, 24 Aug 2009 20:04:52 +0000 Subject: merge -r 130399-131510 skinning-21 -> viewer-2.0.0-3 DEV-11254 DEV-11254 DEV-2003: DEV-21567 DEV-37301 EXT-104 EXT-138 EXT-217 EXT-256 EXT-259 EXT-259 EXT-328 EXT-348 EXT-386 EXT-399 EXT-403 EXT-460 EXT-492 EXT-492 EXT-531 EXT-537 EXT-684 improved text editor (handles multiple fonts simultaneously as well as inline widgets) --- indra/llcharacter/llcharacter.cpp | 4 +- indra/llcommon/llfasttimer.h | 124 +- indra/llcommon/llmetrics.cpp | 2 +- indra/llcommon/llrefcount.h | 7 +- indra/llcommon/llsd.cpp | 10 +- indra/llcommon/llstring.cpp | 3 + indra/llcommon/llstring.h | 9 + indra/llmath/llrect.h | 28 +- indra/llmessage/llpumpio.cpp | 4 +- indra/llmessage/lltemplatemessagereader.cpp | 4 +- indra/llrender/llfontfreetype.cpp | 14 + indra/llrender/llfontgl.cpp | 474 +--- indra/llrender/llfontgl.h | 27 +- indra/llrender/llfontregistry.cpp | 1 - indra/llrender/llimagegl.cpp | 11 +- indra/llui/llbutton.cpp | 25 +- indra/llui/llcombobox.cpp | 15 +- indra/llui/llcontainerview.cpp | 22 +- indra/llui/llfloater.cpp | 18 +- indra/llui/llkeywords.cpp | 31 +- indra/llui/llkeywords.h | 7 +- indra/llui/lllayoutstack.cpp | 2 +- indra/llui/lllineeditor.cpp | 14 +- indra/llui/llmenugl.cpp | 125 +- indra/llui/llmenugl.h | 23 +- indra/llui/llmodaldialog.cpp | 5 +- indra/llui/llmultifloater.cpp | 10 +- indra/llui/llpanel.cpp | 109 +- indra/llui/llpanel.h | 22 - indra/llui/llradiogroup.cpp | 12 - indra/llui/llradiogroup.h | 2 - indra/llui/llresizehandle.h | 4 +- indra/llui/llscrollbar.cpp | 2 +- indra/llui/llscrollbar.h | 5 - indra/llui/llscrollcontainer.cpp | 247 +- indra/llui/llscrollcontainer.h | 25 +- indra/llui/llscrolllistcell.cpp | 21 +- indra/llui/llscrolllistctrl.cpp | 47 +- indra/llui/llscrolllistctrl.h | 11 +- indra/llui/llstyle.cpp | 133 +- indra/llui/llstyle.h | 67 +- indra/llui/lltabcontainer.cpp | 36 +- indra/llui/lltabcontainer.h | 3 +- indra/llui/lltextbox.cpp | 4 +- indra/llui/lltexteditor.cpp | 2932 +++++++++++--------- indra/llui/lltexteditor.h | 428 +-- indra/llui/llui.cpp | 9 +- indra/llui/llui.h | 3 - indra/llui/lluictrl.cpp | 30 +- indra/llui/lluictrl.h | 8 +- indra/llui/lluictrlfactory.cpp | 36 +- indra/llui/llview.cpp | 43 +- indra/llui/llview.h | 52 +- indra/llui/llviewborder.cpp | 4 +- indra/llvfs/llvfile.cpp | 6 +- indra/llwindow/llwindowwin32.cpp | 17 +- indra/llxml/llcontrol.h | 2 +- indra/llxuixml/llinitparam.h | 1 + indra/llxuixml/lltrans.cpp | 25 + indra/llxuixml/lltrans.h | 10 +- indra/llxuixml/llxuiparser.cpp | 4 +- indra/lscript/lscript_execute/lscript_execute.cpp | 2 - indra/newview/llappviewer.cpp | 62 +- indra/newview/llavatarlist.cpp | 2 +- indra/newview/llbottomtray.cpp | 2 +- indra/newview/llchatbar.cpp | 6 +- indra/newview/llchatitemscontainerctrl.cpp | 2 - indra/newview/llchatmsgbox.cpp | 2 +- indra/newview/lldrawable.cpp | 7 +- indra/newview/lldrawable.h | 1 - indra/newview/lldrawpoolalpha.cpp | 10 +- indra/newview/lldrawpoolavatar.cpp | 19 +- indra/newview/lldrawpoolbump.cpp | 33 +- indra/newview/lldrawpoolsimple.cpp | 28 +- indra/newview/lldrawpoolterrain.cpp | 20 +- indra/newview/lldrawpooltree.cpp | 15 +- indra/newview/lldrawpoolwater.cpp | 2 +- indra/newview/lldrawpoolwlsky.cpp | 2 +- indra/newview/llfasttimerview.cpp | 17 +- indra/newview/llfasttimerview.h | 2 +- indra/newview/llfavoritesbar.cpp | 13 +- indra/newview/llflexibleobject.cpp | 3 +- indra/newview/llfloaterabout.cpp | 28 +- indra/newview/llfloaterbuyland.cpp | 39 +- indra/newview/llfloaterbuyland.h | 1 - indra/newview/llfloaterchat.cpp | 3 +- indra/newview/llfloaterchat.h | 6 - indra/newview/llfloaterfriends.cpp | 2 +- indra/newview/llfloaterinventory.cpp | 6 +- indra/newview/llfloaterland.cpp | 6 +- indra/newview/llfloaterland.h | 1 - indra/newview/llfloaternotificationsconsole.cpp | 3 +- indra/newview/llfloaterpostcard.cpp | 12 +- indra/newview/llfloaterpreference.cpp | 38 +- indra/newview/llfloaterproperties.cpp | 20 +- indra/newview/llfloaterregioninfo.cpp | 1 - indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llfloaterscriptdebug.cpp | 3 - indra/newview/llfloatersettingsdebug.cpp | 1 + indra/newview/llfloatersettingsdebug.h | 3 +- indra/newview/llfloatersnapshot.cpp | 1 - indra/newview/llfloatertos.cpp | 13 +- indra/newview/llfloateruipreview.cpp | 6 +- indra/newview/llfolderview.cpp | 169 +- indra/newview/llfolderview.h | 6 +- indra/newview/llfolderviewitem.cpp | 2 +- indra/newview/llhudmanager.cpp | 3 +- indra/newview/llhudobject.cpp | 4 +- indra/newview/llhudtext.cpp | 2 +- indra/newview/llimpanel.cpp | 95 +- indra/newview/llimview.cpp | 14 +- indra/newview/llinventorybridge.cpp | 4 +- indra/newview/lllocationinputctrl.cpp | 2 +- indra/newview/llnavigationbar.cpp | 3 +- indra/newview/llnearbychat.cpp | 4 +- indra/newview/llnearbychatbar.cpp | 56 +- indra/newview/llnearbychatbar.h | 3 +- indra/newview/llnearbychathandler.cpp | 2 + indra/newview/llpanelclassified.cpp | 5 +- indra/newview/llpanelgrouplandmoney.cpp | 1 + indra/newview/llpanelgrouplandmoney.h | 4 - indra/newview/llpanelgroupnotices.cpp | 2 +- indra/newview/llpanelplace.cpp | 2 +- indra/newview/llpanelplaces.cpp | 10 +- indra/newview/llpreviewnotecard.cpp | 8 - indra/newview/llpreviewscript.cpp | 12 +- indra/newview/llsidetray.cpp | 6 +- indra/newview/llspatialpartition.cpp | 20 +- indra/newview/llstartup.cpp | 3 - indra/newview/llstatusbar.cpp | 2 +- indra/newview/llstylemap.cpp | 74 +- indra/newview/llstylemap.h | 16 +- indra/newview/lltoastgroupnotifypanel.cpp | 25 +- indra/newview/lltoastnotifypanel.cpp | 3 - indra/newview/llviewerdisplay.cpp | 25 +- indra/newview/llviewermenu.cpp | 12 +- indra/newview/llviewermessage.cpp | 3 +- indra/newview/llviewerobject.cpp | 4 +- indra/newview/llviewerobjectlist.cpp | 7 +- indra/newview/llviewerpartsim.cpp | 4 +- indra/newview/llviewerstats.cpp | 12 +- indra/newview/llviewertexteditor.cpp | 589 ++-- indra/newview/llviewertexteditor.h | 9 +- indra/newview/llviewertexturelist.cpp | 13 +- indra/newview/llviewerwindow.cpp | 14 +- indra/newview/llvoavatar.cpp | 18 +- indra/newview/llvoclouds.cpp | 4 +- indra/newview/llvograss.cpp | 4 +- indra/newview/llvopartgroup.cpp | 10 +- indra/newview/llvosky.cpp | 7 +- indra/newview/llvosurfacepatch.cpp | 6 +- indra/newview/llvotree.cpp | 4 +- indra/newview/llvovolume.cpp | 31 +- indra/newview/llvowater.cpp | 4 +- indra/newview/llvowlsky.cpp | 4 +- indra/newview/llwaterparammanager.cpp | 4 +- indra/newview/llwlparammanager.cpp | 5 +- indra/newview/pipeline.cpp | 92 +- indra/newview/pipeline.h | 21 + .../textures/navbar/Favorite_Star_Active.png | Bin 641 -> 704 bytes .../default/textures/navbar/Favorite_Star_Off.png | Bin 573 -> 444 bytes .../default/textures/navbar/Favorite_Star_Over.png | Bin 579 -> 445 bytes .../textures/navbar/Favorite_Star_Press.png | Bin 551 -> 616 bytes .../textures/windows/Icon_Close_Foreground.png | Bin 226 -> 263 bytes .../default/textures/windows/Icon_Close_Press.png | Bin 217 -> 263 bytes .../textures/windows/Icon_Dock_Foreground.png | Bin 240 -> 263 bytes .../default/textures/windows/Icon_Dock_Press.png | Bin 241 -> 263 bytes .../textures/windows/Icon_Undock_Foreground.png | Bin 238 -> 268 bytes .../default/textures/windows/Icon_Undock_Press.png | Bin 260 -> 267 bytes .../newview/skins/default/xui/da/notifications.xml | 2601 +++++++---------- .../newview/skins/default/xui/de/notifications.xml | 3 + indra/newview/skins/default/xui/en/floater_aaa.xml | 8 +- .../newview/skins/default/xui/en/floater_about.xml | 2 +- .../skins/default/xui/en/floater_about_land.xml | 3 +- .../skins/default/xui/en/floater_buy_land.xml | 1 + .../skins/default/xui/en/floater_incoming_call.xml | 4 + .../skins/default/xui/en/floater_land_holdings.xml | 4 +- .../skins/default/xui/en/floater_postcard.xml | 3 +- .../skins/default/xui/en/floater_preferences.xml | 1 + .../default/xui/en/floater_preview_gesture.xml | 248 +- .../default/xui/en/floater_preview_notecard.xml | 1 + indra/newview/skins/default/xui/en/floater_tos.xml | 3 +- .../skins/default/xui/en/floater_world_map.xml | 2 - indra/newview/skins/default/xui/en/menu_login.xml | 4 +- indra/newview/skins/default/xui/en/menu_picks.xml | 2 +- indra/newview/skins/default/xui/en/menu_slurl.xml | 2 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 6 +- .../newview/skins/default/xui/en/notifications.xml | 205 +- .../skins/default/xui/en/panel_bottomtray.xml | 3 + .../skins/default/xui/en/panel_classified.xml | 2 +- .../skins/default/xui/en/panel_edit_profile.xml | 4 +- .../skins/default/xui/en/panel_group_general.xml | 35 - .../default/xui/en/panel_group_info_sidetray.xml | 41 +- .../default/xui/en/panel_group_land_money.xml | 4 +- .../skins/default/xui/en/panel_pick_info.xml | 2 +- .../default/xui/en/panel_preferences_advanced.xml | 10 +- .../default/xui/en/panel_preferences_graphics1.xml | 119 +- .../newview/skins/default/xui/en/panel_profile.xml | 67 +- .../skins/default/xui/en/panel_region_covenant.xml | 1 + .../skins/default/xui/en/panel_region_estate.xml | 1008 +++---- .../skins/default/xui/en/panel_region_texture.xml | 635 ++--- .../skins/default/xui/en/panel_script_ed.xml | 2 + .../skins/default/xui/en/panel_status_bar.xml | 4 +- indra/newview/skins/default/xui/en/strings.xml | 36 +- .../skins/default/xui/en/teleport_strings.xml | 33 +- .../default/xui/en/widgets/gesture_combo_box.xml | 2 +- .../default/xui/en/widgets/location_input.xml | 3 + .../skins/default/xui/en/widgets/scroll_bar.xml | 8 +- .../default/xui/en/widgets/scroll_container.xml | 4 +- .../default/xui/en/widgets/simple_text_editor.xml | 4 +- .../skins/default/xui/es/floater_joystick.xml | 33 +- .../skins/default/xui/es/menu_inventory.xml | 4 +- .../newview/skins/default/xui/es/notifications.xml | 55 +- .../newview/skins/default/xui/es/role_actions.xml | 195 +- indra/newview/skins/default/xui/es/strings.xml | 3 + .../newview/skins/default/xui/fr/notifications.xml | 5 +- .../newview/skins/default/xui/it/floater_tools.xml | 104 +- .../newview/skins/default/xui/it/notifications.xml | 5 +- .../newview/skins/default/xui/ja/notifications.xml | 5 +- .../skins/default/xui/nl/menu_inventory.xml | 4 +- .../newview/skins/default/xui/nl/notifications.xml | 5 +- indra/newview/skins/default/xui/nl/strings.xml | 3 + .../skins/default/xui/pl/floater_god_tools.xml | 6 +- .../newview/skins/default/xui/pl/notifications.xml | 9 +- indra/newview/skins/default/xui/pl/strings.xml | 3 + .../newview/skins/default/xui/pt/notifications.xml | 7 +- .../default/xui/pt/panel_preferences_graphics1.xml | 4 +- 227 files changed, 6201 insertions(+), 6671 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 6633c65317..20ff7bab34 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -180,9 +180,11 @@ void LLCharacter::requestStopMotion( LLMotion* motion) //----------------------------------------------------------------------------- // updateMotions() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation"); + void LLCharacter::updateMotions(e_update_t update_type) { - LLFastTimer t(LLFastTimer::FTM_UPDATE_ANIMATION); + LLFastTimer t(FTM_UPDATE_ANIMATION); if (update_type == HIDDEN_UPDATE) { mMotionController.updateMotionsMinimal(); diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 612068b202..0d89353dee 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -69,13 +69,13 @@ public: std::vector& getChildren(); void setCollapsed(bool collapsed) { mCollapsed = collapsed; } - bool getCollapsed() { return mCollapsed; } + bool getCollapsed() const { return mCollapsed; } - U64 getCountAverage() { return mCountAverage; } - U64 getCallAverage() { return mCallAverage; } + U64 getCountAverage() const { return mCountAverage; } + U64 getCallAverage() const { return mCallAverage; } - U64 getHistoricalCount(S32 history_index = 0); - U64 getHistoricalCalls(S32 history_index = 0); + U64 getHistoricalCount(S32 history_index = 0) const; + U64 getHistoricalCalls(S32 history_index = 0) const; static NamedTimer& getRootNamedTimer(); @@ -162,117 +162,6 @@ public: NamedTimer& mNamedTimer; }; - static DeclareTimer FTM_ARRANGE; - static DeclareTimer FTM_ATTACHMENT_UPDATE; - static DeclareTimer FTM_AUDIO_UPDATE; - static DeclareTimer FTM_AUTO_SELECT; - static DeclareTimer FTM_AVATAR_UPDATE; - static DeclareTimer FTM_CLEANUP; - static DeclareTimer FTM_CLIENT_COPY; - static DeclareTimer FTM_CREATE_OBJECT; - static DeclareTimer FTM_CULL; - static DeclareTimer FTM_CULL_REBOUND; - static DeclareTimer FTM_FILTER; - static DeclareTimer FTM_FLEXIBLE_UPDATE; - static DeclareTimer FTM_FRAME; - static DeclareTimer FTM_FRUSTUM_CULL; - static DeclareTimer FTM_GEN_FLEX; - static DeclareTimer FTM_GEN_TRIANGLES; - static DeclareTimer FTM_GEN_VOLUME; - static DeclareTimer FTM_GEO_SKY; - static DeclareTimer FTM_GEO_UPDATE; - static DeclareTimer FTM_HUD_EFFECTS; - static DeclareTimer FTM_HUD_UPDATE; - static DeclareTimer FTM_IDLE; - static DeclareTimer FTM_IDLE_CB; - static DeclareTimer FTM_IDLE_NETWORK; - static DeclareTimer FTM_IMAGE_CREATE; - static DeclareTimer FTM_IMAGE_MARK_DIRTY; - static DeclareTimer FTM_IMAGE_UPDATE; - static DeclareTimer FTM_INVENTORY; - static DeclareTimer FTM_JOINT_UPDATE; - static DeclareTimer FTM_KEYHANDLER; - static DeclareTimer FTM_LOAD_AVATAR; - static DeclareTimer FTM_LOD_UPDATE; - static DeclareTimer FTM_MESSAGES; - static DeclareTimer FTM_MOUSEHANDLER; - static DeclareTimer FTM_NETWORK; - static DeclareTimer FTM_OBJECTLIST_UPDATE; - static DeclareTimer FTM_OCCLUSION_READBACK; - static DeclareTimer FTM_OCTREE_BALANCE; - static DeclareTimer FTM_PICK; - static DeclareTimer FTM_PIPELINE; - static DeclareTimer FTM_POOLRENDER; - static DeclareTimer FTM_POOLS; - static DeclareTimer FTM_PROCESS_IMAGES; - static DeclareTimer FTM_PROCESS_MESSAGES; - static DeclareTimer FTM_PROCESS_OBJECTS; - static DeclareTimer FTM_PUMP; - static DeclareTimer FTM_REBUILD_GRASS_VB; - static DeclareTimer FTM_REBUILD_PARTICLE_VB; - static DeclareTimer FTM_REBUILD_TERRAIN_VB; - static DeclareTimer FTM_REBUILD_VBO; - static DeclareTimer FTM_REBUILD_VOLUME_VB; - static DeclareTimer FTM_REFRESH; - static DeclareTimer FTM_REGION_UPDATE; - static DeclareTimer FTM_RENDER; - static DeclareTimer FTM_RENDER_ALPHA; - static DeclareTimer FTM_RENDER_BLOOM; - static DeclareTimer FTM_RENDER_BLOOM_FBO; - static DeclareTimer FTM_RENDER_BUMP; - static DeclareTimer FTM_RENDER_CHARACTERS; - static DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE; - static DeclareTimer FTM_RENDER_FONTS; - static DeclareTimer FTM_RENDER_FULLBRIGHT; - static DeclareTimer FTM_RENDER_GEOMETRY; - static DeclareTimer FTM_RENDER_GLOW; - static DeclareTimer FTM_RENDER_GRASS; - static DeclareTimer FTM_RENDER_INVISIBLE; - static DeclareTimer FTM_RENDER_OCCLUSION; - static DeclareTimer FTM_RENDER_SHINY; - static DeclareTimer FTM_RENDER_SIMPLE; - static DeclareTimer FTM_RENDER_TERRAIN; - static DeclareTimer FTM_RENDER_TREES; - static DeclareTimer FTM_RENDER_UI; - static DeclareTimer FTM_RENDER_WATER; - static DeclareTimer FTM_RENDER_WL_SKY; - static DeclareTimer FTM_RESET_DRAWORDER; - static DeclareTimer FTM_SHADOW_ALPHA; - static DeclareTimer FTM_SHADOW_AVATAR; - static DeclareTimer FTM_SHADOW_RENDER; - static DeclareTimer FTM_SHADOW_SIMPLE; - static DeclareTimer FTM_SHADOW_TERRAIN; - static DeclareTimer FTM_SHADOW_TREE; - static DeclareTimer FTM_SIMULATE_PARTICLES; - static DeclareTimer FTM_SLEEP; - static DeclareTimer FTM_SORT; - static DeclareTimer FTM_STATESORT; - static DeclareTimer FTM_STATESORT_DRAWABLE; - static DeclareTimer FTM_STATESORT_POSTSORT; - static DeclareTimer FTM_SWAP; - static DeclareTimer FTM_TEMP1; - static DeclareTimer FTM_TEMP2; - static DeclareTimer FTM_TEMP3; - static DeclareTimer FTM_TEMP4; - static DeclareTimer FTM_TEMP5; - static DeclareTimer FTM_TEMP6; - static DeclareTimer FTM_TEMP7; - static DeclareTimer FTM_TEMP8; - static DeclareTimer FTM_UPDATE_ANIMATION; - static DeclareTimer FTM_UPDATE_AVATAR; - static DeclareTimer FTM_UPDATE_CLOUDS; - static DeclareTimer FTM_UPDATE_GRASS; - static DeclareTimer FTM_UPDATE_MOVE; - static DeclareTimer FTM_UPDATE_PARTICLES; - static DeclareTimer FTM_UPDATE_PRIMITIVES; - static DeclareTimer FTM_UPDATE_SKY; - static DeclareTimer FTM_UPDATE_TERRAIN; - static DeclareTimer FTM_UPDATE_TEXTURES; - static DeclareTimer FTM_UPDATE_TREE; - static DeclareTimer FTM_UPDATE_WATER; - static DeclareTimer FTM_UPDATE_WLPARAM; - static DeclareTimer FTM_VFILE_WAIT; - static DeclareTimer FTM_WORLD_UPDATE; public: enum RootTimerMarker { ROOT }; @@ -287,6 +176,7 @@ public: LLFastTimer(NamedTimer::FrameState& timer) : mFrameState(&timer) { +#if FAST_TIMER_ON NamedTimer::FrameState* frame_state = mFrameState; frame_state->mLastStartTime = get_cpu_clock_count(); mStartSelfTime = frame_state->mLastStartTime; @@ -298,6 +188,7 @@ public: mLastTimer = sCurTimer; sCurTimer = this; +#endif } ~LLFastTimer() @@ -332,6 +223,7 @@ public: static S32 getCurFrameIndex() { return sCurFrameIndex; } static void writeLog(std::ostream& os); + static const NamedTimer* getTimerByName(const std::string& name); public: static bool sPauseHistory; diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp index 8db3284c42..30e5d435ae 100644 --- a/indra/llcommon/llmetrics.cpp +++ b/indra/llcommon/llmetrics.cpp @@ -71,7 +71,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location, metrics["location"] = location; metrics["stats"] = stats; - llinfos << "LLMETRICS: " << LLSDNotationStreamer(metrics) << llendl; + llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl; } // Store this: diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 540a18b8a0..d3597b454c 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -32,6 +32,8 @@ #ifndef LLREFCOUNT_H #define LLREFCOUNT_H +#include + //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s // see llthread.h for LLThreadSafeRefCount @@ -40,10 +42,9 @@ class LLRefCount { protected: - LLRefCount(const LLRefCount&); // not implemented + LLRefCount(const LLRefCount& other); // no implementation private: - LLRefCount&operator=(const LLRefCount&); // not implemented - + LLRefCount& operator=(const LLRefCount&); // no implementation protected: virtual ~LLRefCount(); // use unref() diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index ba0f798dbb..9140ebb3f3 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -819,9 +819,15 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat) { std::ostringstream out; if (useXMLFormat) - out << LLSDXMLStreamer(llsd); + { + LLSDXMLStreamer xml_streamer(llsd); + out << xml_streamer; + } else - out << LLSDNotationStreamer(llsd); + { + LLSDNotationStreamer notation_streamer(llsd); + out << notation_streamer; + } out_string = out.str(); } int len = out_string.length(); diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index ec1718a8cb..d7da40d645 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -42,6 +42,9 @@ #include // for WideCharToMultiByte #endif +LLFastTimer::DeclareTimer STRING_LOCALIZATION("String Localization"); + + std::string ll_safe_string(const char* in) { if(in) return std::string(in); diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index f6bb0e0fe2..a15d6a9a14 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -38,6 +38,7 @@ #include #include #include "llsd.h" +#include "llfasttimer.h" #if LL_LINUX || LL_SOLARIS #include @@ -337,6 +338,9 @@ public: // Copies src into dst at a given offset. static void copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset); + static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } + + #ifdef _DEBUG static void testHarness(); #endif @@ -617,10 +621,13 @@ void LLStringUtilBase::getTokens (std::basic_string input, std::vector S32 LLStringUtilBase::format(std::basic_string& s, const format_map_t& substitutions) { + LLFastTimer ft(STRING_LOCALIZATION); S32 res = 0; std::basic_ostringstream output; @@ -695,6 +702,8 @@ S32 LLStringUtilBase::format(std::basic_string& s, const format_map_t& sub template S32 LLStringUtilBase::format(std::basic_string& s, const LLSD& substitutions) { + LLFastTimer ft(STRING_LOCALIZATION); + S32 res = 0; if (!substitutions.isMap()) diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index 894f0a7ed0..c03a331aff 100644 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h @@ -141,10 +141,20 @@ public: // Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect // returns TRUE if any part of rect is is inside this LLRect - BOOL rectInRect(const LLRectBase* rect) const + BOOL overlaps(const LLRectBase& rect) const { - return mLeft <= rect->mRight && rect->mLeft <= mRight && - mBottom <= rect->mTop && rect->mBottom <= mTop ; + return !(mLeft > rect.mRight + || mRight < rect.mLeft + || mBottom > rect.mTop + || mTop < rect.mBottom); + } + + BOOL contains(const LLRectBase& rect) const + { + return mLeft <= rect.mLeft + && mRight >= rect.mRight + && mBottom <= rect.mBottom + && mTop >= rect.mTop; } LLRectBase& set(Type left, Type top, Type right, Type bottom) @@ -223,26 +233,25 @@ public: return mLeft <= mRight && mBottom <= mTop; } - bool isNull() const + bool isEmpty() const { return mLeft == mRight || mBottom == mTop; } - bool notNull() const + bool notEmpty() const { - return !isNull(); + return !isEmpty(); } - LLRectBase& unionWith(const LLRectBase &other) + void unionWith(const LLRectBase &other) { mLeft = llmin(mLeft, other.mLeft); mRight = llmax(mRight, other.mRight); mBottom = llmin(mBottom, other.mBottom); mTop = llmax(mTop, other.mTop); - return *this; } - LLRectBase& intersectWith(const LLRectBase &other) + void intersectWith(const LLRectBase &other) { mLeft = llmax(mLeft, other.mLeft); mRight = llmin(mRight, other.mRight); @@ -256,7 +265,6 @@ public: { mBottom = mTop; } - return *this; } friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect) diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 3e3f0b37a7..5e9dfd81fa 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -444,11 +444,13 @@ void LLPumpIO::pump() pump(DEFAULT_POLL_TIMEOUT); } +static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); + //timeout is in microseconds void LLPumpIO::pump(const S32& poll_timeout) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - LLFastTimer t1(LLFastTimer::FTM_PUMP); + LLFastTimer t1(FTM_PUMP); //llinfos << "LLPumpIO::pump()" << llendl; // Run any pending runners. diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index 80ea6ce96b..8c9eb7ed42 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -531,6 +531,8 @@ void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S3 gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET); } +static LLFastTimer::DeclareTimer FTM_PROCESS_MESSAGES("Process Messages"); + // decode a given message BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender ) { @@ -714,7 +716,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender } { - LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES); + LLFastTimer t(FTM_PROCESS_MESSAGES); if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) { llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl; diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 62534969b7..0be6bedbee 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -33,6 +33,7 @@ #include "linden_common.h" #include "llfontfreetype.h" +#include "llfontgl.h" // Freetype stuff #include @@ -204,6 +205,19 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v mName = filename; mPointSize = point_size; + mStyle = LLFontGL::NORMAL; + if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD) + { + mStyle |= LLFontGL::BOLD; + mStyle &= ~LLFontGL::NORMAL; + } + + if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC) + { + mStyle |= LLFontGL::ITALIC; + mStyle &= ~LLFontGL::NORMAL; + } + return TRUE; } diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 177e13e27c..d76b23248d 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -89,12 +89,10 @@ static F32 llfont_round_y(F32 y) LLFontGL::LLFontGL() { - clearEmbeddedChars(); } LLFontGL::~LLFontGL() { - clearEmbeddedChars(); } void LLFontGL::reset() @@ -117,8 +115,10 @@ BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dp return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback); } +static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts"); + S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, - ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const { if(!sDisplayFont) //do not display texts { @@ -159,7 +159,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f); - LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS); + LLFastTimer t(FTM_RENDER_FONTS); gGL.color4fv( color.mV ); @@ -251,135 +251,69 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons { llwchar wch = wstr[i]; - // Handle embedded characters first, if they're enabled. - // Embedded characters are a hack for notecards - const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; - if (ext_data) + if (!mFontFreetype->hasGlyph(wch)) { - LLImageGL* ext_image = ext_data->mImage; - const LLWString& label = ext_data->mLabel; - - F32 ext_height = (F32)ext_image->getHeight() * sScaleY; - - F32 ext_width = (F32)ext_image->getWidth() * sScaleX; - F32 ext_advance = (EXT_X_BEARING * sScaleX) + ext_width; - - if (!label.empty()) - { - ext_advance += (EXT_X_BEARING + getFontExtChar()->getWidthF32( label.c_str() )) * sScaleX; - } - - if (start_x + scaled_max_pixels < cur_x + ext_advance) - { - // Not enough room for this character. - break; - } - - if (last_bound_texture != ext_image) - { - gGL.getTexUnit(0)->bind(ext_image); - last_bound_texture = ext_image; - } - - // snap origin to whole screen pixel - const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX)); - const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mFontFreetype->getAscenderHeight() - mFontFreetype->getLineHeight())); - - LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); - LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); - drawGlyph(screen_rect, uv_rect, LLColor4::white, style_to_add, shadow, drop_shadow_strength); - - if (!label.empty()) - { - gGL.pushMatrix(); - //glLoadIdentity(); - //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); - //glScalef(sScaleX, sScaleY, 1.f); - getFontExtChar()->render(label, 0, - /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), - /*llfloor*/(cur_y / sScaleY), - color, - halign, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, - TRUE ); - gGL.popMatrix(); - } - - gGL.color4fv(color.mV); + addChar(wch); + } - chars_drawn++; - cur_x += ext_advance; - if (((i + 1) < length) && wstr[i+1]) - { - cur_x += EXT_KERNING * sScaleX; - } - cur_render_x = cur_x; + const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch); + if (!fgi) + { + llerrs << "Missing Glyph Info" << llendl; + break; } - else + // Per-glyph bitmap texture. + LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum); + if (last_bound_texture != image_gl) { - if (!mFontFreetype->hasGlyph(wch)) - { - addChar(wch); - } - - const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch); - if (!fgi) - { - llerrs << "Missing Glyph Info" << llendl; - break; - } - // Per-glyph bitmap texture. - LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum); - if (last_bound_texture != image_gl) - { - gGL.getTexUnit(0)->bind(image_gl); - last_bound_texture = image_gl; - } + gGL.getTexUnit(0)->bind(image_gl); + last_bound_texture = image_gl; + } - if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) - { - // Not enough room for this character. - break; - } + if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) + { + // Not enough room for this character. + break; + } - // Draw the text at the appropriate location - //Specify vertices and texture coordinates - LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width, - (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height, - (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, - (fgi->mYBitmapOffset - PAD_UVY) * inv_height); - // snap glyph origin to whole screen pixel - LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), - llround(cur_render_y + (F32)fgi->mYBearing), - llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, - llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); - - drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength); + // Draw the text at the appropriate location + //Specify vertices and texture coordinates + LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width, + (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height, + (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, + (fgi->mYBitmapOffset - PAD_UVY) * inv_height); + // snap glyph origin to whole screen pixel + LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), + llround(cur_render_y + (F32)fgi->mYBearing), + llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, + llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); + + drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength); - chars_drawn++; - cur_x += fgi->mXAdvance; - cur_y += fgi->mYAdvance; + chars_drawn++; + cur_x += fgi->mXAdvance; + cur_y += fgi->mYAdvance; - llwchar next_char = wstr[i+1]; - if (next_char && (next_char < LAST_CHARACTER)) + llwchar next_char = wstr[i+1]; + if (next_char && (next_char < LAST_CHARACTER)) + { + // Kern this puppy. + if (!mFontFreetype->hasGlyph(next_char)) { - // Kern this puppy. - if (!mFontFreetype->hasGlyph(next_char)) - { - addChar(next_char); - } - cur_x += mFontFreetype->getXKerning(wch, next_char); + addChar(next_char); } + cur_x += mFontFreetype->getXKerning(wch, next_char); + } - // Round after kerning. - // Must do this to cur_x, not just to cur_render_x, otherwise you - // will squish sub-pixel kerned characters too close together. - // For example, "CCCCC" looks bad. - cur_x = (F32)llfloor(cur_x + 0.5f); - //cur_y = (F32)llfloor(cur_y + 0.5f); + // Round after kerning. + // Must do this to cur_x, not just to cur_render_x, otherwise you + // will squish sub-pixel kerned characters too close together. + // For example, "CCCCC" looks bad. + cur_x = (F32)llfloor(cur_x + 0.5f); + //cur_y = (F32)llfloor(cur_y + 0.5f); - cur_render_x = cur_x; - cur_render_y = cur_y; - } + cur_render_x = cur_x; + cur_render_y = cur_y; } if (right_x) @@ -427,12 +361,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const { - return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE); + return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); } S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const { - return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); + return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses); } S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const @@ -478,9 +412,9 @@ S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_ch return getWidth(wtext.c_str(), begin_offset, max_chars); } -S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const +S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars) const { - F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded); + F32 width = getWidthF32(wchars, begin_offset, max_chars); return llround(width); } @@ -501,7 +435,7 @@ F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max return getWidthF32(wtext.c_str(), begin_offset, max_chars); } -F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const +F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars) const { const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; @@ -509,34 +443,21 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars const S32 max_index = begin_offset + max_chars; for (S32 i = begin_offset; i < max_index; i++) { - const llwchar wch = wchars[i]; + llwchar wch = wchars[i]; if (wch == 0) { break; // done } - const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; - if (ext_data) - { - // Handle crappy embedded hack - cur_x += getEmbeddedCharAdvance(ext_data); - if( ((i+1) < max_chars) && (i+1 < max_index)) - { - cur_x += EXT_KERNING * sScaleX; - } - } - else - { - cur_x += mFontFreetype->getXAdvance(wch); - llwchar next_char = wchars[i+1]; + cur_x += mFontFreetype->getXAdvance(wch); + llwchar next_char = wchars[i+1]; - if (((i + 1) < max_chars) - && next_char - && (next_char < LAST_CHARACTER)) - { - // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, next_char); - } + if (((i + 1) < begin_offset + max_chars) + && next_char + && (next_char < LAST_CHARACTER)) + { + // Kern this puppy. + cur_x += mFontFreetype->getXKerning(wch, next_char); } // Round after kerning. cur_x = (F32)llfloor(cur_x + 0.5f); @@ -546,7 +467,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars } // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels -S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, BOOL end_on_word_boundary, BOOL use_embedded, F32* drawn_pixels) const +S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, BOOL end_on_word_boundary) const { if (!wchars || !wchars[0] || max_chars == 0) { @@ -576,83 +497,51 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch break; } - const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; - if (ext_data) + if (in_word) { - if (in_word) - { - in_word = FALSE; - } - else - { - start_of_last_word = i; - } - cur_x += getEmbeddedCharAdvance(ext_data); - - if (scaled_max_pixels < cur_x) - { - clip = TRUE; - break; - } - - if (((i+1) < max_chars) && wchars[i+1]) + if (iswspace(wch)) { - cur_x += EXT_KERNING * sScaleX; - } - - if( scaled_max_pixels < cur_x ) - { - clip = TRUE; - break; + if(wch !=(0x00A0)) + { + in_word = FALSE; + } } - } - else - { - if (in_word) + if (iswindividual(wch)) { - if (iswspace(wch)) + if (iswpunct(wchars[i+1])) { - if(wch !=(0x00A0)) - { - in_word = FALSE; - } + in_word=TRUE; } - if (iswindividual(wch)) + else { - if (iswpunct(wchars[i+1])) - { - in_word=TRUE; - } - else - { - in_word=FALSE; - start_of_last_word = i; - } + in_word=FALSE; + start_of_last_word = i; } } - else + } + else + { + start_of_last_word = i; + if (!iswspace(wch)||!iswindividual(wch)) { - start_of_last_word = i; - if (!iswspace(wch)||!iswindividual(wch)) - { - in_word = TRUE; - } + in_word = TRUE; } + } - cur_x += mFontFreetype->getXAdvance(wch); - - if (scaled_max_pixels < cur_x) - { - clip = TRUE; - break; - } + cur_x += mFontFreetype->getXAdvance(wch); + + if (scaled_max_pixels < cur_x) + { + clip = TRUE; + break; + } - if (((i+1) < max_chars) && wchars[i+1]) - { - // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]); - } + if (((i+1) < max_chars) && wchars[i+1]) + { + // Kern this puppy. + cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]); } + // Round after kerning. cur_x = (F32)llfloor(cur_x + 0.5f); drawn_x = cur_x; @@ -662,10 +551,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch { i = start_of_last_word; } - if (drawn_pixels) - { - *drawn_pixels = drawn_x; - } return i; } @@ -686,8 +571,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ { llwchar wch = wchars[i]; - const embedded_data_t* ext_data = getEmbeddedCharData(wch); - F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : mFontFreetype->getXAdvance(wch); + F32 char_width = mFontFreetype->getXAdvance(wch); if( scaled_max_pixels < (total_width + char_width) ) { @@ -705,7 +589,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ if ( i > 0 ) { // kerning - total_width += ext_data ? (EXT_KERNING * sScaleX) : mFontFreetype->getXKerning(wchars[i-1], wch); + total_width += mFontFreetype->getXKerning(wchars[i-1], wch); } // Round after kerning. @@ -715,7 +599,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ return start_pos - drawable_chars; } -S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const +S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round) const { if (!wchars || !wchars[0] || max_chars == 0) { @@ -723,7 +607,6 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t } F32 cur_x = 0; - S32 pos = 0; target_x *= sScaleX; @@ -732,113 +615,50 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t F32 scaled_max_pixels = max_pixels * sScaleX; - for (S32 i = begin_offset; (i < max_index); i++) + S32 pos; + for (pos = begin_offset; pos < max_index; pos++) { - llwchar wch = wchars[i]; + llwchar wch = wchars[pos]; if (!wch) { break; // done } - const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; - if (ext_data) - { - F32 ext_advance = getEmbeddedCharAdvance(ext_data); - - if (round) - { - // Note: if the mouse is on the left half of the character, the pick is to the character's left - // If it's on the right half, the pick is to the right. - if (target_x < cur_x + ext_advance/2) - { - break; - } - } - else - { - if (target_x < cur_x + ext_advance) - { - break; - } - } + F32 char_width = mFontFreetype->getXAdvance(wch); - if (scaled_max_pixels < cur_x + ext_advance) + if (round) + { + // Note: if the mouse is on the left half of the character, the pick is to the character's left + // If it's on the right half, the pick is to the right. + if (target_x < cur_x + char_width*0.5f) { break; } - - pos++; - cur_x += ext_advance; - - if (((i + 1) < max_index) - && (wchars[(i + 1)])) - { - cur_x += EXT_KERNING * sScaleX; - } - // Round after kerning. - cur_x = (F32)llfloor(cur_x + 0.5f); } - else + else if (target_x < cur_x + char_width) { - F32 char_width = mFontFreetype->getXAdvance(wch); - - if (round) - { - // Note: if the mouse is on the left half of the character, the pick is to the character's left - // If it's on the right half, the pick is to the right. - if (target_x < cur_x + char_width*0.5f) - { - break; - } - } - else if (target_x < cur_x + char_width) - { - break; - } - - if (scaled_max_pixels < cur_x + char_width) - { - break; - } - - pos++; - cur_x += char_width; - - if (((i + 1) < max_index) - && (wchars[(i + 1)])) - { - llwchar next_char = wchars[i + 1]; - // Kern this puppy. - cur_x += mFontFreetype->getXKerning(wch, next_char); - } - - // Round after kerning. - cur_x = (F32)llfloor(cur_x + 0.5f); + break; } - } - return pos; -} + if (scaled_max_pixels < cur_x + char_width) + { + break; + } -void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label ) const -{ - LLWString wlabel = utf8str_to_wstring(label); - addEmbeddedChar(wc, image, wlabel); -} + cur_x += char_width; -void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& wlabel ) const -{ - embedded_data_t* ext_data = new embedded_data_t(image->getGLTexture(), wlabel); - mEmbeddedChars[wc] = ext_data; -} + if (((pos + 1) < max_index) + && (wchars[(pos + 1)])) + { + llwchar next_char = wchars[pos + 1]; + // Kern this puppy. + cur_x += mFontFreetype->getXKerning(wch, next_char); + } -void LLFontGL::removeEmbeddedChar(llwchar wc) const -{ - embedded_map_t::iterator iter = mEmbeddedChars.find(wc); - if (iter != mEmbeddedChars.end()) - { - delete iter->second; - mEmbeddedChars.erase(wc); + // Round after kerning. + cur_x = (F32)llfloor(cur_x + 0.5f); } + + return llmin(max_chars, pos - begin_offset); } BOOL LLFontGL::addChar(llwchar wch) const @@ -1154,38 +974,6 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source) return *this; } -const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(llwchar wch) const -{ - // Handle crappy embedded hack - embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch); - if (iter != mEmbeddedChars.end()) - { - return iter->second; - } - return NULL; -} - -F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const -{ - const LLWString& label = ext_data->mLabel; - LLImageGL* ext_image = ext_data->mImage; - - F32 ext_width = (F32)ext_image->getWidth(); - if( !label.empty() ) - { - ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX; - } - - return (EXT_X_BEARING * sScaleX) + ext_width; -} - -void LLFontGL::clearEmbeddedChars() -{ - for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); - mEmbeddedChars.clear(); -} - - void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const { gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 42ed7a381f..af8e0909af 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -97,7 +97,7 @@ public: BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback); S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign = LEFT, VAlign valign = BASELINE, U8 style = NORMAL, - ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, BOOL use_embedded = FALSE, BOOL use_ellipses = FALSE) const; + ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, BOOL use_ellipses = FALSE) const; S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; // renderUTF8 does a conversion, so is slower! @@ -113,28 +113,24 @@ public: S32 getWidth(const std::string& utf8text) const; S32 getWidth(const llwchar* wchars) const; S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars ) const; - S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE) const; + S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars) const; F32 getWidthF32(const std::string& utf8text) const; F32 getWidthF32(const llwchar* wchars) const; F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const; - F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE ) const; + F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars) const; // The following are called often, frequently with large buffers, so do not use a string interface // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels - S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, BOOL end_on_word_boundary = FALSE, BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const; + S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, BOOL end_on_word_boundary = FALSE) const; // Returns the index of the first complete characters from text that can be drawn in max_pixels // given that the character at start_pos should be the last character (or as close to last as possible). S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) - S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const; - - void addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label) const; - void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; - void removeEmbeddedChar( llwchar wc ) const; + S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE) const; BOOL addChar(const llwchar wch) const; @@ -199,19 +195,6 @@ private: LLFontDescriptor mFontDescriptor; LLPointer mFontFreetype; - struct embedded_data_t - { - embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} - LLPointer mImage; - LLWString mLabel; - }; - - typedef std::map embedded_map_t; - mutable embedded_map_t mEmbeddedChars; - - const embedded_data_t* getEmbeddedCharData(llwchar wch) const; - F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; - void clearEmbeddedChars(); void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 553e7b8f9d..99f364a589 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -477,7 +477,6 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) if (result) { - result->mFontFreetype->setStyle(match_desc->getStyle()); result->mFontDescriptor = desc; } else diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c3d1d9e894..3669b49e51 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -516,7 +516,6 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { -// LLFastTimer t1(LLFastTimer::FTM_TEMP1); llpushcallstacks ; bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) @@ -524,12 +523,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) is_compressed = true; } -// LLFastTimer t2(LLFastTimer::FTM_TEMP2); gGL.getTexUnit(0)->bind(this); if (mUseMipMaps) { -// LLFastTimer t2(LLFastTimer::FTM_TEMP3); if (data_hasmips) { // NOTE: data_in points to largest image; smaller images @@ -546,14 +543,13 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } if (is_compressed) { -// LLFastTimer t2(LLFastTimer::FTM_TEMP4); S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); stop_glerror(); } else { -// LLFastTimer t2(LLFastTimer::FTM_TEMP4); +// LLFastTimer t2(FTM_TEMP4); if(mFormatSwapBytes) { @@ -586,7 +582,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE); stop_glerror(); { -// LLFastTimer t2(LLFastTimer::FTM_TEMP4); +// LLFastTimer t2(FTM_TEMP4); if(mFormatSwapBytes) { @@ -646,7 +642,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } llassert(w > 0 && h > 0 && cur_mip_data); { -// LLFastTimer t1(LLFastTimer::FTM_TEMP4); +// LLFastTimer t1(FTM_TEMP4); if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); @@ -988,7 +984,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ LLImageGL::generateTextures(1, &mTexName); stop_glerror(); { -// LLFastTimer t1(LLFastTimer::FTM_TEMP6); llverify(gGL.getTexUnit(0)->bind(this)); glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level); diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index c566282bef..b13b250c75 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -419,8 +419,16 @@ BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); } - } +// if (pointInView(x, y)) +// { +// } + } + // send the mouse down signal + LLUICtrl::handleRightMouseDown(x,y,mask); + // *TODO: Return result of LLUICtrl call above? Should defer to base class + // but this might change the mouse handling of existing buttons in a bad way + // if they are not mouse opaque. return TRUE; } @@ -432,15 +440,20 @@ BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) // Always release the mouse gFocusMgr.setMouseCapture( NULL ); - if (pointInView(x, y)) - { - mRightClickSignal(this, x,y,mask); - } +// if (pointInView(x, y)) +// { +// mRightMouseUpSignal(this, x,y,mask); +// } } else { childrenHandleRightMouseUp(x, y, mask); } + // send the mouse up signal + LLUICtrl::handleRightMouseUp(x,y,mask); + // *TODO: Return result of LLUICtrl call above? Should defer to base class + // but this might change the mouse handling of existing buttons in a bad way. + // if they are not mouse opaque. return TRUE; } @@ -788,7 +801,7 @@ void LLButton::draw() LLFontGL::NORMAL, mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, S32_MAX, text_width, - NULL, FALSE, mUseEllipses); + NULL, mUseEllipses); } LLUICtrl::draw(); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index b3c3a2e698..ac56d15d1b 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -191,6 +191,7 @@ void LLComboBox::clear() mButton->setLabelSelected(LLStringUtil::null); mButton->setLabelUnselected(LLStringUtil::null); mList->deselectAllItems(); + mLastSelectedIndex = -1; } void LLComboBox::onCommit() @@ -296,6 +297,7 @@ BOOL LLComboBox::setSimple(const LLStringExplicit& name) if (found) { setLabel(name); + mLastSelectedIndex = mList->getFirstSelectedIndex(); } return found; @@ -312,6 +314,7 @@ void LLComboBox::setValue(const LLSD& value) { setLabel( mList->getSelectedItemLabel() ); } + mLastSelectedIndex = mList->getFirstSelectedIndex(); } } @@ -359,6 +362,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name) if (mList->selectItemByLabel(name, FALSE)) { mTextEntry->setTentative(FALSE); + mLastSelectedIndex = mList->getFirstSelectedIndex(); } else { @@ -384,6 +388,7 @@ BOOL LLComboBox::remove(const std::string& name) { mList->deleteSingleItem(mList->getItemIndex(item)); } + mLastSelectedIndex = mList->getFirstSelectedIndex(); } return found; @@ -436,6 +441,7 @@ BOOL LLComboBox::setCurrentByIndex( S32 index ) if (found) { setLabel(mList->getSelectedItemLabel()); + mLastSelectedIndex = index; } return found; } @@ -607,9 +613,6 @@ void LLComboBox::showList() mList->setVisible(TRUE); setUseBoundingRect(TRUE); - - mList->sortItems(); - mLastSelectedIndex = mList->getFirstSelectedIndex(); } void LLComboBox::hideList() @@ -819,11 +822,13 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) if (mList->selectItemByLabel(line_editor->getText(), FALSE)) { line_editor->setTentative(FALSE); + mLastSelectedIndex = mList->getFirstSelectedIndex(); } else { line_editor->setTentative(mTextEntryTentative); mList->deselectAllItems(); + mLastSelectedIndex = -1; } return; } @@ -890,6 +895,7 @@ void LLComboBox::updateSelection() if (mList->selectItemByLabel(full_string, FALSE)) { mTextEntry->setTentative(FALSE); + mLastSelectedIndex = mList->getFirstSelectedIndex(); } else if (mList->selectItemByPrefix(left_wstring, FALSE)) { @@ -900,6 +906,7 @@ void LLComboBox::updateSelection() mTextEntry->endSelection(); mTextEntry->setTentative(FALSE); mHasAutocompletedText = TRUE; + mLastSelectedIndex = mList->getFirstSelectedIndex(); } else // no matching items found { @@ -907,6 +914,7 @@ void LLComboBox::updateSelection() mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion mTextEntry->setTentative(mTextEntryTentative); mHasAutocompletedText = FALSE; + mLastSelectedIndex = -1; } } @@ -994,6 +1002,7 @@ BOOL LLComboBox::setCurrentByID(const LLUUID& id) if (found) { setLabel(mList->getSelectedItemLabel()); + mLastSelectedIndex = mList->getFirstSelectedIndex(); } return found; diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index 7e7d6ac111..51ef80f4b9 100644 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -132,35 +132,31 @@ void LLContainerView::draw() void LLContainerView::reshape(S32 width, S32 height, BOOL called_from_parent) { - S32 desired_width = width; - S32 desired_height = height; + LLRect scroller_rect; + scroller_rect.setOriginAndSize(0, 0, width, height); if (mScrollContainer) { - BOOL dum_bool; - mScrollContainer->calcVisibleSize(&desired_width, &desired_height, &dum_bool, &dum_bool); + scroller_rect = mScrollContainer->getContentWindowRect(); } else { // if we're uncontained - make height as small as possible - desired_height = 0; + scroller_rect.mTop = 0; } - arrange(desired_width, desired_height, called_from_parent); + arrange(scroller_rect.getWidth(), scroller_rect.getHeight(), called_from_parent); // sometimes, after layout, our container will change size (scrollbars popping in and out) // if so, attempt another layout if (mScrollContainer) { - S32 new_container_width; - S32 new_container_height; - BOOL dum_bool; - mScrollContainer->calcVisibleSize(&new_container_width, &new_container_height, &dum_bool, &dum_bool); + LLRect new_container_rect = mScrollContainer->getContentWindowRect(); - if ((new_container_width != desired_width) || - (new_container_height != desired_height)) // the container size has changed, attempt to arrange again + if ((new_container_rect.getWidth() != scroller_rect.getWidth()) || + (new_container_rect.getHeight() != scroller_rect.getHeight())) // the container size has changed, attempt to arrange again { - arrange(new_container_width, new_container_height, called_from_parent); + arrange(new_container_rect.getWidth(), new_container_rect.getHeight(), called_from_parent); } } } diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d420d1141e..2679143bbc 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -711,10 +711,7 @@ void LLFloater::releaseFocus() gFocusMgr.setTopCtrl(NULL); } - if( gFocusMgr.childHasKeyboardFocus( this ) ) - { - gFocusMgr.setKeyboardFocus(NULL); - } + setFocus(FALSE); if( gFocusMgr.childHasMouseCapture( this ) ) { @@ -1074,7 +1071,7 @@ void LLFloater::setFocus( BOOL b ) } LLUICtrl* last_focus = gFocusMgr.getLastFocusForGroup(this); // a descendent already has focus - BOOL child_had_focus = gFocusMgr.childHasKeyboardFocus(this); + BOOL child_had_focus = hasFocus(); // give focus to first valid descendent LLPanel::setFocus(b); @@ -1948,7 +1945,7 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF if (sibling && sibling != neighbor && sibling->getVisible() && - expanded_base_rect.rectInRect(&sibling->getRect())) + expanded_base_rect.overlaps(sibling->getRect())) { base_rect.unionWith(sibling->getRect()); } @@ -2593,6 +2590,8 @@ void LLFloater::initFromParams(const LLFloater::Params& p) initCommitCallback(p.close_callback, mCloseSignal); } +LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build"); + void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { Params params(LLUICtrlFactory::getDefaultParams()); @@ -2626,7 +2625,12 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o LLFloater::setFloaterHost(last_host); } - BOOL result = postBuild(); + BOOL result; + { + LLFastTimer ft(POST_BUILD); + + result = postBuild(); + } if (!result) { diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 30796a5ab9..db1611abb5 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -231,11 +231,13 @@ LLColor3 LLKeywords::readColor( const std::string& s ) return LLColor3( r, g, b ); } +LLFastTimer::DeclareTimer FTM_SYNTAX_COLORING("Syntax Coloring"); + // Walk through a string, applying the rules specified by the keyword token list and // create a list of color segments. -void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, const LLColor4 &defaultColor) +void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, const LLColor4 &defaultColor, LLTextEditor& editor) { - std::for_each(seg_list->begin(), seg_list->end(), DeletePointer()); + LLFastTimer ft(FTM_SYNTAX_COLORING); seg_list->clear(); if( wtext.empty() ) @@ -245,7 +247,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS S32 text_len = wtext.size(); - seg_list->push_back( new LLTextSegment( LLColor3(defaultColor), 0, text_len ) ); + seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) ); const llwchar* base = wtext.c_str(); const llwchar* cur = base; @@ -296,9 +298,9 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS } S32 seg_end = cur - base; - LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); + LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); line_done = TRUE; // to break out of second loop. break; } @@ -405,9 +407,9 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS } - LLTextSegment* text_segment = new LLTextSegment( cur_delimiter->getColor(), seg_start, seg_end ); + LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); text_segment->setToken( cur_delimiter ); - insertSegment( seg_list, text_segment, text_len, defaultColor); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); // Note: we don't increment cur, since the end of one delimited seg may be immediately // followed by the start of another one. @@ -438,9 +440,9 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS // llinfos << "Seg: [" << word.c_str() << "]" << llendl; - LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); + LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); } cur += seg_len; continue; @@ -455,25 +457,24 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS } } -void LLKeywords::insertSegment(std::vector* seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor ) +void LLKeywords::insertSegment(std::vector* seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) { - LLTextSegment* last = seg_list->back(); + LLTextSegmentPtr last = seg_list->back(); S32 new_seg_end = new_segment->getEnd(); if( new_segment->getStart() == last->getStart() ) { - *last = *new_segment; - delete new_segment; + seg_list->pop_back(); } else { last->setEnd( new_segment->getStart() ); - seg_list->push_back( new_segment ); } + seg_list->push_back( new_segment ); if( new_seg_end < text_len ) { - seg_list->push_back( new LLTextSegment( defaultColor, new_seg_end, text_len ) ); + seg_list->push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) ); } } diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 38f5e993c2..53377869ca 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -39,9 +39,10 @@ #include #include #include +#include "llpointer.h" class LLTextSegment; - +typedef LLPointer LLTextSegmentPtr; class LLKeywordToken { @@ -84,7 +85,7 @@ public: BOOL loadFromFile(const std::string& filename); BOOL isLoaded() const { return mLoaded; } - void findSegments(std::vector *seg_list, const LLWString& text, const LLColor4 &defaultColor ); + void findSegments(std::vector *seg_list, const LLWString& text, const LLColor4 &defaultColor, class LLTextEditor& editor ); // Add the token as described void addToken(LLKeywordToken::TOKEN_TYPE type, @@ -103,7 +104,7 @@ public: private: LLColor3 readColor(const std::string& s); - void insertSegment(std::vector *seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor); + void insertSegment(std::vector *seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor); BOOL mLoaded; word_token_map_t mWordTokenMap; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 702d8e4a39..f98edec1f3 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -167,7 +167,7 @@ void LLLayoutStack::draw() LLLocalClipRect clip(clip_rect, mClip); // only force drawing invisible children if visible amount is non-zero - drawChild(panelp, 0, 0, !clip_rect.isNull()); + drawChild(panelp, 0, 0, !clip_rect.isEmpty()); } } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 42a1b9ad9c..6926415c6d 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -494,19 +494,19 @@ BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask) BOOL doSelectAll = TRUE; // Select the word we're on - if( LLTextEditor::isPartOfWord( wtext[mCursorPos] ) ) + if( LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) ) { S32 old_selection_start = mLastSelectionStart; S32 old_selection_end = mLastSelectionEnd; // Select word the cursor is over - while ((mCursorPos > 0) && LLTextEditor::isPartOfWord( wtext[mCursorPos-1] )) + while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[mCursorPos-1] )) { // Find the start of the word mCursorPos--; } startSelection(); - while ((mCursorPos < (S32)wtext.length()) && LLTextEditor::isPartOfWord( wtext[mCursorPos] ) ) + while ((mCursorPos < (S32)wtext.length()) && LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) ) { // Find the end of the word mCursorPos++; } @@ -840,7 +840,7 @@ S32 LLLineEditor::prevWordPos(S32 cursorPos) const { cursorPos--; } - while( (cursorPos > 0) && LLTextEditor::isPartOfWord( wtext[cursorPos-1] ) ) + while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) ) { cursorPos--; } @@ -850,7 +850,7 @@ S32 LLLineEditor::prevWordPos(S32 cursorPos) const S32 LLLineEditor::nextWordPos(S32 cursorPos) const { const LLWString& wtext = mText.getWString(); - while( (cursorPos < getLength()) && LLTextEditor::isPartOfWord( wtext[cursorPos] ) ) + while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) ) { cursorPos++; } @@ -1732,11 +1732,11 @@ void LLLineEditor::draw() #endif // If we're editing... - if( gFocusMgr.getKeyboardFocus() == this) + if( hasFocus()) { //mBorder->setVisible(TRUE); // ok, programmer art just this once. // (Flash the cursor every half second) - if (gShowTextEditCursor && !mReadOnly) + if (!mReadOnly && gFocusMgr.getAppHasFocus()) { F32 elapsed = mKeystrokeTimer.getElapsedTimeF32(); if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) ) diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 5be53e6afc..b6c3ffc61c 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -184,6 +184,13 @@ LLMenuItemGL::LLMenuItemGL(const LLMenuItemGL::Params& p) << LL_ENDL; } +//virtual +void LLMenuItemGL::setValue(const LLSD& value) +{ + setLabel(value.asString()); +} + +//virtual BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask) { if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) @@ -201,6 +208,26 @@ BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask) return TRUE; } +//virtual +BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return LLUICtrl::handleRightMouseDown(x,y,mask); +} + +//virtual +BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + // If this event came from a right-click context menu spawn, + // process as a left-click to allow menu items to be hit + if (LLMenuHolderGL::sContextMenuSpawnPos.mX != S32_MAX + || LLMenuHolderGL::sContextMenuSpawnPos.mY != S32_MAX) + { + BOOL handled = handleMouseUp(x, y, mask); + return handled; + } + return LLUICtrl::handleRightMouseUp(x,y,mask); +} + // This function checks to see if the accelerator key is already in use; // if not, it will be added to the list BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp) @@ -306,6 +333,17 @@ U32 LLMenuItemGL::getNominalHeight( void ) const return llround(mFont->getLineHeight()) + MENU_ITEM_PADDING; } +//virtual +void LLMenuItemGL::setBriefItem(BOOL brief) +{ + mBriefItem = brief; +} + +//virtual +BOOL LLMenuItemGL::isBriefItem() const +{ + return mBriefItem; +} // Get the parent menu for this item LLMenuGL* LLMenuItemGL::getMenu() const @@ -800,15 +838,8 @@ BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask ) return FALSE; } -BOOL LLMenuItemCallGL::handleRightMouseUp(S32 x, S32 y, MASK mask) -{ - if (pointInView(x, y)) - { - mRightClickSignal(this,x,y, mask); - } - - return TRUE; -} +// handleRightMouseUp moved into base class LLMenuItemGL so clicks are +// handled for all menu item types ///============================================================================ /// Class LLMenuItemCheckGL @@ -898,24 +929,38 @@ LLMenuItemBranchGL::~LLMenuItemBranchGL() } // virtual -LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const +LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse) const { LLMenuGL* branch = getBranch(); - if (!branch) - return LLView::getChildView(name, recurse, create_if_missing); - - // richard: this is redundant with parent, remove - if (branch->getName() == name) + if (branch) { - return branch; + if (branch->getName() == name) + { + return branch; + } + + // Always recurse on branches + return branch->getChildView(name, recurse); } - // Always recurse on branches - LLView* child = branch->getChildView(name, recurse, FALSE); - if (!child) + + return LLView::getChildView(name, recurse); +} + +LLView* LLMenuItemBranchGL::findChildView(const std::string& name, BOOL recurse) const +{ + LLMenuGL* branch = getBranch(); + if (branch) { - child = LLView::getChildView(name, recurse, create_if_missing); + if (branch->getName() == name) + { + return branch; + } + + // Always recurse on branches + return branch->findChildView(name, recurse); } - return child; + + return LLView::findChildView(name, recurse); } // virtual @@ -1123,6 +1168,18 @@ BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) return LLMenuItemGL::handleKeyHere(key, mask); } +//virtual +BOOL LLMenuItemBranchGL::isActive() const +{ + return isOpen() && getBranch() && getBranch()->getHighlightedItem(); +} + +//virtual +BOOL LLMenuItemBranchGL::isOpen() const +{ + return getBranch() && getBranch()->isOpen(); +} + void LLMenuItemBranchGL::openMenu() { LLMenuGL* branch = getBranch(); @@ -1298,6 +1355,9 @@ void LLMenuItemBranchDownGL::setHighlight( BOOL highlight ) { if (highlight == getHighlight()) return; + LLMenuGL* branch = getBranch(); + if (!branch) return; + //NOTE: Purposely calling all the way to the base to bypass auto-open. LLMenuItemGL::setHighlight(highlight); if( !highlight) @@ -2803,9 +2863,9 @@ void LLMenuGL::setVisible(BOOL visible) } } -LLMenuGL* LLMenuGL::getChildMenuByName(const std::string& name, BOOL recurse) const +LLMenuGL* LLMenuGL::findChildMenuByName(const std::string& name, BOOL recurse) const { - LLView* view = getChildView(name, recurse, FALSE); + LLView* view = findChildView(name, recurse); if (view) { LLMenuItemBranchGL* branch = dynamic_cast(view); @@ -2844,9 +2904,19 @@ void hide_top_view( LLView* view ) } +// x and y are the desired location for the popup, NOT necessarily the +// mouse location // static void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) { + // Save click point for detecting cursor moves before mouse-up. + // Must be in local coords to compare with mouseUp events. + // If the mouse doesn't move, the menu will stay open ala the Mac. + // See also LLContextMenu::show() + S32 mouse_x, mouse_y; + LLUI::getCursorPositionLocal(menu->getParent(), &mouse_x, &mouse_y); + LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y); + const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); const S32 HPAD = 2; @@ -2857,9 +2927,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent()); rect.setLeftTopAndSize( left, top, rect.getWidth(), rect.getHeight() ); - - - //rect.setLeftTopAndSize(x + HPAD, y, rect.getWidth(), rect.getHeight()); menu->setRect( rect ); // Resetting scrolling position @@ -2871,18 +2938,16 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) menu->arrangeAndClear(); // Fix menu rect if needed. rect = menu->getRect(); + // Adjust context menu to fit onscreen S32 bottom; left = rect.mLeft; bottom = rect.mBottom; - //menu->getParent()->localPointToScreen( rect.mLeft, rect.mBottom, - // &left, &bottom ); S32 delta_x = 0; S32 delta_y = 0; if( bottom < menu_region_rect.mBottom ) { // At this point, we need to move the context menu to the // other side of the mouse. - //delta_y = menu_region_rect.mBottom - bottom; delta_y = (rect.getHeight() + 2 * HPAD); } @@ -2890,7 +2955,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) { // At this point, we need to move the context menu to the // other side of the mouse. - //delta_x = (window_width - rect.getWidth()) - x; delta_x = -(rect.getWidth() + 2 * HPAD); } menu->translate( delta_x, delta_y ); @@ -3633,6 +3697,7 @@ void LLContextMenu::show(S32 x, S32 y) // Save click point for detecting cursor moves before mouse-up. // Must be in local coords to compare with mouseUp events. // If the mouse doesn't move, the menu will stay open ala the Mac. + // See also LLMenuGL::showPopup() LLMenuHolderGL::sContextMenuSpawnPos.set(x,y); arrangeAndClear(); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index d39a02da28..2e7f61c2dd 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -105,10 +105,15 @@ protected: LLMenuItemGL(const Params&); friend class LLUICtrlFactory; public: - virtual void setValue(const LLSD& value) { setLabel(value.asString()); } + // LLView overrides /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); + + // LLUICtrl overrides + /*virtual*/ void setValue(const LLSD& value); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleAcceleratorKey(KEY key, MASK mask); LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); } @@ -124,8 +129,8 @@ public: virtual U32 getNominalHeight( void ) const; // Marks item as not needing space for check marks or accelerator keys - virtual void setBriefItem(BOOL brief) { mBriefItem = brief; } - virtual BOOL isBriefItem() const { return mBriefItem; } + virtual void setBriefItem(BOOL brief); + virtual BOOL isBriefItem() const; virtual BOOL addToAcceleratorList(std::list *listp); void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; } @@ -283,7 +288,6 @@ public: virtual BOOL handleAcceleratorKey(KEY key, MASK mask); virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); //virtual void draw(); @@ -427,7 +431,7 @@ public: virtual BOOL handleAcceleratorKey(KEY key, MASK mask); - LLMenuGL* getChildMenuByName(const std::string& name, BOOL recurse) const; + LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const; BOOL clearHoverItem(); @@ -610,9 +614,9 @@ public: virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL isActive() const { return isOpen() && getBranch() && getBranch()->getHighlightedItem(); } + virtual BOOL isActive() const; - virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); } + virtual BOOL isOpen() const; LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); } @@ -627,7 +631,8 @@ public: virtual void openMenu(); - virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; + virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const; + virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const; private: LLHandle mBranchHandle; diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 11fa290de1..c8162fe466 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -279,10 +279,7 @@ void LLModalDialog::onAppFocusLost() gFocusMgr.setMouseCapture( NULL ); } - if( gFocusMgr.childHasKeyboardFocus( instance ) ) - { - gFocusMgr.setKeyboardFocus( NULL ); - } + instance->setFocus(FALSE); } } diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 9f9e3aecac..e8ce1a8d97 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -454,14 +454,8 @@ BOOL LLMultiFloater::postBuild() return TRUE; } - requires("Preview Tabs"); - if (checkRequirements()) - { - mTabContainer = getChild("Preview Tabs"); - return TRUE; - } - - return FALSE; + mTabContainer = getChild("Preview Tabs"); + return TRUE; } void LLMultiFloater::updateResizeLimits() diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index da55ababab..667a3e10c4 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -192,10 +192,6 @@ void LLPanel::draw() void LLPanel::updateDefaultBtn() { - // This method does not call LLView::draw() so callers will need - // to take care of that themselves at the appropriate place in - // their rendering sequence - if( mDefaultBtn) { if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled()) @@ -254,7 +250,7 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask ) // handle user hitting ESC to defocus if (key == KEY_ESCAPE) { - gFocusMgr.setKeyboardFocus(NULL); + setFocus(FALSE); return TRUE; } else if( (mask == MASK_SHIFT) && (KEY_TAB == key)) @@ -315,53 +311,18 @@ void LLPanel::handleVisibilityChange ( BOOL new_visibility ) mVisibleSignal(this, LLSD(new_visibility) ); // Pass BOOL as LLSD } -BOOL LLPanel::checkRequirements() -{ - if (!mRequirementsError.empty()) - { - LLSD args; - args["COMPONENTS"] = mRequirementsError; - args["FLOATER"] = getName(); - - llwarns << getName() << " failed requirements check on: \n" - << mRequirementsError << llendl; - - LLNotifications::instance().add(LLNotification::Params("FailedRequirementsCheck").payload(args)); - mRequirementsError.clear(); - return FALSE; - } - - return TRUE; -} - void LLPanel::setFocus(BOOL b) { - if( b ) + if( b && !hasFocus()) { - if (!gFocusMgr.childHasKeyboardFocus(this)) - { - // give ourselves focus preemptively, to avoid infinite loop - LLUICtrl::setFocus(TRUE); - // then try to pass to first valid child - focusFirstItem(); - } + // give ourselves focus preemptively, to avoid infinite loop + LLUICtrl::setFocus(TRUE); + // then try to pass to first valid child + focusFirstItem(); } else { - if( this == gFocusMgr.getKeyboardFocus() ) - { - gFocusMgr.setKeyboardFocus( NULL ); - } - else - { - //RN: why is this here? - LLView::ctrl_list_t ctrls = getCtrlList(); - for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it) - { - LLUICtrl* ctrl = *ctrl_it; - ctrl->setFocus( FALSE ); - } - } + LLUICtrl::setFocus(b); } } @@ -704,7 +665,6 @@ BOOL LLPanel::childHasFocus(const std::string& id) } else { - childNotFound(id); return FALSE; } } @@ -881,58 +841,3 @@ void LLPanel::childSetControlName(const std::string& id, const std::string& cont view->setControlName(control_name, NULL); } } - -//virtual -LLView* LLPanel::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const -{ - // just get child, don't try to create a dummy one - LLView* view = LLUICtrl::getChildView(name, recurse, FALSE); - if (!view && !recurse) - { - childNotFound(name); - } - if (!view && create_if_missing) - { - view = getDefaultWidget(name); - if (!view) - { - // create LLViews explicitly, as they are not registered widget types - view = LLUICtrlFactory::createDefaultWidget(name); - } - } - return view; -} - -void LLPanel::childNotFound(const std::string& id) const -{ - if (mExpectedMembers.find(id) == mExpectedMembers.end()) - { - mNewExpectedMembers.insert(id); - } -} - -void LLPanel::childDisplayNotFound() -{ - if (mNewExpectedMembers.empty()) - { - return; - } - std::string msg; - expected_members_list_t::iterator itor; - for (itor=mNewExpectedMembers.begin(); itor!=mNewExpectedMembers.end(); ++itor) - { - msg.append(*itor); - msg.append("\n"); - mExpectedMembers.insert(*itor); - } - mNewExpectedMembers.clear(); - LLSD args; - args["CONTROLS"] = msg; - LLNotifications::instance().add("FloaterNotFound", args); -} - -void LLPanel::requires(const std::string& name) -{ - requires(name); -} - diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 2a70467ffc..3ee11483c3 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -115,9 +115,6 @@ public: /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); - // Override to set not found list: - /*virtual*/ LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; - // From LLFocusableElement /*virtual*/ void setFocus( BOOL b ); @@ -132,19 +129,6 @@ public: BOOL hasBorder() const { return mBorder != NULL; } void setBorderVisible( BOOL b ); - template void requires(const std::string& name) - { - // check for widget with matching type and name - if (LLView::getChild(name) == NULL) - { - mRequirementsError += name + "\n"; - } - } - - // requires LLView by default - void requires(const std::string& name); - BOOL checkRequirements(); - void setBackgroundColor( const LLColor4& color ) { mBgColorOpaque = color; } const LLColor4& getBackgroundColor() const { return mBgColorOpaque; } void setTransparentColor(const LLColor4& color) { mBgColorAlpha = color; } @@ -241,10 +225,6 @@ public: void childSetControlName(const std::string& id, const std::string& control_name); - // Error reporting - void childNotFound(const std::string& id) const; - void childDisplayNotFound(); - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); //call onOpen to let panel know when it's about to be shown or activated @@ -279,8 +259,6 @@ private: typedef std::map ui_string_map_t; ui_string_map_t mUIStrings; - std::string mRequirementsError; - // for setting the xml filename when building panel in context dependent cases std::string mXMLFilename; diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 30adbb023c..c66b9bde2b 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -90,18 +90,6 @@ BOOL LLRadioGroup::postBuild() return TRUE; } -// virtual -void LLRadioGroup::setEnabled(BOOL enabled) -{ - for (child_list_const_iter_t child_iter = getChildList()->begin(); - child_iter != getChildList()->end(); ++child_iter) - { - LLView *child = *child_iter; - child->setEnabled(enabled); - } - LLView::setEnabled(enabled); -} - void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled) { S32 count = 0; diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h index d04473fa44..b5516307fd 100644 --- a/indra/llui/llradiogroup.h +++ b/indra/llui/llradiogroup.h @@ -106,9 +106,7 @@ public: virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual void setEnabled(BOOL enabled); void setIndexEnabled(S32 index, BOOL enabled); - // return the index value of the selected item S32 getSelectedIndex() const { return mSelectedIndex; } diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h index 1560a03796..1c09cbb1bd 100644 --- a/indra/llui/llresizehandle.h +++ b/indra/llui/llresizehandle.h @@ -76,8 +76,8 @@ private: const ECorner mCorner; }; -const S32 RESIZE_HANDLE_HEIGHT = 16; -const S32 RESIZE_HANDLE_WIDTH = 16; +const S32 RESIZE_HANDLE_HEIGHT = 11; +const S32 RESIZE_HANDLE_WIDTH = 11; #endif // LL_RESIZEHANDLE_H diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 566825ff3b..b46915b379 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -394,7 +394,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) } else { - handled = childrenHandleMouseUp( x, y, mask ) != NULL; + handled = childrenHandleHover( x, y, mask ) != NULL; } // Opaque diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index 5522e5d0fa..30d906e04c 100644 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -127,11 +127,6 @@ public: void onLineUpBtnPressed(const LLSD& data); void onLineDownBtnPressed(const LLSD& data); - void setTrackColor( const LLColor4& color ) { mTrackColor = color; } - void setThumbColor( const LLColor4& color ) { mThumbColor = color; } - - void setOnScrollEndCallback(void (*callback)(void*), void* userdata) { mOnScrollEndCallback = callback; mOnScrollEndData = userdata;} - private: void updateThumbRect(); void changeLine(S32 delta, BOOL update_thumb ); diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 0b455f8e17..13f862f3af 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -55,8 +55,6 @@ static const S32 HORIZONTAL_MULTIPLE = 8; static const S32 VERTICAL_MULTIPLE = 16; -static const F32 MIN_AUTO_SCROLL_RATE = 120.f; -static const F32 MAX_AUTO_SCROLL_RATE = 500.f; static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; ///---------------------------------------------------------------------------- @@ -75,6 +73,9 @@ static ScrollContainerRegistry::Register r3("panel", &LLPanel::fromXML) LLScrollContainer::Params::Params() : is_opaque("opaque"), bg_color("color"), + border_visible("border_visible"), + min_auto_scroll_rate("min_auto_scroll_rate", 100), + max_auto_scroll_rate("max_auto_scroll_rate", 1000), reserve_scroll_corner("reserve_scroll_corner", false) { name = "scroll_container"; @@ -91,6 +92,8 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) mBackgroundColor(p.bg_color()), mIsOpaque(p.is_opaque), mReserveScrollCorner(p.reserve_scroll_corner), + mMinAutoScrollRate(p.min_auto_scroll_rate), + mMaxAutoScrollRate(p.max_auto_scroll_rate), mScrolledView(NULL) { static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); @@ -98,6 +101,7 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) LLViewBorder::Params params; params.name("scroll border"); params.rect(border_rect); + params.visible(p.border_visible); params.bevel_style(LLViewBorder::BEVEL_IN); mBorder = LLUICtrlFactory::create (params); LLView::addChild( mBorder ); @@ -115,12 +119,11 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) sbparams.doc_pos(0); sbparams.page_size(mInnerRect.getHeight()); sbparams.step_size(VERTICAL_MULTIPLE); + sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + sbparams.visible(false); + sbparams.change_callback(p.scroll_callback); mScrollbar[VERTICAL] = LLUICtrlFactory::create (sbparams); LLView::addChild( mScrollbar[VERTICAL] ); - mScrollbar[VERTICAL]->setVisible( FALSE ); - mScrollbar[VERTICAL]->setFollowsRight(); - mScrollbar[VERTICAL]->setFollowsTop(); - mScrollbar[VERTICAL]->setFollowsBottom(); LLRect horizontal_scroll_rect = mInnerRect; horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size; @@ -131,11 +134,11 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) sbparams.doc_pos(0); sbparams.page_size(mInnerRect.getWidth()); sbparams.step_size(VERTICAL_MULTIPLE); + sbparams.visible(false); + sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT); + sbparams.change_callback(p.scroll_callback); mScrollbar[HORIZONTAL] = LLUICtrlFactory::create (sbparams); LLView::addChild( mScrollbar[HORIZONTAL] ); - mScrollbar[HORIZONTAL]->setVisible( FALSE ); - mScrollbar[HORIZONTAL]->setFollowsLeft(); - mScrollbar[HORIZONTAL]->setFollowsRight(); } // Destroys the object @@ -181,7 +184,7 @@ void LLScrollContainer::reshape(S32 width, S32 height, { LLUICtrl::reshape( width, height, called_from_parent ); - mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 ); + mInnerRect = getLocalRect(); mInnerRect.stretch( -mBorder->getBorderWidth() ); if (mScrolledView) @@ -192,13 +195,14 @@ void LLScrollContainer::reshape(S32 width, S32 height, S32 visible_height = 0; BOOL show_v_scrollbar = FALSE; BOOL show_h_scrollbar = FALSE; - calcVisibleSize( scrolled_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() ); mScrollbar[VERTICAL]->setPageSize( visible_height ); mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() ); mScrollbar[HORIZONTAL]->setPageSize( visible_width ); + updateScroll(); } } @@ -217,6 +221,7 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask) { if( mScrollbar[i]->handleKeyHere(key, mask) ) { + updateScroll(); return TRUE; } } @@ -233,6 +238,7 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks ) // Pretend the mouse is over the scrollbar if( mScrollbar[i]->handleScrollWheel( 0, 0, clicks ) ) { + updateScroll(); return TRUE; } } @@ -241,28 +247,6 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks ) return TRUE; } -BOOL LLScrollContainer::needsToScroll(S32 x, S32 y, LLScrollContainer::SCROLL_ORIENTATION axis) const -{ - if(mScrollbar[axis]->getVisible()) - { - LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 ); - const S32 AUTOSCROLL_SIZE = 10; - if(mScrollbar[axis]->getVisible()) - { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - inner_rect_local.mRight -= scrollbar_size; - inner_rect_local.mTop += AUTOSCROLL_SIZE; - inner_rect_local.mBottom = inner_rect_local.mTop - AUTOSCROLL_SIZE; - } - if( inner_rect_local.pointInRect( x, y ) && (mScrollbar[axis]->getDocPos() > 0) ) - { - return TRUE; - } - - } - return FALSE; -} - BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -273,12 +257,27 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); // Scroll folder view if needed. Never accepts a drag or drop. *accept = ACCEPT_NO; - BOOL handled = FALSE; + BOOL handled = autoScroll(x, y); + + if( !handled ) + { + handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, + cargo_data, accept, tooltip_msg) != NULL; + } + + return TRUE; +} + +bool LLScrollContainer::autoScroll(S32 x, S32 y) +{ + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + bool scrolling = false; if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() ) { - const S32 AUTOSCROLL_SIZE = 10; - S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); - + LLRect screen_local_extents; + screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); + LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 ); if( mScrollbar[HORIZONTAL]->getVisible() ) { @@ -289,65 +288,61 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, inner_rect_local.mRight -= scrollbar_size; } + // clip rect against root view + inner_rect_local.intersectWith(screen_local_extents); + + S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); + // autoscroll region should take up no more than one third of visible scroller area + S32 auto_scroll_region_width = llmin(inner_rect_local.getWidth() / 3, 10); + S32 auto_scroll_region_height = llmin(inner_rect_local.getHeight() / 3, 10); + if( mScrollbar[HORIZONTAL]->getVisible() ) { - LLRect left_scroll_rect = inner_rect_local; - left_scroll_rect.mRight = AUTOSCROLL_SIZE; + LLRect left_scroll_rect = screen_local_extents; + left_scroll_rect.mRight = inner_rect_local.mLeft + auto_scroll_region_width; if( left_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() > 0) ) { mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() - auto_scroll_speed ); mAutoScrolling = TRUE; - handled = TRUE; + scrolling = true; } - LLRect right_scroll_rect = inner_rect_local; - right_scroll_rect.mLeft = inner_rect_local.mRight - AUTOSCROLL_SIZE; + LLRect right_scroll_rect = screen_local_extents; + right_scroll_rect.mLeft = inner_rect_local.mRight - auto_scroll_region_width; if( right_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() < mScrollbar[HORIZONTAL]->getDocPosMax()) ) { mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() + auto_scroll_speed ); mAutoScrolling = TRUE; - handled = TRUE; + scrolling = true; } } if( mScrollbar[VERTICAL]->getVisible() ) { - LLRect bottom_scroll_rect = inner_rect_local; - bottom_scroll_rect.mTop = AUTOSCROLL_SIZE + bottom_scroll_rect.mBottom; + LLRect bottom_scroll_rect = screen_local_extents; + bottom_scroll_rect.mTop = inner_rect_local.mBottom + auto_scroll_region_height; if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() < mScrollbar[VERTICAL]->getDocPosMax()) ) { mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() + auto_scroll_speed ); mAutoScrolling = TRUE; - handled = TRUE; + scrolling = true; } - LLRect top_scroll_rect = inner_rect_local; - top_scroll_rect.mBottom = inner_rect_local.mTop - AUTOSCROLL_SIZE; + LLRect top_scroll_rect = screen_local_extents; + top_scroll_rect.mBottom = inner_rect_local.mTop - auto_scroll_region_height; if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() > 0) ) { mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() - auto_scroll_speed ); mAutoScrolling = TRUE; - handled = TRUE; + scrolling = true; } } } - - if( !handled ) - { - handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, - cargo_data, accept, tooltip_msg) != NULL; - } - - return TRUE; + return scrolling; } void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const { - const LLRect& rect = getScrolledViewRect(); - calcVisibleSize(rect, visible_width, visible_height, show_h_scrollbar, show_v_scrollbar); -} - -void LLScrollContainer::calcVisibleSize( const LLRect& doc_rect, S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const -{ + const LLRect& doc_rect = getScrolledViewRect(); static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); S32 doc_width = doc_rect.getWidth(); S32 doc_height = doc_rect.getHeight(); @@ -384,20 +379,20 @@ void LLScrollContainer::draw() if (mAutoScrolling) { // add acceleration to autoscroll - mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE); + mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), mMaxAutoScrollRate); } else { - // reset to minimum - mAutoScrollRate = MIN_AUTO_SCROLL_RATE; + // reset to minimum for next time + mAutoScrollRate = mMinAutoScrollRate; } - // clear this flag to be set on next call to handleDragAndDrop + // clear this flag to be set on next call to autoScroll mAutoScrolling = FALSE; // auto-focus when scrollbar active // this allows us to capture user intent (i.e. stop automatically scrolling the view/etc) - if (!gFocusMgr.childHasKeyboardFocus(this) && - (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture())) + if (!hasFocus() + && (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture())) { focusFirstItem(); } @@ -424,7 +419,7 @@ void LLScrollContainer::draw() S32 visible_height = 0; BOOL show_v_scrollbar = FALSE; BOOL show_h_scrollbar = FALSE; - calcVisibleSize( mScrolledView->getRect(), &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); LLLocalClipRect clip(LLRect(mInnerRect.mLeft, mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height, @@ -506,7 +501,7 @@ void LLScrollContainer::updateScroll() S32 visible_height = 0; BOOL show_v_scrollbar = FALSE; BOOL show_h_scrollbar = FALSE; - calcVisibleSize( doc_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); S32 border_width = mBorder->getBorderWidth(); if( show_v_scrollbar ) @@ -584,71 +579,73 @@ void LLScrollContainer::setBorderVisible(BOOL b) mBorder->setVisible( b ); } -// Scroll so that as much of rect as possible is showing (where rect is defined in the space of scroller view, not scrolled) -void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLCoordGL& desired_offset) +LLRect LLScrollContainer::getVisibleContentRect() { - if (!mScrolledView) - { - llwarns << "LLScrollContainer::scrollToShowRect with no view!" << llendl; - return; - } + updateScroll(); + LLRect visible_rect = getContentWindowRect(); + LLRect contents_rect = mScrolledView->getRect(); + visible_rect.translate(-contents_rect.mLeft, -contents_rect.mBottom); + return visible_rect; +} +LLRect LLScrollContainer::getContentWindowRect() const +{ + LLRect scroller_view_rect; S32 visible_width = 0; S32 visible_height = 0; - BOOL show_v_scrollbar = FALSE; BOOL show_h_scrollbar = FALSE; - const LLRect& scrolled_rect = mScrolledView->getRect(); - calcVisibleSize( scrolled_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); - - // can't be so far left that right side of rect goes off screen, or so far right that left side does - S32 horiz_offset = llclamp(desired_offset.mX, llmin(0, -visible_width + rect.getWidth()), 0); - // can't be so high that bottom of rect goes off screen, or so low that top does - S32 vert_offset = llclamp(desired_offset.mY, 0, llmax(0, visible_height - rect.getHeight())); - - // Vertical - // 1. First make sure the top is visible - // 2. Then, if possible without hiding the top, make the bottom visible. - S32 vert_pos = mScrollbar[VERTICAL]->getDocPos(); - - // find scrollbar position to get top of rect on screen (scrolling up) - S32 top_offset = scrolled_rect.mTop - rect.mTop - vert_offset; - // find scrollbar position to get bottom of rect on screen (scrolling down) - S32 bottom_offset = vert_offset == 0 ? scrolled_rect.mTop - rect.mBottom - visible_height : top_offset; - // scroll up far enough to see top or scroll down just enough if item is bigger than visual area - if( vert_pos >= top_offset || visible_height < rect.getHeight()) - { - vert_pos = top_offset; - } - // else scroll down far enough to see bottom - else - if( vert_pos <= bottom_offset ) + BOOL show_v_scrollbar = FALSE; + calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar ); + S32 border_width = mBorder->getBorderWidth(); + scroller_view_rect.setOriginAndSize(border_width, + show_h_scrollbar ? mScrollbar[HORIZONTAL]->getRect().mTop : border_width, + visible_width, + visible_height); + return scroller_view_rect; +} + +// rect is in document coordinates, constraint is in display coordinates relative to content window rect +void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLRect& constraint) +{ + if (!mScrolledView) { - vert_pos = bottom_offset; + llwarns << "LLScrollContainer::scrollToShowRect with no view!" << llendl; + return; } + LLRect content_window_rect = getContentWindowRect(); + // get document rect + LLRect scrolled_rect = mScrolledView->getRect(); + + // shrink target rect to fit within constraint region, biasing towards top left + LLRect rect_to_constrain = rect; + rect_to_constrain.mBottom = llmax(rect_to_constrain.mBottom, rect_to_constrain.mTop - constraint.getHeight()); + rect_to_constrain.mRight = llmin(rect_to_constrain.mRight, rect_to_constrain.mLeft + constraint.getWidth()); + + // calculate allowable positions for scroller window in document coordinates + LLRect allowable_scroll_rect(rect_to_constrain.mRight - constraint.mRight, + rect_to_constrain.mBottom - constraint.mBottom, + rect_to_constrain.mLeft - constraint.mLeft, + rect_to_constrain.mTop - constraint.mTop); + + // translate from allowable region for lower left corner to upper left corner + allowable_scroll_rect.translate(0, content_window_rect.getHeight()); + + S32 vert_pos = llclamp(mScrollbar[VERTICAL]->getDocPos(), + mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mTop, // min vertical scroll + mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mBottom); // max vertical scroll + mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() ); - mScrollbar[VERTICAL]->setPageSize( visible_height ); + mScrollbar[VERTICAL]->setPageSize( content_window_rect.getHeight() ); mScrollbar[VERTICAL]->setDocPos( vert_pos ); - // Horizontal - // 1. First make sure left side is visible - // 2. Then, if possible without hiding the left side, make the right side visible. - S32 horiz_pos = mScrollbar[HORIZONTAL]->getDocPos(); - S32 left_offset = rect.mLeft - scrolled_rect.mLeft + horiz_offset; - S32 right_offset = horiz_offset == 0 ? rect.mRight - scrolled_rect.mLeft - visible_width : left_offset; + S32 horizontal_pos = llclamp(mScrollbar[HORIZONTAL]->getDocPos(), + allowable_scroll_rect.mLeft, + allowable_scroll_rect.mRight); - if( horiz_pos >= left_offset || visible_width < rect.getWidth() ) - { - horiz_pos = left_offset; - } - else if( horiz_pos <= right_offset ) - { - horiz_pos = right_offset; - } - mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() ); - mScrollbar[HORIZONTAL]->setPageSize( visible_width ); - mScrollbar[HORIZONTAL]->setDocPos( horiz_pos ); + mScrollbar[HORIZONTAL]->setPageSize( content_window_rect.getWidth() ); + mScrollbar[HORIZONTAL]->setDocPos( horizontal_pos ); // propagate scroll to document updateScroll(); @@ -657,21 +654,25 @@ void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLCoordGL& de void LLScrollContainer::pageUp(S32 overlap) { mScrollbar[VERTICAL]->pageUp(overlap); + updateScroll(); } void LLScrollContainer::pageDown(S32 overlap) { mScrollbar[VERTICAL]->pageDown(overlap); + updateScroll(); } void LLScrollContainer::goToTop() { mScrollbar[VERTICAL]->setDocPos(0); + updateScroll(); } void LLScrollContainer::goToBottom() { mScrollbar[VERTICAL]->setDocPos(mScrollbar[VERTICAL]->getDocSize()); + updateScroll(); } S32 LLScrollContainer::getBorderWidth() const diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 912d126f23..8385bca02f 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -66,9 +66,13 @@ public: struct Params : public LLInitParam::Block { - Optional is_opaque; + Optional is_opaque, + reserve_scroll_corner, + border_visible; + Optional min_auto_scroll_rate, + max_auto_scroll_rate; Optional bg_color; - Optional reserve_scroll_corner; + Optional scroll_callback; Params(); }; @@ -84,21 +88,23 @@ public: virtual void setValue(const LLSD& value) { mInnerRect.setValue(value); } - void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; - void calcVisibleSize( const LLRect& doc_rect, S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; void setBorderVisible( BOOL b ); - void scrollToShowRect( const LLRect& rect, const LLCoordGL& desired_offset ); + void scrollToShowRect( const LLRect& rect, const LLRect& constraint); + void scrollToShowRect( const LLRect& rect) { scrollToShowRect(rect, LLRect(0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0)); } + void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; } + LLRect getVisibleContentRect(); + LLRect getContentWindowRect() const; const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } void pageUp(S32 overlap = 0); void pageDown(S32 overlap = 0); void goToTop(); void goToBottom(); + bool isAtTop() { return mScrollbar[VERTICAL]->isAtBeginning(); } + bool isAtBottom() { return mScrollbar[VERTICAL]->isAtEnd(); } S32 getBorderWidth() const; - BOOL needsToScroll(S32 x, S32 y, SCROLL_ORIENTATION axis) const; - // LLView functionality virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -111,12 +117,15 @@ public: virtual void draw(); virtual bool addChild(LLView* view, S32 tab_group = 0); + + bool autoScroll(S32 x, S32 y); private: // internal scrollbar handlers virtual void scrollHorizontal( S32 new_pos ); virtual void scrollVertical( S32 new_pos ); void updateScroll(); + void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; LLScrollbar* mScrollbar[SCROLLBAR_COUNT]; LLView* mScrolledView; @@ -128,6 +137,8 @@ private: BOOL mReserveScrollCorner; BOOL mAutoScrolling; F32 mAutoScrollRate; + F32 mMinAutoScrollRate; + F32 mMaxAutoScrollRate; }; diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index cd43e194d2..e28da91305 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -310,17 +310,16 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col break; } mFont->render(mText.getWString(), 0, - start_x, 2.f, - display_color, - mFontAlignment, - LLFontGL::BOTTOM, - 0, - LLFontGL::NO_SHADOW, - string_chars, - getWidth(), - &right_x, - FALSE, - TRUE); + start_x, 2.f, + display_color, + mFontAlignment, + LLFontGL::BOTTOM, + 0, + LLFontGL::NO_SHADOW, + string_chars, + getWidth(), + &right_x, + TRUE); } // diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 3041773fb2..637642cdcd 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -160,7 +160,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), mTotalColumnPadding(0), - mSorted(FALSE), + mSorted(false), mDirty(FALSE), mOriginalSelection(-1), mLastSelected(NULL), @@ -374,6 +374,10 @@ std::vector LLScrollListCtrl::getAllSelected() const S32 LLScrollListCtrl::getFirstSelectedIndex() const { S32 CurSelectedIndex = 0; + + // make sure sort is up to date before returning an index + updateSort(); + item_list::const_iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { @@ -507,7 +511,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r { case ADD_TOP: mItemList.push_front(item); - setSorted(FALSE); + setNeedsSort(); break; case ADD_SORTED: @@ -524,18 +528,18 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r // ADD_SORTED just sorts by first column... // this might not match user sort criteria, so flag list as being in unsorted state - setSorted(FALSE); + setNeedsSort(); break; } case ADD_BOTTOM: mItemList.push_back(item); - setSorted(FALSE); + setNeedsSort(); break; default: llassert(0); mItemList.push_back(item); - setSorted(FALSE); + setNeedsSort(); break; } @@ -759,6 +763,9 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index ) return FALSE; } + // make sure sort is up to date + updateSort(); + S32 listlen = (S32)mItemList.size(); first_index = llclamp(first_index, 0, listlen-1); @@ -812,6 +819,7 @@ void LLScrollListCtrl::swapWithNext(S32 index) // At end of list, doesn't do anything return; } + updateSort(); LLScrollListItem *cur_itemp = mItemList[index]; mItemList[index] = mItemList[index + 1]; mItemList[index + 1] = cur_itemp; @@ -825,6 +833,7 @@ void LLScrollListCtrl::swapWithPrevious(S32 index) // At beginning of list, don't do anything } + updateSort(); LLScrollListItem *cur_itemp = mItemList[index]; mItemList[index] = mItemList[index - 1]; mItemList[index - 1] = cur_itemp; @@ -838,6 +847,8 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index) return; } + updateSort(); + LLScrollListItem *itemp; itemp = mItemList[target_index]; if (itemp == mLastSelected) @@ -939,6 +950,8 @@ S32 LLScrollListCtrl::selectMultiple( std::vector ids ) S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const { + updateSort(); + S32 index = 0; item_list::const_iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) @@ -955,6 +968,8 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id ) const { + updateSort(); + S32 index = 0; item_list::const_iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) @@ -980,6 +995,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) } else { + updateSort(); + item_list::iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { @@ -1022,6 +1039,8 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection) } else { + updateSort(); + item_list::reverse_iterator iter; for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++) { @@ -1436,7 +1455,7 @@ void LLScrollListCtrl::draw() LLLocalClipRect clip(getLocalRect()); // if user specifies sort, make sure it is maintained - sortItems(); + updateSort(); if (mNeedsScroll) { @@ -1463,7 +1482,7 @@ void LLScrollListCtrl::draw() if (mBorder) { - mBorder->setKeyboardFocusHighlight(gFocusMgr.getKeyboardFocus() == this); + mBorder->setKeyboardFocusHighlight(hasFocus()); } LLUICtrl::draw(); @@ -1754,6 +1773,8 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) // Excludes disabled items. LLScrollListItem* hit_item = NULL; + updateSort(); + LLRect item_rect; item_rect.setLeftTopAndSize( mItemListRect.mLeft, @@ -2199,7 +2220,7 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) sort_column_t new_sort_column(column_idx, ascending); - setSorted(FALSE); + setNeedsSort(); if (mSortColumns.empty()) { @@ -2241,10 +2262,10 @@ void LLScrollListCtrl::sortByColumn(const std::string& name, BOOL ascending) void LLScrollListCtrl::sortByColumnIndex(U32 column, BOOL ascending) { setSort(column, ascending); - sortItems(); + updateSort(); } -void LLScrollListCtrl::sortItems() +void LLScrollListCtrl::updateSort() const { if (hasSortOrder() && !isSorted()) { @@ -2254,7 +2275,7 @@ void LLScrollListCtrl::sortItems() mItemList.end(), SortScrollListItem(mSortColumns)); - setSorted(TRUE); + mSorted = true; } } @@ -2311,7 +2332,7 @@ void LLScrollListCtrl::scrollToShowSelected() return; } - sortItems(); + updateSort(); S32 index = getFirstSelectedIndex(); if (index < 0) @@ -2552,7 +2573,7 @@ std::string LLScrollListCtrl::getSortColumnName() else return ""; } -BOOL LLScrollListCtrl::hasSortOrder() +BOOL LLScrollListCtrl::hasSortOrder() const { return !mSortColumns.empty(); } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index e699711bd4..253a58ab73 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -329,15 +329,16 @@ public: std::string getSortColumnName(); BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } - BOOL hasSortOrder(); + BOOL hasSortOrder() const; S32 selectMultiple( std::vector ids ); - void sortItems(); + // conceptually const, but mutates mItemList + void updateSort() const; // sorts a list without affecting the permanent sort order (so further list insertions can be unsorted, for example) void sortOnce(S32 column, BOOL ascending); // manually call this whenever editing list items in place to flag need for resorting - void setSorted(BOOL sorted) { mSorted = sorted; } + void setNeedsSort() { mSorted = false; } void dirtyColumns(); // some operation has potentially affected column layout or ordering protected: @@ -390,7 +391,7 @@ private: const BOOL mDisplayColumnHeaders; BOOL mColumnsDirty; - item_list mItemList; + mutable item_list mItemList; LLScrollListItem *mLastSelected; @@ -429,7 +430,7 @@ private: S32 mTotalStaticColumnWidth; S32 mTotalColumnPadding; - BOOL mSorted; + mutable bool mSorted; typedef std::map column_map_t; column_map_t mColumns; diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp index 432d54dfee..929a809d88 100644 --- a/indra/llui/llstyle.cpp +++ b/indra/llui/llstyle.cpp @@ -38,119 +38,34 @@ #include "llstring.h" #include "llui.h" - -LLStyle::LLStyle() -{ - init(TRUE, LLColor4(0,0,0,1),LLStringUtil::null); -} - -LLStyle::LLStyle(const LLStyle &style) -{ - if (this != &style) - { - init(style.isVisible(),style.getColor(),style.getFontString()); - if (style.isLink()) - { - setLinkHREF(style.getLinkHREF()); - } - mItalic = style.mItalic; - mBold = style.mBold; - mUnderline = style.mUnderline; - mDropShadow = style.mDropShadow; - mImageHeight = style.mImageHeight; - mImageWidth = style.mImageWidth; - mImagep = style.mImagep; - mIsEmbeddedItem = style.mIsEmbeddedItem; - } - else - { - init(TRUE, LLColor4(0,0,0,1),LLStringUtil::null); - } -} - -LLStyle::LLStyle(BOOL is_visible, const LLColor4 &color, const std::string& font_name) -{ - init(is_visible, color, font_name); -} - -void LLStyle::init(BOOL is_visible, const LLColor4 &color, const std::string& font_name) +LLStyle::Params::Params() +: visible("visible", true), + drop_shadow("drop_shadow", false), + color("color", LLColor4::black), + font("font", LLFontGL::getFontMonospace()), + image("image"), + link_href("href") +{} + + +LLStyle::LLStyle(const LLStyle::Params& p) +: mVisible(p.visible), + mColor(p.color()), + mFont(p.font()), + mLink(p.link_href), + mDropShadow(p.drop_shadow), + mImageHeight(0), + mImageWidth(0), + mImagep(p.image()) +{} + +void LLStyle::setFont(const LLFontGL* font) { - mVisible = is_visible; - mColor = color; - setFontName(font_name); - setLinkHREF(LLStringUtil::null); - mItalic = FALSE; - mBold = FALSE; - mUnderline = FALSE; - mDropShadow = FALSE; - mImageHeight = 0; - mImageWidth = 0; - mIsEmbeddedItem = FALSE; -} - - -// Copy assignment -LLStyle &LLStyle::operator=(const LLStyle &rhs) -{ - if (this != &rhs) - { - setVisible(rhs.isVisible()); - setColor(rhs.getColor()); - this->mFontName = rhs.getFontString(); - this->mLink = rhs.getLinkHREF(); - mImagep = rhs.mImagep; - mImageHeight = rhs.mImageHeight; - mImageWidth = rhs.mImageWidth; - mItalic = rhs.mItalic; - mBold = rhs.mBold; - mUnderline = rhs.mUnderline; - mDropShadow = rhs.mDropShadow; - mIsEmbeddedItem = rhs.mIsEmbeddedItem; - } - - return *this; + mFont = font; } -//virtual -const std::string& LLStyle::getFontString() const -{ - return mFontName; -} - -//virtual -void LLStyle::setFontName(const std::string& fontname) -{ - mFontName = fontname; - - std::string fontname_lc = fontname; - LLStringUtil::toLower(fontname_lc); - - // cache the font pointer for speed when rendering text - if ((fontname_lc == "sansserif") || (fontname_lc == "sans-serif")) - { - mFont = LLFontGL::getFontSansSerif(); - } - else if ((fontname_lc == "serif")) - { - // *TODO: Do we have a real serif font? - mFont = LLFontGL::getFontMonospace(); - } - else if ((fontname_lc == "sansserifbig")) - { - mFont = LLFontGL::getFontSansSerifBig(); - } - else if (fontname_lc == "small") - { - mFont = LLFontGL::getFontSansSerifSmall(); - } - else - { - mFont = LLFontGL::getFontMonospace(); - } -} -//virtual -LLFontGL* LLStyle::getFont() const +const LLFontGL* LLStyle::getFont() const { return mFont; } diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h index 32ddded2c8..dcf274a651 100644 --- a/indra/llui/llstyle.h +++ b/indra/llui/llstyle.h @@ -35,59 +35,59 @@ #include "v4color.h" #include "llui.h" +#include "llinitparam.h" class LLFontGL; class LLStyle : public LLRefCount { public: - LLStyle(); - LLStyle(const LLStyle &style); - LLStyle(BOOL is_visible, const LLColor4 &color, const std::string& font_name); - - LLStyle &operator=(const LLStyle &rhs); - - virtual void init (BOOL is_visible, const LLColor4 &color, const std::string& font_name); - - virtual const LLColor4& getColor() const { return mColor; } - virtual void setColor(const LLColor4 &color) { mColor = color; } - - virtual BOOL isVisible() const; - virtual void setVisible(BOOL is_visible); + struct Params : public LLInitParam::Block + { + Optional visible, + drop_shadow; + Optional color; + Optional font; + Optional image; + Optional link_href; + Params(); + }; + LLStyle(const Params& p = Params()); +public: + const LLColor4& getColor() const { return mColor; } + void setColor(const LLColor4 &color) { mColor = color; } - virtual const std::string& getFontString() const; - virtual void setFontName(const std::string& fontname); - virtual LLFontGL* getFont() const; + BOOL isVisible() const; + void setVisible(BOOL is_visible); - virtual const std::string& getLinkHREF() const { return mLink; } - virtual void setLinkHREF(const std::string& href); - virtual BOOL isLink() const; + void setFont(const LLFontGL* font); + const LLFontGL* getFont() const; - virtual LLUIImagePtr getImage() const; - virtual void setImage(const LLUUID& src); + const std::string& getLinkHREF() const { return mLink; } + void setLinkHREF(const std::string& href); + BOOL isLink() const; - virtual BOOL isImage() const { return ((mImageWidth != 0) && (mImageHeight != 0)); } - virtual void setImageSize(S32 width, S32 height); + LLUIImagePtr getImage() const; + void setImage(const LLUUID& src); - BOOL getIsEmbeddedItem() const { return mIsEmbeddedItem; } - void setIsEmbeddedItem( BOOL b ) { mIsEmbeddedItem = b; } + BOOL isImage() const { return ((mImageWidth != 0) && (mImageHeight != 0)); } + void setImageSize(S32 width, S32 height); // inlined here to make it easier to compare to member data below. -MG bool operator==(const LLStyle &rhs) const { return - mVisible == rhs.isVisible() - && mColor == rhs.getColor() - && mFontName == rhs.getFontString() - && mLink == rhs.getLinkHREF() + mVisible == rhs.mVisible + && mColor == rhs.mColor + && mFont == rhs.mFont + && mLink == rhs.mLink && mImagep == rhs.mImagep && mImageHeight == rhs.mImageHeight && mImageWidth == rhs.mImageWidth && mItalic == rhs.mItalic && mBold == rhs.mBold && mUnderline == rhs.mUnderline - && mDropShadow == rhs.mDropShadow - && mIsEmbeddedItem == rhs.mIsEmbeddedItem; + && mDropShadow == rhs.mDropShadow; } bool operator!=(const LLStyle& rhs) const { return !(*this == rhs); } @@ -101,16 +101,15 @@ public: S32 mImageHeight; protected: - virtual ~LLStyle() { } + ~LLStyle() { } private: BOOL mVisible; LLUIColor mColor; std::string mFontName; - LLFontGL* mFont; // cached for performance + const LLFontGL* mFont; // cached for performance std::string mLink; LLUIImagePtr mImagep; - BOOL mIsEmbeddedItem; }; typedef LLPointer LLStyleSP; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 29c30004ef..ee36318107 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -190,7 +190,7 @@ void LLTabContainer::reshape(S32 width, S32 height, BOOL called_from_parent) } //virtual -LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const +LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse) const { tuple_list_t::const_iterator itor; for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) @@ -207,14 +207,42 @@ LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse, BOOL for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) { LLPanel *panel = (*itor)->mTabPanel; - LLView *child = panel->getChildView(name, recurse, FALSE); + LLView *child = panel->getChildView(name, recurse); if (child) { return child; } } } - return LLView::getChildView(name, recurse, create_if_missing); + return LLView::getChildView(name, recurse); +} + +//virtual +LLView* LLTabContainer::findChildView(const std::string& name, BOOL recurse) const +{ + tuple_list_t::const_iterator itor; + for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) + { + LLPanel *panel = (*itor)->mTabPanel; + if (panel->getName() == name) + { + return panel; + } + } + + if (recurse) + { + for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) + { + LLPanel *panel = (*itor)->mTabPanel; + LLView *child = panel->findChildView(name, recurse); + if (child) + { + return child; + } + } + } + return LLView::findChildView(name, recurse); } bool LLTabContainer::addChild(LLView* view, S32 tab_group) @@ -457,7 +485,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) index = llclamp(index, 0, tab_count-1); LLButton* tab_button = getTab(index)->mButton; gFocusMgr.setMouseCapture(this); - gFocusMgr.setKeyboardFocus(tab_button); + tab_button->setFocus(TRUE); } } return handled; diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 78592a0f9a..ebe76af966 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -104,7 +104,8 @@ public: /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance* accept, std::string& tooltip); - /*virtual*/ LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; + /*virtual*/ LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const; + /*virtual*/ LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const; /*virtual*/ void initFromParams(const LLPanel::Params& p); /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); /*virtual*/ BOOL postBuild(); diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index f9bcb685b8..96e72487b8 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -389,7 +389,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color ) mHAlign, mVAlign, 0, mShadowType, - S32_MAX, getRect().getWidth(), NULL, TRUE, mUseEllipses); + S32_MAX, getRect().getWidth(), NULL, mUseEllipses); } else { @@ -402,7 +402,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color ) mHAlign, mVAlign, 0, mShadowType, - line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses ); + line_length, getRect().getWidth(), NULL, mUseEllipses ); cur_pos += line_length + 1; y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing; } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 48816e4b9e..7d13220c94 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -58,7 +58,10 @@ #include "llcontrol.h" #include "llwindow.h" #include "lltextparser.h" +#include "llscrollcontainer.h" +#include "llpanel.h" #include +#include "llcombobox.h" // // Globals @@ -75,19 +78,73 @@ const S32 CURSOR_THICKNESS = 2; const S32 SPACES_PER_TAB = 4; -LLUIColor LLTextEditor::mLinkColor = LLColor4::blue; -void (* LLTextEditor::mURLcallback)(const std::string&) = NULL; -bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; -bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL; +void (* LLTextEditor::sURLcallback)(const std::string&) = NULL; +bool (* LLTextEditor::sSecondlifeURLcallback)(const std::string&) = NULL; +bool (* LLTextEditor::sSecondlifeURLcallbackRightClick)(const std::string&) = NULL; +// helper functors +struct LLTextEditor::compare_bottom +{ + bool operator()(const S32& a, const LLTextEditor::line_info& b) const + { + return a > b.mBottom; // bottom of a is higher than bottom of b + } + + bool operator()(const LLTextEditor::line_info& a, const S32& b) const + { + return a.mBottom > b; // bottom of a is higher than bottom of b + } +}; + +// helper functors +struct LLTextEditor::compare_top +{ + bool operator()(const S32& a, const LLTextEditor::line_info& b) const + { + return a > b.mTop; // top of a is higher than top of b + } + + bool operator()(const LLTextEditor::line_info& a, const S32& b) const + { + return a.mTop > b; // top of a is higher than top of b + } +}; + +struct LLTextEditor::line_end_compare +{ + bool operator()(const S32& pos, const LLTextEditor::line_info& info) const + { + return (pos < info.mDocIndexEnd); + } + + bool operator()(const LLTextEditor::line_info& info, const S32& pos) const + { + return (info.mDocIndexEnd < pos); + } + +}; + +// +// DocumentPanel +// + +class DocumentPanel : public LLPanel +{ +public: + DocumentPanel(const Params&); +}; + +DocumentPanel::DocumentPanel(const Params& p) +: LLPanel(p) +{} /////////////////////////////////////////////////////////////////// class LLTextEditor::LLTextCmdInsert : public LLTextEditor::LLTextCmd { public: - LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws) - : LLTextCmd(pos, group_with_next), mWString(ws) + LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment) + : LLTextCmd(pos, group_with_next, segment), mWString(ws) { } virtual ~LLTextCmdInsert() {} @@ -117,8 +174,8 @@ private: class LLTextEditor::LLTextCmdAddChar : public LLTextEditor::LLTextCmd { public: - LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc) - : LLTextCmd(pos, group_with_next), mWString(1, wc), mBlockExtensions(FALSE) + LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment) + : LLTextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE) { } virtual void blockExtensions() @@ -127,6 +184,9 @@ public: } virtual BOOL canExtend(S32 pos) const { + // cannot extend text with custom segments + if (!mSegments.empty()) return FALSE; + return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length()); } virtual BOOL execute( LLTextEditor* editor, S32* delta ) @@ -201,9 +261,10 @@ private: class LLTextEditor::LLTextCmdRemove : public LLTextEditor::LLTextCmd { public: - LLTextCmdRemove( S32 pos, BOOL group_with_next, S32 len ) : + LLTextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) : LLTextCmd(pos, group_with_next), mLen(len) { + std::swap(mSegments, segments); } virtual BOOL execute( LLTextEditor* editor, S32* delta ) { @@ -213,7 +274,7 @@ public: } virtual S32 undo( LLTextEditor* editor ) { - insert(editor, getPosition(), mWString ); + insert(editor, getPosition(), mWString); return getPosition() + mWString.length(); } virtual S32 redo( LLTextEditor* editor ) @@ -233,12 +294,13 @@ LLTextEditor::Params::Params() max_text_length("max_length", 255), read_only("read_only", false), embedded_items("embedded_items", false), - hide_scrollbar("hide_scrollbar", false), + hide_scrollbar("hide_scrollbar"), hide_border("hide_border", false), word_wrap("word_wrap", false), ignore_tab("ignore_tab", true), track_bottom("track_bottom", false), - takes_non_scroll_clicks("takes_non_scroll_clicks", true), + handle_edit_keys_directly("handle_edit_keys_directly", false), + show_line_numbers("show_line_numbers", false), cursor_color("cursor_color"), default_color("default_color"), text_color("text_color"), @@ -246,6 +308,8 @@ LLTextEditor::Params::Params() bg_readonly_color("bg_readonly_color"), bg_writeable_color("bg_writeable_color"), bg_focus_color("bg_focus_color"), + link_color("link_color"), + commit_on_focus_lost("commit_on_focus_lost", false), length("length"), // ignored type("type"), // ignored is_unicode("is_unicode")// ignored @@ -261,8 +325,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) mIsSelecting( FALSE ), mSelectionStart( 0 ), mSelectionEnd( 0 ), - mScrolledToBottom( TRUE ), - mOnScrollEndCallback( NULL ), mOnScrollEndData( NULL ), mCursorColor( p.cursor_color() ), mFgColor( p.text_color() ), @@ -271,15 +333,14 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) mWriteableBgColor( p.bg_writeable_color() ), mReadOnlyBgColor( p.bg_readonly_color() ), mFocusBgColor( p.bg_focus_color() ), + mLinkColor( p.link_color() ), mReadOnly(p.read_only), mWordWrap( p.word_wrap ), - mShowLineNumbers ( FALSE ), - mCommitOnFocusLost( FALSE ), - mHideScrollbarForShortDocs( FALSE ), - mTakesNonScrollClicks( p.takes_non_scroll_clicks ), + mShowLineNumbers ( p.show_line_numbers ), + mCommitOnFocusLost( p.commit_on_focus_lost), mTrackBottom( p.track_bottom ), mAllowEmbeddedItems( p.embedded_items ), - mHandleEditKeysDirectly( FALSE ), + mHandleEditKeysDirectly( p.handle_edit_keys_directly ), mMouseDownX(0), mMouseDownY(0), mLastSelectionX(-1), @@ -289,7 +350,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) mParseHTML(FALSE), mParseHighlights(FALSE), mTabsToNextField(p.ignore_tab), - mGLFont(p.font) + mDefaultFont(p.font), + mScrollIndex(-1) { static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); @@ -298,44 +360,42 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) // reset desired x cursor position mDesiredXPixel = -1; - updateTextRect(); + LLScrollContainer::Params scroll_params; + scroll_params.name = "text scroller"; + scroll_params.rect = getLocalRect(); + scroll_params.follows.flags = FOLLOWS_ALL; + scroll_params.is_opaque = false; + scroll_params.mouse_opaque = false; + scroll_params.min_auto_scroll_rate = 200; + scroll_params.max_auto_scroll_rate = 800; + mScroller = LLUICtrlFactory::create(scroll_params); + addChild(mScroller); + + LLPanel::Params panel_params; + panel_params.name = "text_contents"; + panel_params.rect = LLRect(0, 500, 500, 0); + panel_params.background_visible = true; + panel_params.background_opaque = true; + panel_params.mouse_opaque = false; + + mDocumentPanel = LLUICtrlFactory::create(panel_params); + mScroller->addChild(mDocumentPanel); - S32 line_height = llround( mGLFont->getLineHeight() ); - S32 page_size = mTextRect.getHeight() / line_height; - - // Init the scrollbar - LLRect scroll_rect; - scroll_rect.setOriginAndSize( - getRect().getWidth() - scrollbar_size, - 1, - scrollbar_size, - getRect().getHeight() - 1); - S32 lines_in_doc = getLineCount(); - LLScrollbar::Params sbparams; - sbparams.name("Scrollbar"); - sbparams.rect(scroll_rect); - sbparams.orientation(LLScrollbar::VERTICAL); - sbparams.doc_size(lines_in_doc); - sbparams.doc_pos(0); - sbparams.page_size(page_size); - sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - mScrollbar = LLUICtrlFactory::create (sbparams); - mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData); - addChild(mScrollbar); + updateTextRect(); static LLUICachedControl text_editor_border ("UITextEditorBorder", 0); LLViewBorder::Params params; - params.name("text ed border"); - params.rect(getLocalRect()); - params.bevel_style(LLViewBorder::BEVEL_IN); - params.border_thickness(text_editor_border); + params.name = "text ed border"; + params.rect = getLocalRect(); + params.bevel_style = LLViewBorder::BEVEL_IN; + params.border_thickness = text_editor_border; mBorder = LLUICtrlFactory::create (params); addChild( mBorder ); mBorder->setVisible(!p.hide_border); - appendText(p.default_text, FALSE, FALSE); + createDefaultSegment(); - setHideScrollbarForShortDocs(p.hide_scrollbar); + appendText(p.default_text, FALSE, FALSE); mHTML.clear(); } @@ -350,16 +410,23 @@ void LLTextEditor::initFromParams( const LLTextEditor::Params& p) if (p.read_only.isProvided()) { mReadOnly = p.read_only; - updateSegments(); - updateAllowingLanguageInput(); } + + if (p.commit_on_focus_lost.isProvided()) + { + mCommitOnFocusLost = p.commit_on_focus_lost; + } + + updateSegments(); + updateAllowingLanguageInput(); + // HACK: text editors always need to be enabled so that we can scroll LLView::setEnabled(true); } LLTextEditor::~LLTextEditor() { - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid // Route menu back to the default if( gEditMenuHandler == this ) @@ -369,8 +436,6 @@ LLTextEditor::~LLTextEditor() // Scrollbar is deleted by LLView mHoverSegment = NULL; - std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); - std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); } @@ -379,117 +444,183 @@ LLTextViewModel* LLTextEditor::getViewModel() const return (LLTextViewModel*)mViewModel.get(); } -void LLTextEditor::setTrackColor( const LLColor4& color ) -{ - mScrollbar->setTrackColor(color); -} - -void LLTextEditor::setThumbColor( const LLColor4& color ) -{ - mScrollbar->setThumbColor(color); -} - -void LLTextEditor::updateLineStartList(S32 startpos) +static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow"); +void LLTextEditor::reflow(S32 start_index) { - updateSegments(); - - bindEmbeddedChars(mGLFont); + if (!mReflowNeeded) return; - S32 seg_num = mSegments.size(); - S32 seg_idx = 0; - S32 seg_offset = 0; + LLFastTimer ft(FTM_TEXT_REFLOW); + static LLUICachedControl texteditor_vpad_top ("UITextEditorVPadTop", 0); + updateSegments(); - if (!mLineStartList.empty()) + while(mReflowNeeded) { - getSegmentAndOffset(startpos, &seg_idx, &seg_offset); - line_info t(seg_idx, seg_offset); - line_list_t::iterator iter = std::upper_bound(mLineStartList.begin(), mLineStartList.end(), t, line_info_compare()); - if (iter != mLineStartList.begin()) --iter; - seg_idx = iter->mSegment; - seg_offset = iter->mOffset; - mLineStartList.erase(iter, mLineStartList.end()); - } + bool scrolled_to_bottom = mScroller->isAtBottom(); + mReflowNeeded = FALSE; - LLWString text(getWText()); - while( seg_idx < seg_num ) - { - mLineStartList.push_back(line_info(seg_idx,seg_offset)); - BOOL line_ended = FALSE; - S32 start_x = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0; - S32 line_width = start_x; - while(!line_ended && seg_idx < seg_num) + LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos); + bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible + S32 first_line = getFirstVisibleLine(); + // if scroll anchor not on first line, update it to first character of first line + if (!mLineInfoList.empty() + && (mScrollIndex < mLineInfoList[first_line].mDocIndexStart + || mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd)) + { + mScrollIndex = mLineInfoList[first_line].mDocIndexStart; + } + LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex); + //first_char_rect.intersectWith(mTextRect); + + S32 cur_top = -texteditor_vpad_top; + + if (getLength()) { - LLTextSegment* segment = mSegments[seg_idx]; - S32 start_idx = segment->getStart() + seg_offset; - S32 end_idx = start_idx; - while (end_idx < segment->getEnd() && text[end_idx] != '\n') + segment_set_t::iterator seg_iter = mSegments.begin(); + S32 seg_offset = 0; + S32 line_start_index = 0; + S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin + S32 remaining_pixels = text_width; + LLWString text(getWText()); + S32 line_count = 0; + + // find and erase line info structs starting at start_index and going to end of document + if (!mLineInfoList.empty()) { - end_idx++; + // find first element whose end comes after 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; + getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset); + mLineInfoList.erase(iter, mLineInfoList.end()); } - if (start_idx == end_idx) + + // reserve enough space for line numbers + S32 line_height = mShowLineNumbers ? (S32)(LLFontGL::getFontMonospace()->getLineHeight()) : 0; + + while(seg_iter != mSegments.end()) { - if (end_idx >= segment->getEnd()) - { - // empty segment - seg_idx++; - seg_offset = 0; - } - else - { - // empty line - line_ended = TRUE; - seg_offset++; - } - } - else - { - const llwchar* str = text.c_str() + start_idx; - S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width, - end_idx - start_idx, mWordWrap, mAllowEmbeddedItems ); - if( 0 == drawn && line_width == start_x) + LLTextSegmentPtr segment = *seg_iter; + + // track maximum height of any segment on this line + line_height = llmax(line_height, segment->getMaxHeight()); + S32 cur_index = segment->getStart() + seg_offset; + // find run of text from this segment that we can display on one line + S32 end_index = cur_index; + while(end_index < segment->getEnd() && text[end_index] != '\n') { - // If at the beginning of a line, draw at least one character, even if it doesn't all fit. - drawn = 1; + ++end_index; } - seg_offset += drawn; - line_width += mGLFont->getWidth(str, 0, drawn, mAllowEmbeddedItems); - end_idx = segment->getStart() + seg_offset; - if (end_idx < segment->getEnd()) + + // ask segment how many character fit in remaining space + S32 max_characters = end_index - cur_index; + S32 character_count = segment->getNumChars(llmax(0, remaining_pixels), seg_offset, cur_index - line_start_index, max_characters); + + seg_offset += character_count; + + S32 last_segment_char_on_line = segment->getStart() + seg_offset; + + // if we didn't finish the current segment... + if (last_segment_char_on_line < segment->getEnd()) { - line_ended = TRUE; - if (text[end_idx] == '\n') + // set up index for next line + // ...skip newline, we don't want to draw + S32 next_line_count = line_count; + if (text[last_segment_char_on_line] == '\n') { - seg_offset++; // skip newline + seg_offset++; + last_segment_char_on_line++; + next_line_count++; } + + // add line info and keep going + mLineInfoList.push_back(line_info(line_start_index, last_segment_char_on_line, cur_top, cur_top - line_height, line_count)); + + line_start_index = segment->getStart() + seg_offset; + cur_top -= line_height; + remaining_pixels = text_width; + line_height = 0; + line_count = next_line_count; + } + // ...just consumed last segment.. + else if (++segment_set_t::iterator(seg_iter) == mSegments.end()) + { + mLineInfoList.push_back(line_info(line_start_index, last_segment_char_on_line, cur_top, cur_top - line_height, line_count)); + cur_top -= line_height; + break; } + // finished a segment and there are segments remaining on this line else { - // finished with segment - seg_idx++; + // subtract pixels used and increment segment + remaining_pixels -= segment->getWidth(seg_offset, character_count); + ++seg_iter; seg_offset = 0; } } } - } - - unbindEmbeddedChars(mGLFont); - mScrollbar->setDocSize( getLineCount() ); + // change mDocumentPanel document size to accomodate reflowed text + LLRect document_rect; + document_rect.setOriginAndSize(1, 1, + mScroller->getContentWindowRect().getWidth(), + llmax(mScroller->getContentWindowRect().getHeight(), -cur_top)); + mDocumentPanel->setShape(document_rect); - if (mHideScrollbarForShortDocs) - { - BOOL short_doc = (mScrollbar->getDocSize() <= mScrollbar->getPageSize()); - mScrollbar->setVisible(!short_doc); - } + // after making document big enough to hold all the text, move the text to fit in the document + if (!mLineInfoList.empty()) + { + S32 delta_pos = mDocumentPanel->getRect().getHeight() - mLineInfoList.begin()->mTop - texteditor_vpad_top; + // move line segments to fit new document rect + for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it) + { + it->mTop += delta_pos; + it->mBottom += delta_pos; + } + } - // if scrolled to bottom, stay at bottom - // unless user is selecting text - // do this after updating page size - if (mScrolledToBottom && mTrackBottom && !hasMouseCapture()) - { - endOfDoc(); + // calculate visible region for diplaying text + updateTextRect(); + + for (segment_set_t::iterator segment_it = mSegments.begin(); + segment_it != mSegments.end(); + ++segment_it) + { + LLTextSegmentPtr segmentp = *segment_it; + segmentp->updateLayout(*this); + + } + + // apply scroll constraints after reflowing text + if (!hasMouseCapture()) + { + LLRect visible_content_rect = mScroller->getVisibleContentRect(); + if (scrolled_to_bottom && mTrackBottom) + { + // keep bottom of text buffer visible + endOfDoc(); + } + else if (hasSelection() && follow_selection) + { + // keep cursor in same vertical position on screen when selecting text + LLRect new_cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos); + new_cursor_rect_doc.translate(visible_content_rect.mLeft, visible_content_rect.mBottom); + mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect); + //llassert_always(getLocalRectFromDocIndex(mCursorPos).mBottom == old_cursor_rect.mBottom); + } + else + { + // keep first line of text visible + LLRect new_first_char_rect = getLocalRectFromDocIndex(mScrollIndex); + new_first_char_rect.translate(visible_content_rect.mLeft, visible_content_rect.mBottom); + mScroller->scrollToShowRect(new_first_char_rect, first_char_rect); + //llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom); + } + } } + + // reset desired x cursor position + updateCursorXPos(); } //////////////////////////////////////////////////////////// @@ -519,35 +650,53 @@ BOOL LLTextEditor::truncate() return did_truncate; } +void LLTextEditor::clearSegments() +{ + mHoverSegment = NULL; + mSegments.clear(); +} + void LLTextEditor::setText(const LLStringExplicit &utf8str) { + clearSegments(); + // LLStringUtil::removeCRLF(utf8str); - mViewModel->setValue(utf8str_removeCRLF(utf8str)); + getViewModel()->setValue(utf8str_removeCRLF(utf8str)); truncate(); blockUndo(); - setCursorPos(0); + createDefaultSegment(); + + startOfDoc(); deselect(); needsReflow(); resetDirty(); + + onValueChange(0, getLength()); } void LLTextEditor::setWText(const LLWString &wtext) { + clearSegments(); + getViewModel()->setDisplay(wtext); truncate(); blockUndo(); - setCursorPos(0); + createDefaultSegment(); + + startOfDoc(); deselect(); needsReflow(); resetDirty(); + + onValueChange(0, getLength()); } // virtual @@ -562,39 +711,7 @@ std::string LLTextEditor::getText() const { llwarns << "getText() called on text with embedded items (not supported)" << llendl; } - return mViewModel->getValue().asString(); -} - -void LLTextEditor::setWordWrap(BOOL b) -{ - mWordWrap = b; - - setCursorPos(0); - deselect(); - - needsReflow(); -} - - -void LLTextEditor::setBorderVisible(BOOL b) -{ - mBorder->setVisible(b); -} - -BOOL LLTextEditor::isBorderVisible() const -{ - return mBorder->getVisible(); -} - -void LLTextEditor::setHideScrollbarForShortDocs(BOOL b) -{ - mHideScrollbarForShortDocs = b; - - if (mHideScrollbarForShortDocs) - { - BOOL short_doc = (mScrollbar->getDocSize() <= mScrollbar->getPageSize()); - mScrollbar->setVisible(!short_doc); - } + return getViewModel()->getValue().asString(); } void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap) @@ -619,7 +736,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insen if (selected_text == search_text) { // We already have this word selected, we are searching for the next. - mCursorPos += search_text.size(); + setCursorPos(mCursorPos + search_text.size()); } } @@ -682,9 +799,7 @@ BOOL LLTextEditor::replaceText(const std::string& search_text_in, const std::str void LLTextEditor::replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive) { - S32 cur_pos = mScrollbar->getDocPos(); - - setCursorPos(0); + startOfDoc(); selectNext(search_text, case_insensitive, FALSE); BOOL replaced = TRUE; @@ -692,14 +807,12 @@ void LLTextEditor::replaceTextAll(const std::string& search_text, const std::str { replaced = replaceText(search_text,replace_text, case_insensitive, FALSE); } - - mScrollbar->setDocPos(cur_pos); } // Picks a new cursor position based on the screen size of text being drawn. -void LLTextEditor::setCursorAtLocalPos( S32 local_x, S32 local_y, BOOL round ) +void LLTextEditor::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset ) { - setCursorPos(getCursorPosFromLocalCoord(local_x, local_y, round)); + setCursorPos(getDocIndexFromLocalCoord(local_x, local_y, round), keep_cursor_offset); } S32 LLTextEditor::prevWordPos(S32 cursorPos) const @@ -709,7 +822,7 @@ S32 LLTextEditor::prevWordPos(S32 cursorPos) const { cursorPos--; } - while( (cursorPos > 0) && isPartOfWord( wtext[cursorPos-1] ) ) + while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) ) { cursorPos--; } @@ -719,7 +832,7 @@ S32 LLTextEditor::prevWordPos(S32 cursorPos) const S32 LLTextEditor::nextWordPos(S32 cursorPos) const { LLWString wtext(getWText()); - while( (cursorPos < getLength()) && isPartOfWord( wtext[cursorPos] ) ) + while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) ) { cursorPos++; } @@ -739,171 +852,331 @@ S32 LLTextEditor::getLineStart( S32 line ) const } line = llclamp(line, 0, num_lines-1); - S32 segidx = mLineStartList[line].mSegment; - S32 segoffset = mLineStartList[line].mOffset; - LLTextSegment* seg = mSegments[segidx]; - S32 res = seg->getStart() + segoffset; - if (res > seg->getEnd()) llerrs << "wtf" << llendl; - return res; + return mLineInfoList[line].mDocIndexStart; +} + +S32 LLTextEditor::getLineHeight( S32 line ) const +{ + S32 num_lines = getLineCount(); + if (num_lines == 0) + { + return 0; + } + + line = llclamp(line, 0, num_lines-1); + return mLineInfoList[line].mTop - mLineInfoList[line].mBottom; } // Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line. -void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp ) const +void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp, bool include_wordwrap) const { - if (mLineStartList.empty()) + if (mLineInfoList.empty()) { *linep = 0; *offsetp = startpos; } else { - S32 seg_idx, seg_offset; - getSegmentAndOffset( startpos, &seg_idx, &seg_offset ); + line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), startpos, line_end_compare()); + if (include_wordwrap) + { + *linep = iter - mLineInfoList.begin(); + } + else + { + if (iter == mLineInfoList.end()) + { + *linep = mLineInfoList.back().mLineNum; + } + else + { + *linep = iter->mLineNum; + } + } + *offsetp = startpos - iter->mDocIndexStart; + } +} - line_info tline(seg_idx, seg_offset); - line_list_t::const_iterator iter = std::upper_bound(mLineStartList.begin(), mLineStartList.end(), tline, line_info_compare()); - if (iter != mLineStartList.begin()) --iter; - *linep = iter - mLineStartList.begin(); - S32 line_start = mSegments[iter->mSegment]->getStart() + iter->mOffset; - *offsetp = startpos - line_start; +void LLTextEditor::getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const +{ + *seg_iter = getSegIterContaining(startpos); + if (*seg_iter == mSegments.end()) + { + *offsetp = 0; + } + else + { + *offsetp = startpos - (**seg_iter)->getStart(); } } -void LLTextEditor::getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const +void LLTextEditor::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp ) { - if (mSegments.empty()) + *seg_iter = getSegIterContaining(startpos); + if (*seg_iter == mSegments.end()) { - *segidxp = -1; - *offsetp = startpos; + *offsetp = 0; + } + else + { + *offsetp = startpos - (**seg_iter)->getStart(); } - - LLTextSegment tseg(startpos); - segment_list_t::const_iterator seg_iter; - seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &tseg, LLTextSegment::compare()); - if (seg_iter != mSegments.begin()) --seg_iter; - *segidxp = seg_iter - mSegments.begin(); - *offsetp = startpos - (*seg_iter)->getStart(); } -const LLTextSegment* LLTextEditor::getPreviousSegment() const +const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const { // find segment index at character to left of cursor (or rightmost edge of selection) - S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1); - return idx >= 0 ? mSegments[idx] : NULL; + segment_set_t::const_iterator it = mSegments.lower_bound(new LLIndexSegment(mCursorPos)); + + if (it != mSegments.end()) + { + return *it; + } + else + { + return LLTextSegmentPtr(); + } } -void LLTextEditor::getSelectedSegments(std::vector& segments) const +void LLTextEditor::getSelectedSegments(LLTextEditor::segment_vec_t& segments) const { S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; - S32 first_idx = llmax(0, getSegmentIdxAtOffset(left)); - S32 last_idx = llmax(0, first_idx, getSegmentIdxAtOffset(right)); - for (S32 idx = first_idx; idx <= last_idx; ++idx) - { - segments.push_back(mSegments[idx]); - } + return getSegmentsInRange(segments, left, right, true); } -S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const +void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, S32 start, S32 end, bool include_partial) const { - if(mShowLineNumbers) + segment_set_t::const_iterator first_it = getSegIterContaining(start); + segment_set_t::const_iterator end_it = getSegIterContaining(end - 1); + if (end_it != mSegments.end()) ++end_it; + + for (segment_set_t::const_iterator it = first_it; it != end_it; ++it) { - local_x -= UI_TEXTEDITOR_LINE_NUMBER_MARGIN; + LLTextSegmentPtr segment = *it; + if (include_partial + || (segment->getStart() >= start + && segment->getEnd() <= end)) + { + segments_out.push_back(segment); + } } +} - // If round is true, if the position is on the right half of a character, the cursor - // will be put to its right. If round is false, the cursor will always be put to the - // character's left. +// If round is true, if the position is on the right half of a character, the cursor +// will be put to its right. If round is false, the cursor will always be put to the +// character's left. +S32 LLTextEditor::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const +{ // Figure out which line we're nearest to. - S32 total_lines = getLineCount(); - S32 line_height = llround( mGLFont->getLineHeight() ); - S32 max_visible_lines = mTextRect.getHeight() / line_height; - S32 scroll_lines = mScrollbar->getDocPos(); - S32 visible_lines = llmin( total_lines - scroll_lines, max_visible_lines ); // Lines currently visible + LLRect visible_region = mScroller->getVisibleContentRect(); + + // binary search for line that starts before local_y + line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mTextRect.mBottom + visible_region.mBottom, compare_bottom()); - //S32 line = S32( 0.5f + ((mTextRect.mTop - local_y) / mGLFont->getLineHeight()) ); - S32 line = (mTextRect.mTop - 1 - local_y) / line_height; - if (line >= total_lines) + if (line_iter == mLineInfoList.end()) { return getLength(); // past the end } - line = llclamp( line, 0, visible_lines ) + scroll_lines; + S32 pos = getLength(); + S32 start_x = mTextRect.mLeft; + + segment_set_t::iterator line_seg_iter; + S32 line_seg_offset; + for(getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset); + line_seg_iter != mSegments.end(); + ++line_seg_iter, line_seg_offset = 0) + { + const LLTextSegmentPtr segmentp = *line_seg_iter; + + S32 segment_line_start = segmentp->getStart() + line_seg_offset; + S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd - 1) - segment_line_start; + S32 text_width = segmentp->getWidth(line_seg_offset, segment_line_length); + 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 + { + // Figure out which character we're nearest to. + S32 offset; + if (!segmentp->canEdit()) + { + S32 segment_width = segmentp->getWidth(0, segmentp->getEnd() - segmentp->getStart()); + if (round && local_x - start_x > segment_width / 2) + { + offset = segment_line_length; + } + else + { + offset = 0; + } + } + else + { + offset = segmentp->getOffset(local_x - start_x, line_seg_offset, segment_line_length, round); + } + pos = segment_line_start + offset; + break; + } + start_x += text_width; + } - S32 line_start = getLineStart(line); - S32 next_start = getLineStart(line+1); - S32 line_end = (next_start != line_start) ? next_start - 1 : getLength(); + return pos; +} - if(line_start == -1) - { - return 0; +LLRect LLTextEditor::getLocalRectFromDocIndex(S32 pos) const +{ + LLRect local_rect(mTextRect); + local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); + if (mLineInfoList.empty()) + { + return local_rect; } - else + + // clamp pos to valid values + pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1); + + + // find line that contains cursor + line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare()); + + LLRect scrolled_view_rect = mScroller->getVisibleContentRect(); + local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft; + local_rect.mBottom = mTextRect.mBottom + (line_iter->mBottom - scrolled_view_rect.mBottom); + local_rect.mTop = mTextRect.mBottom + (line_iter->mTop - scrolled_view_rect.mBottom); + + segment_set_t::iterator line_seg_iter; + S32 line_seg_offset; + segment_set_t::iterator cursor_seg_iter; + S32 cursor_seg_offset; + getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset); + getSegmentAndOffset(pos, &cursor_seg_iter, &cursor_seg_offset); + + while(line_seg_iter != mSegments.end()) { - S32 line_len = line_end - line_start; - S32 pos; - LLWString text(getWText()); + const LLTextSegmentPtr segmentp = *line_seg_iter; - if (mAllowEmbeddedItems) + if (line_seg_iter == cursor_seg_iter) { - // Figure out which character we're nearest to. - bindEmbeddedChars(mGLFont); - pos = mGLFont->charFromPixelOffset(text.c_str(), line_start, - (F32)(local_x - mTextRect.mLeft), - (F32)(mTextRect.getWidth()), - line_len, - round, TRUE); - unbindEmbeddedChars(mGLFont); + // cursor advanced to right based on difference in offset of cursor to start of line + local_rect.mLeft += segmentp->getWidth(line_seg_offset, cursor_seg_offset - line_seg_offset); + + break; } else { - pos = mGLFont->charFromPixelOffset(text.c_str(), line_start, - (F32)(local_x - mTextRect.mLeft), - (F32)mTextRect.getWidth(), - line_len, - round); + // add remainder of current text segment to cursor position + local_rect.mLeft += segmentp->getWidth(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset); + // offset will be 0 for all segments after the first + line_seg_offset = 0; + // go to next text segment on this line + ++line_seg_iter; } - - return line_start + pos; } + + local_rect.mRight = local_rect.mLeft; + + return local_rect; +} + +void LLTextEditor::addDocumentChild(LLView* view) +{ + mDocumentPanel->addChild(view); } -void LLTextEditor::setCursor(S32 row, S32 column) +void LLTextEditor::removeDocumentChild(LLView* view) +{ + mDocumentPanel->removeChild(view); +} + +bool LLTextEditor::setCursor(S32 row, S32 column) { - LLWString text(getWText()); - const llwchar* doc = text.c_str(); - const char CR = 10; - while(row--) + if (0 <= row && row < (S32)mLineInfoList.size()) { - while (CR != *doc++); + S32 doc_pos = mLineInfoList[row].mDocIndexStart; + column = llclamp(column, 0, mLineInfoList[row].mDocIndexEnd - mLineInfoList[row].mDocIndexStart - 1); + doc_pos += column; + updateCursorXPos(); + + return setCursorPos(doc_pos); } - doc += column; - setCursorPos(doc - text.c_str()); + return false; } -void LLTextEditor::setCursorPos(S32 offset) +bool LLTextEditor::setCursorPos(S32 cursor_pos, bool keep_cursor_offset) { - mCursorPos = llclamp(offset, 0, (S32)getLength()); + S32 new_cursor_pos = cursor_pos; + if (new_cursor_pos != mCursorPos) + { + new_cursor_pos = getEditableIndex(new_cursor_pos, new_cursor_pos >= mCursorPos); + } + + mCursorPos = llclamp(new_cursor_pos, 0, (S32)getLength()); needsScroll(); - // reset desired x cursor position - mDesiredXPixel = -1; + if (!keep_cursor_offset) + updateCursorXPos(); + // did we get requested position? + return new_cursor_pos == cursor_pos; } -// virtual -BOOL LLTextEditor::canDeselect() const +void LLTextEditor::updateCursorXPos() { - return hasSelection(); + // reset desired x cursor position + mDesiredXPixel = getLocalRectFromDocIndex(mCursorPos).mLeft; } - -void LLTextEditor::deselect() +// constraint cursor to editable segments of document +S32 LLTextEditor::getEditableIndex(S32 index, bool increasing_direction) { - mSelectionStart = 0; - mSelectionEnd = 0; - mIsSelecting = FALSE; -} + //// always allow editable position at end of doc + //if (index == getLength()) + //{ + // return index; + //} + + segment_set_t::iterator segment_iter; + S32 offset; + getSegmentAndOffset(index, &segment_iter, &offset); + + LLTextSegmentPtr segmentp = *segment_iter; + + if (segmentp->canEdit()) + { + return segmentp->getStart() + offset; + } + else if (segmentp->getStart() < index && index < segmentp->getEnd()) + { + // bias towards document end + if (increasing_direction) + { + return segmentp->getEnd(); + } + // bias towards document start + else + { + return segmentp->getStart(); + } + } + else + { + return index; + } +} + +// virtual +BOOL LLTextEditor::canDeselect() const +{ + return hasSelection(); +} + + +void LLTextEditor::deselect() +{ + mSelectionStart = 0; + mSelectionEnd = 0; + mIsSelecting = FALSE; +} void LLTextEditor::startSelection() @@ -1029,7 +1302,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) } right += delta_spaces; - //text = mWText; + text = getWText(); // Find the next new line while( (cur < right) && (text[cur] != '\n') ) @@ -1055,7 +1328,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) mSelectionStart = right; mSelectionEnd = left; } - mCursorPos = mSelectionEnd; + setCursorPos(mSelectionEnd); } } @@ -1070,7 +1343,7 @@ void LLTextEditor::selectAll() { mSelectionStart = getLength(); mSelectionEnd = 0; - mCursorPos = mSelectionEnd; + setCursorPos(mSelectionEnd); } @@ -1088,12 +1361,7 @@ BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_ } } - if( mSegments.empty() ) - { - return TRUE; - } - - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); + const LLTextSegmentPtr cur_segment = getSegmentAtLocalPos( x, y ); if( cur_segment ) { BOOL has_tool_tip = FALSE; @@ -1114,12 +1382,6 @@ BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_ return TRUE; } -BOOL LLTextEditor::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - // Pretend the mouse is over the scrollbar - return mScrollbar->handleScrollWheel( 0, 0, clicks ); -} - BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -1127,7 +1389,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) // Let scrollbar have first dibs handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; - if( !handled && mTakesNonScrollClicks) + if( !handled ) { if (!(mask & MASK_SHIFT)) { @@ -1141,31 +1403,10 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) if (mask & MASK_SHIFT) { S32 old_cursor_pos = mCursorPos; - setCursorAtLocalPos( x, y, TRUE ); + setCursorAtLocalPos( x, y, true ); if (hasSelection()) { - /* Mac-like behavior - extend selection towards the cursor - if (mCursorPos < mSelectionStart - && mCursorPos < mSelectionEnd) - { - // ...left of selection - mSelectionStart = llmax(mSelectionStart, mSelectionEnd); - mSelectionEnd = mCursorPos; - } - else if (mCursorPos > mSelectionStart - && mCursorPos > mSelectionEnd) - { - // ...right of selection - mSelectionStart = llmin(mSelectionStart, mSelectionEnd); - mSelectionEnd = mCursorPos; - } - else - { - mSelectionEnd = mCursorPos; - } - */ - // Windows behavior mSelectionEnd = mCursorPos; } else @@ -1178,7 +1419,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) } else { - setCursorAtLocalPos( x, y, TRUE ); + setCursorAtLocalPos( x, y, true ); startSelection(); } gFocusMgr.setMouseCapture( this ); @@ -1202,11 +1443,17 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - setFocus( TRUE ); - if( canPastePrimary() ) + BOOL handled = FALSE; + handled = childrenHandleMiddleMouseDown(x, y, mask) != NULL; + + if (!handled) { - setCursorAtLocalPos( x, y, TRUE ); - pastePrimary(); + setFocus( TRUE ); + if( canPastePrimary() ) + { + setCursorAtLocalPos( x, y, true ); + pastePrimary(); + } } return TRUE; } @@ -1217,7 +1464,12 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); BOOL handled = FALSE; + if (mHoverSegment) + { + mHoverSegment->setHasMouseHover(false); + } mHoverSegment = NULL; + if(hasMouseCapture() ) { if( mIsSelecting ) @@ -1228,17 +1480,11 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) mLastSelectionY = y; } - if( y > mTextRect.mTop ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 ); - } - else - if( y < mTextRect.mBottom ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 ); - } + mScroller->autoScroll(x, y); - setCursorAtLocalPos( x, y, TRUE ); + S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight); + S32 clamped_y = llclamp(y, mTextRect.mBottom, mTextRect.mTop); + setCursorAtLocalPos( clamped_x, clamped_y, true ); mSelectionEnd = mCursorPos; } @@ -1260,51 +1506,43 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) } // Opaque - if( !handled && mTakesNonScrollClicks) + if( !handled ) { // Check to see if we're over an HTML-style link - if( !mSegments.empty() ) + LLTextSegmentPtr cur_segment = getSegmentAtLocalPos( x, y ); + if( cur_segment ) { - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment ) + if(cur_segment->getStyle()->isLink()) { - if(cur_segment->getStyle()->isLink()) - { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl; - getWindow()->setCursor(UI_CURSOR_HAND); - handled = TRUE; - } - else - if(cur_segment->getStyle()->getIsEmbeddedItem()) - { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl; - getWindow()->setCursor(UI_CURSOR_HAND); - //getWindow()->setCursor(UI_CURSOR_ARROW); - handled = TRUE; - } - mHoverSegment = cur_segment; + lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl; + getWindow()->setCursor(UI_CURSOR_HAND); + handled = TRUE; } + //else + //if(cur_segment->getStyle()->getIsEmbeddedItem()) + //{ + // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl; + // getWindow()->setCursor(UI_CURSOR_HAND); + // //getWindow()->setCursor(UI_CURSOR_ARROW); + // handled = TRUE; + //} + if (mHoverSegment) + { + mHoverSegment->setHasMouseHover(false); + } + cur_segment->setHasMouseHover(true); + mHoverSegment = cur_segment; + mHTML = mHoverSegment->getStyle()->getLinkHREF(); } if( !handled ) { lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl; - if (!mScrollbar->getVisible() || x < getRect().getWidth() - scrollbar_size) - { - getWindow()->setCursor(UI_CURSOR_IBEAM); - } - else - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } + getWindow()->setCursor(UI_CURSOR_IBEAM); handled = TRUE; } } - if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())) - { - mOnScrollEndCallback(mOnScrollEndData); - } return handled; } @@ -1316,22 +1554,14 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) // let scrollbar have first dibs handled = LLView::childrenHandleMouseUp(x, y, mask) != NULL; - if( !handled && mTakesNonScrollClicks) + if( !handled ) { if( mIsSelecting ) { - // Finish selection - if( y > mTextRect.mTop ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 ); - } - else - if( y < mTextRect.mBottom ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 ); - } - - setCursorAtLocalPos( x, y, TRUE ); + mScroller->autoScroll(x, y); + S32 clamped_x = llclamp(x, mTextRect.mLeft, mTextRect.mRight); + S32 clamped_y = llclamp(y, mTextRect.mBottom, mTextRect.mTop); + setCursorAtLocalPos( clamped_x, clamped_y, true ); endSelection(); } @@ -1367,25 +1597,25 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) // let scrollbar have first dibs handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL; - if( !handled && mTakesNonScrollClicks) + if( !handled ) { - setCursorAtLocalPos( x, y, FALSE ); + setCursorAtLocalPos( x, y, false ); deselect(); LLWString text = getWText(); - if( isPartOfWord( text[mCursorPos] ) ) + if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) ) { // Select word the cursor is over - while ((mCursorPos > 0) && isPartOfWord(text[mCursorPos-1])) + while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1])) { - mCursorPos--; + if (!setCursorPos(mCursorPos - 1)) break; } startSelection(); - while ((mCursorPos < (S32)text.length()) && isPartOfWord( text[mCursorPos] ) ) + while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) ) { - mCursorPos++; + if (!setCursorPos(mCursorPos + 1)) break; } mSelectionEnd = mCursorPos; @@ -1394,7 +1624,7 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { // Select the character the cursor is over startSelection(); - mCursorPos++; + setCursorPos(mCursorPos + 1); mSelectionEnd = mCursorPos; } @@ -1457,19 +1687,25 @@ S32 LLTextEditor::execute( LLTextCmd* cmd ) return delta; } -S32 LLTextEditor::insert(const S32 pos, const LLWString &wstr, const BOOL group_with_next_op) +S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment) { - return execute( new LLTextCmdInsert( pos, group_with_next_op, wstr ) ); + return execute( new LLTextCmdInsert( pos, group_with_next_op, wstr, segment ) ); } -S32 LLTextEditor::remove(const S32 pos, const S32 length, const BOOL group_with_next_op) +S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op) { - return execute( new LLTextCmdRemove( pos, group_with_next_op, length ) ); + S32 end_pos = getEditableIndex(pos + length, true); + + segment_vec_t segments_to_remove; + // store text segments + getSegmentsInRange(segments_to_remove, pos, pos + length, false); + + return execute( new LLTextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) ); } -S32 LLTextEditor::append(const LLWString &wstr, const BOOL group_with_next_op) +S32 LLTextEditor::append(const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment) { - return insert(getLength(), wstr, group_with_next_op); + return insert(getLength(), wstr, group_with_next_op, segment); } S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc) @@ -1575,7 +1811,7 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc) } else { - return execute(new LLTextCmdAddChar(pos, FALSE, wc)); + return execute(new LLTextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); } } @@ -1612,10 +1848,10 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) if( 0 < mCursorPos ) { startSelection(); - mCursorPos--; + setCursorPos(mCursorPos - 1); if( mask & MASK_CONTROL ) { - mCursorPos = prevWordPos(mCursorPos); + setCursorPos(prevWordPos(mCursorPos)); } mSelectionEnd = mCursorPos; } @@ -1625,10 +1861,10 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) if( mCursorPos < getLength() ) { startSelection(); - mCursorPos++; + setCursorPos(mCursorPos + 1); if( mask & MASK_CONTROL ) { - mCursorPos = nextWordPos(mCursorPos); + setCursorPos(nextWordPos(mCursorPos)); } mSelectionEnd = mCursorPos; } @@ -1650,7 +1886,7 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) startSelection(); if( mask & MASK_CONTROL ) { - mCursorPos = 0; + setCursorPos(0); } else { @@ -1675,7 +1911,7 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask) startSelection(); if( mask & MASK_CONTROL ) { - mCursorPos = getLength(); + setCursorPos(getLength()); } else { @@ -1726,14 +1962,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) switch( key ) { case KEY_UP: - if (mReadOnly) - { - mScrollbar->setDocPos(mScrollbar->getDocPos() - 1); - } - else - { - changeLine( -1 ); - } + changeLine( -1 ); break; case KEY_PAGE_UP: @@ -1741,25 +1970,11 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) break; case KEY_HOME: - if (mReadOnly) - { - mScrollbar->setDocPos(0); - } - else - { - startOfLine(); - } + startOfLine(); break; case KEY_DOWN: - if (mReadOnly) - { - mScrollbar->setDocPos(mScrollbar->getDocPos() + 1); - } - else - { - changeLine( 1 ); - } + changeLine( 1 ); break; case KEY_PAGE_DOWN: @@ -1767,21 +1982,10 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) break; case KEY_END: - if (mReadOnly) - { - mScrollbar->setDocPos(mScrollbar->getDocPosMax()); - } - else - { - endOfLine(); - } + endOfLine(); break; case KEY_LEFT: - if (mReadOnly) - { - break; - } if( hasSelection() ) { setCursorPos(llmin( mCursorPos - 1, mSelectionStart, mSelectionEnd )); @@ -1800,10 +2004,6 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) break; case KEY_RIGHT: - if (mReadOnly) - { - break; - } if( hasSelection() ) { setCursorPos(llmax( mCursorPos + 1, mSelectionStart, mSelectionEnd )); @@ -1827,10 +2027,6 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask) } } - if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())) - { - mOnScrollEndCallback(mOnScrollEndData); - } return handled; } @@ -1967,7 +2163,7 @@ void LLTextEditor::pasteHelper(bool is_primary) } // Insert the new text into the existing text. - setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE)); + setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE, LLTextSegmentPtr())); deselect(); needsReflow(); @@ -2014,7 +2210,7 @@ BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask) if( mask & MASK_SHIFT ) { startSelection(); - mCursorPos = 0; + setCursorPos(0); mSelectionEnd = mCursorPos; } else @@ -2022,7 +2218,7 @@ BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask) // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down // all move the cursor as if clicking, so should deselect. deselect(); - setCursorPos(0); + startOfDoc(); } break; @@ -2251,42 +2447,87 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) BOOL return_key_hit = FALSE; BOOL text_may_have_changed = TRUE; - if ( gFocusMgr.getKeyboardFocus() == this ) + // Special case for TAB. If want to move to next field, report + // not handled and let the parent take care of field movement. + if (KEY_TAB == key && mTabsToNextField) { - // Special case for TAB. If want to move to next field, report - // not handled and let the parent take care of field movement. - if (KEY_TAB == key && mTabsToNextField) - { - return FALSE; - } + return FALSE; + } + /* + if (KEY_F10 == key) + { + LLComboBox::Params cp; + cp.name = "combo box"; + cp.label = "my combo"; + cp.rect.width = 100; + cp.rect.height = 20; + cp.items.add().label = "item 1"; + cp.items.add().label = "item 2"; + cp.items.add().label = "item 3"; + + appendWidget(LLUICtrlFactory::create(cp), "combo", true, false); + } + if (KEY_F11 == key) + { + LLButton::Params bp; + bp.name = "text button"; + bp.label = "Click me"; + bp.rect.width = 100; + bp.rect.height = 20; + appendWidget(LLUICtrlFactory::create(bp), "button", true, false); + } + */ + if (mReadOnly) + { + handled = mScroller->handleKeyHere( key, mask ); + } + else + { + // handle navigation keys ourself handled = handleNavigationKey( key, mask ); + } + + + if( handled ) + { + text_may_have_changed = FALSE; + } + + if( !handled ) + { + handled = handleSelectionKey( key, mask ); if( handled ) { - text_may_have_changed = FALSE; + selection_modified = TRUE; } - - if( !handled ) + } + + if( !handled ) + { + handled = handleControlKey( key, mask ); + if( handled ) { - handled = handleSelectionKey( key, mask ); - if( handled ) - { - selection_modified = TRUE; - } + selection_modified = TRUE; } - - if( !handled ) + } + + if( !handled && mHandleEditKeysDirectly ) + { + handled = handleEditKey( key, mask ); + if( handled ) { - handled = handleControlKey( key, mask ); - if( handled ) - { - selection_modified = TRUE; - } + selection_modified = TRUE; + text_may_have_changed = TRUE; } + } - if( !handled && mHandleEditKeysDirectly ) + // Handle most keys only if the text editor is writeable. + if( !mReadOnly ) + { + if( !handled ) { - handled = handleEditKey( key, mask ); + handled = handleSpecialKey( key, mask, &return_key_hit ); if( handled ) { selection_modified = TRUE; @@ -2294,41 +2535,27 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) } } - // Handle most keys only if the text editor is writeable. - if( !mReadOnly ) - { - if( !handled ) - { - handled = handleSpecialKey( key, mask, &return_key_hit ); - if( handled ) - { - selection_modified = TRUE; - text_may_have_changed = TRUE; - } - } + } - } + if( handled ) + { + resetKeystrokeTimer(); - if( handled ) + // Most keystrokes will make the selection box go away, but not all will. + if( !selection_modified && + KEY_SHIFT != key && + KEY_CONTROL != key && + KEY_ALT != key && + KEY_CAPSLOCK ) { - resetKeystrokeTimer(); - - // Most keystrokes will make the selection box go away, but not all will. - if( !selection_modified && - KEY_SHIFT != key && - KEY_CONTROL != key && - KEY_ALT != key && - KEY_CAPSLOCK ) - { - deselect(); - } + deselect(); + } - if(text_may_have_changed) - { - needsReflow(); - } - needsScroll(); + if(text_may_have_changed) + { + needsReflow(); } + needsScroll(); } return handled; @@ -2344,34 +2571,31 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char) BOOL handled = FALSE; - if ( gFocusMgr.getKeyboardFocus() == this ) + // Handle most keys only if the text editor is writeable. + if( !mReadOnly ) { - // Handle most keys only if the text editor is writeable. - if( !mReadOnly ) + if( '}' == uni_char ) { - if( '}' == uni_char ) - { - unindentLineBeforeCloseBrace(); - } + unindentLineBeforeCloseBrace(); + } - // TODO: KLW Add auto show of tool tip on ( - addChar( uni_char ); + // TODO: KLW Add auto show of tool tip on ( + addChar( uni_char ); - // Keys that add characters temporarily hide the cursor - getWindow()->hideCursorUntilMouseMove(); + // Keys that add characters temporarily hide the cursor + getWindow()->hideCursorUntilMouseMove(); - handled = TRUE; - } + handled = TRUE; + } - if( handled ) - { - resetKeystrokeTimer(); + if( handled ) + { + resetKeystrokeTimer(); - // Most keystrokes will make the selection box go away, but not all will. - deselect(); + // Most keystrokes will make the selection box go away, but not all will. + deselect(); - needsReflow(); - } + needsReflow(); } return handled; @@ -2544,6 +2768,12 @@ void LLTextEditor::onFocusLost() LLUICtrl::onFocusLost(); } +void LLTextEditor::onCommit() +{ + setControlValue(getValue()); + LLUICtrl::onCommit(); +} + void LLTextEditor::setEnabled(BOOL enabled) { // just treat enabled as read-only flag @@ -2560,300 +2790,187 @@ void LLTextEditor::drawBackground() { S32 left = 0; S32 top = getRect().getHeight(); - S32 right = getRect().getWidth(); S32 bottom = 0; LLColor4 bg_color = mReadOnly ? mReadOnlyBgColor.get() - : gFocusMgr.getKeyboardFocus() == this ? mFocusBgColor.get() : mWriteableBgColor.get(); + : hasFocus() ? mFocusBgColor.get() : mWriteableBgColor.get(); if( mShowLineNumbers ) { gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor.get() ); // line number area always read-only - gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, right, bottom, bg_color); // body text area to the right of line numbers gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator - } else { - gl_rect_2d(left, top, right, bottom, bg_color); // body text area - } - - LLView::draw(); + } } // Draws the black box behind the selected text void LLTextEditor::drawSelectionBackground() { // Draw selection even if we don't have keyboard focus for search/replace - if( hasSelection() ) + if( hasSelection() && !mLineInfoList.empty()) { LLWString text = getWText(); - const S32 text_len = getLength(); - std::queue line_endings; - - S32 line_height = llround( mGLFont->getLineHeight() ); + std::vector selection_rects; S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); - S32 selection_left_x = mTextRect.mLeft; - S32 selection_left_y = mTextRect.mTop - line_height; - S32 selection_right_x = mTextRect.mRight; - S32 selection_right_y = mTextRect.mBottom; - - BOOL selection_left_visible = FALSE; - BOOL selection_right_visible = FALSE; + LLRect selection_rect = mTextRect; // Skip through the lines we aren't drawing. - S32 cur_line = mScrollbar->getDocPos(); - - S32 left_line_num = cur_line; - S32 num_lines = getLineCount(); - S32 right_line_num = num_lines - 1; - - S32 line_start = -1; - if (cur_line >= num_lines) - { - return; - } + LLRect content_display_rect = mScroller->getVisibleContentRect(); - line_start = getLineStart(cur_line); + // binary search for line that starts before top of visible buffer + line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); + line_list_t::const_iterator end_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); - S32 left_visible_pos = line_start; - S32 right_visible_pos = line_start; - - S32 text_y = mTextRect.mTop - line_height; + bool done = false; // Find the coordinates of the selected area - while((cur_line < num_lines)) + for (;line_iter != end_iter && !done; ++line_iter) { - S32 next_line = -1; - S32 line_end = text_len; - - if ((cur_line + 1) < num_lines) + // is selection visible on this line? + if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right) { - next_line = getLineStart(cur_line + 1); - line_end = next_line; - - line_end = ( (line_end - line_start)==0 || text[next_line-1] == '\n' || text[next_line-1] == '\0' || text[next_line-1] == ' ' || text[next_line-1] == '\t' ) ? next_line-1 : next_line; - } + segment_set_t::iterator segment_iter; + S32 segment_offset; + getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); + + LLRect selection_rect; + selection_rect.mLeft = 0; + selection_rect.mRight = 0; + selection_rect.mBottom = line_iter->mBottom; + selection_rect.mTop = line_iter->mTop; + + for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) + { + LLTextSegmentPtr segmentp = *segment_iter; - const llwchar* line = text.c_str() + line_start; + S32 segment_line_start = segmentp->getStart() + segment_offset; + S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); - if( line_start <= selection_left && selection_left <= line_end ) - { - left_line_num = cur_line; - selection_left_visible = TRUE; - selection_left_x = mTextRect.mLeft + mGLFont->getWidth(line, 0, selection_left - line_start, mAllowEmbeddedItems); - selection_left_y = text_y; - } - if( line_start <= selection_right && selection_right <= line_end ) - { - right_line_num = cur_line; - selection_right_visible = TRUE; - selection_right_x = mTextRect.mLeft + mGLFont->getWidth(line, 0, selection_right - line_start, mAllowEmbeddedItems); - if (selection_right == line_end) - { - // add empty space for "newline" - //selection_right_x += mGLFont->getWidth("n"); - } - selection_right_y = text_y; - } - - // if selection spans end of current line... - if (selection_left <= line_end && line_end < selection_right && selection_left != selection_right) - { - // extend selection slightly beyond end of line - // to indicate selection of newline character (use "n" character to determine width) - const LLWString nstr(utf8str_to_wstring(std::string("n"))); - line_endings.push(mTextRect.mLeft + mGLFont->getWidth(line, 0, line_end - line_start, mAllowEmbeddedItems) + mGLFont->getWidth(nstr.c_str())); - } - - // move down one line - text_y -= line_height; + // if selection after beginning of segment + if(selection_left >= segment_line_start) + { + S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; + selection_rect.mLeft += segmentp->getWidth(segment_offset, num_chars); + } - right_visible_pos = line_end; - line_start = next_line; - cur_line++; + // if selection spans end of current segment... + if (selection_right > segment_line_end) + { + // extend selection slightly beyond end of line + // to indicate selection of newline character (use "n" character to determine width) + selection_rect.mRight += segmentp->getWidth(segment_offset, segment_line_end - segment_line_start); + } + // else if selection ends on current segment... + else + { + S32 num_chars = selection_right - segment_line_start; + selection_rect.mRight += segmentp->getWidth(segment_offset, num_chars); - if (selection_right_visible) - { - break; + break; + } + } + selection_rects.push_back(selection_rect); } } // Draw the selection box (we're using a box instead of reversing the colors on the selected text). - BOOL selection_visible = (left_visible_pos <= selection_right) && (selection_left <= right_visible_pos); - if( selection_visible ) + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + const LLColor4& color = mReadOnly ? mReadOnlyBgColor.get() : mWriteableBgColor.get(); + F32 alpha = hasFocus() ? 0.7f : 0.3f; + gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); + + for (std::vector::iterator rect_it = selection_rects.begin(); + rect_it != selection_rects.end(); + ++rect_it) { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - const LLColor4& color = mReadOnly ? mReadOnlyBgColor.get() : mWriteableBgColor.get(); - F32 alpha = hasFocus() ? 1.f : 0.5f; - gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); - S32 margin_offset = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0; - - if( selection_left_y == selection_right_y ) - { - // Draw from selection start to selection end - gl_rect_2d( selection_left_x + margin_offset, selection_left_y + line_height + 1, - selection_right_x + margin_offset, selection_right_y); - } - else - { - // Draw from selection start to the end of the first line - if( mTextRect.mRight == selection_left_x ) - { - selection_left_x -= CURSOR_THICKNESS; - } - - S32 line_end = line_endings.front(); - line_endings.pop(); - gl_rect_2d( selection_left_x + margin_offset, selection_left_y + line_height + 1, - line_end + margin_offset, selection_left_y ); - - S32 line_num = left_line_num + 1; - while(line_endings.size()) - { - S32 vert_offset = -(line_num - left_line_num) * line_height; - // Draw the block between the two lines - gl_rect_2d( mTextRect.mLeft + margin_offset, selection_left_y + vert_offset + line_height + 1, - line_endings.front() + margin_offset, selection_left_y + vert_offset); - line_endings.pop(); - line_num++; - } - - // Draw from the start of the last line to selection end - if( mTextRect.mLeft == selection_right_x ) - { - selection_right_x += CURSOR_THICKNESS; - } - gl_rect_2d( mTextRect.mLeft + margin_offset, selection_right_y + line_height + 1, - selection_right_x + margin_offset, selection_right_y ); - } - } - } -} + LLRect selection_rect = *rect_it; + selection_rect.translate(mTextRect.mLeft - content_display_rect.mLeft, mTextRect.mBottom - content_display_rect.mBottom); + gl_rect_2d(selection_rect); + } + } +} void LLTextEditor::drawCursor() { - if( gFocusMgr.getKeyboardFocus() == this - && gShowTextEditCursor && !mReadOnly) + if( hasFocus() + && gFocusMgr.getAppHasFocus() + && !mReadOnly) { - LLWString text = getWText(); - const S32 text_len = getLength(); + LLWString wtext = getWText(); + const llwchar* text = wtext.c_str(); - // Skip through the lines we aren't drawing. - S32 cur_pos = mScrollbar->getDocPos(); + LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos); + cursor_rect.translate(-1, 0); + segment_set_t::iterator seg_it = getSegIterContaining(mCursorPos); - S32 num_lines = getLineCount(); - if (cur_pos >= num_lines) + // take style from last segment + LLTextSegmentPtr segmentp; + + if (seg_it != mSegments.end()) { + segmentp = *seg_it; + } + else + { + //segmentp = mSegments.back(); return; } - S32 line_start = getLineStart(cur_pos); - - F32 line_height = mGLFont->getLineHeight(); - F32 text_y = (F32)(mTextRect.mTop) - line_height; - - F32 cursor_left = 0.f; - F32 next_char_left = 0.f; - F32 cursor_bottom = 0.f; - BOOL cursor_visible = FALSE; - S32 line_end = 0; - // Determine if the cursor is visible and if so what its coordinates are. - while( (mTextRect.mBottom <= llround(text_y)) && (cur_pos < num_lines)) + // Draw the cursor + // (Flash the cursor every half second starting a fixed time after the last keystroke) + F32 elapsed = mKeystrokeTimer.getElapsedTimeF32(); + if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) ) { - line_end = text_len + 1; - S32 next_line = -1; - if ((cur_pos + 1) < num_lines) + if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) { - next_line = getLineStart(cur_pos + 1); - line_end = next_line - 1; + S32 width = llmax(CURSOR_THICKNESS, segmentp->getWidth(mCursorPos - segmentp->getStart(), 1)); + cursor_rect.mRight = cursor_rect.mLeft + width; } - - const llwchar* line = text.c_str() + line_start; - - // Find the cursor and selection bounds - if( line_start <= mCursorPos && mCursorPos <= line_end ) + else { - cursor_visible = TRUE; - next_char_left = (F32)mTextRect.mLeft + mGLFont->getWidthF32(line, 0, mCursorPos - line_start, mAllowEmbeddedItems ); - cursor_left = next_char_left - 1.f; - cursor_bottom = text_y; - break; + cursor_rect.mRight = cursor_rect.mLeft + CURSOR_THICKNESS; } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // move down one line - text_y -= line_height; - line_start = next_line; - cur_pos++; - } - - if(mShowLineNumbers) - { - cursor_left += UI_TEXTEDITOR_LINE_NUMBER_MARGIN; - } + gGL.color4fv( mCursorColor.get().mV ); + + gl_rect_2d(cursor_rect); - // Draw the cursor - if( cursor_visible ) - { - // (Flash the cursor every half second starting a fixed time after the last keystroke) - F32 elapsed = mKeystrokeTimer.getElapsedTimeF32(); - if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) ) + if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n') { - F32 cursor_top = cursor_bottom + line_height + 1.f; - F32 cursor_right = cursor_left + (F32)CURSOR_THICKNESS; - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection()) + LLColor4 text_color; + const LLFontGL* fontp; + if (segmentp) { - cursor_left += CURSOR_THICKNESS; - const LLWString space(utf8str_to_wstring(std::string(" "))); - F32 spacew = mGLFont->getWidthF32(space.c_str()); - if (mCursorPos == line_end) - { - cursor_right = cursor_left + spacew; - } - else - { - F32 width = mGLFont->getWidthF32(text.c_str(), mCursorPos, 1, mAllowEmbeddedItems); - cursor_right = cursor_left + llmax(spacew, width); - } + text_color = segmentp->getColor(); + fontp = segmentp->getStyle()->getFont(); } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( mCursorColor.get().mV ); - - gl_rect_2d(llfloor(cursor_left), llfloor(cursor_top), - llfloor(cursor_right), llfloor(cursor_bottom)); - - if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n') + else if (mReadOnly) { - const LLTextSegment* segmentp = getSegmentAtOffset(mCursorPos); - LLColor4 text_color; - if (segmentp) - { - text_color = segmentp->getColor(); - } - else if (mReadOnly) - { - text_color = mReadOnlyFgColor.get(); - } - else - { - text_color = mFgColor.get(); - } - mGLFont->render(text, mCursorPos, next_char_left, cursor_bottom + line_height, - LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f), - LLFontGL::LEFT, LLFontGL::TOP, - LLFontGL::NORMAL, - LLFontGL::NO_SHADOW, - 1); + text_color = mReadOnlyFgColor.get(); + fontp = mDefaultFont; } + else + { + text_color = mFgColor.get(); + fontp = mDefaultFont; + } + fontp->render(text, mCursorPos, cursor_rect.mLeft, cursor_rect.mBottom, + LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f), + LLFontGL::LEFT, LLFontGL::BOTTOM, + LLFontGL::NORMAL, + LLFontGL::NO_SHADOW, + 1); + } - // Make sure the IME is in the right place - LLRect screen_pos = calcScreenRect(); - LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_left), screen_pos.mBottom + llfloor(cursor_top) ); + // Make sure the IME is in the right place + LLRect screen_pos = calcScreenRect(); + LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); - getWindow()->setLanguageTextInput( ime_pos ); - } + ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + getWindow()->setLanguageTextInput( ime_pos ); } } } @@ -2879,13 +2996,13 @@ void LLTextEditor::drawPreeditMarker() const S32 text_len = getLength(); const S32 num_lines = getLineCount(); - S32 cur_line = mScrollbar->getDocPos(); + S32 cur_line = getFirstVisibleLine(); if (cur_line >= num_lines) { return; } - const S32 line_height = llround( mGLFont->getLineHeight() ); + const S32 line_height = llround( mDefaultFont->getLineHeight() ); S32 line_start = getLineStart(cur_line); S32 line_y = mTextRect.mTop - line_height; @@ -2924,16 +3041,16 @@ void LLTextEditor::drawPreeditMarker() S32 preedit_left = mTextRect.mLeft; if (left > line_start) { - preedit_left += mGLFont->getWidth(text, line_start, left - line_start, mAllowEmbeddedItems); + preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start); } S32 preedit_right = mTextRect.mLeft; if (right < line_end) { - preedit_right += mGLFont->getWidth(text, line_start, right - line_start, mAllowEmbeddedItems); + preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start); } else { - preedit_right += mGLFont->getWidth(text, line_start, line_end - line_start, mAllowEmbeddedItems); + preedit_right += mDefaultFont->getWidth(text, line_start, line_end - line_start); } if (mPreeditStandouts[i]) @@ -2981,25 +3098,34 @@ void LLTextEditor::drawText() } LLGLSUIDefault gls_ui; - - S32 cur_line = mScrollbar->getDocPos(); + LLRect scrolled_view_rect = mScroller->getVisibleContentRect(); + LLRect content_rect = mScroller->getContentWindowRect(); + S32 first_line = getFirstVisibleLine(); S32 num_lines = getLineCount(); - if (cur_line >= num_lines) + if (first_line >= num_lines) { return; } - S32 line_start = getLineStart(cur_line); - LLTextSegment t(line_start); - segment_list_t::iterator seg_iter; - seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &t, LLTextSegment::compare()); - if (seg_iter == mSegments.end() || (*seg_iter)->getStart() > line_start) --seg_iter; - LLTextSegment* cur_segment = *seg_iter; - - S32 line_height = llround( mGLFont->getLineHeight() ); - F32 text_y = (F32)(mTextRect.mTop - line_height); - while((mTextRect.mBottom <= text_y) && (cur_line < num_lines)) + S32 line_start = getLineStart(first_line); + // find first text segment that spans top of visible portion of text buffer + segment_set_t::iterator seg_iter = getSegIterContaining(line_start); + if (seg_iter == mSegments.end()) { + return; + } + + LLTextSegmentPtr cur_segment = *seg_iter; + + for (S32 cur_line = first_line; cur_line < num_lines; cur_line++) + { + line_info& line = mLineInfoList[cur_line]; + + if ((line.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom) + { + break; + } + S32 next_start = -1; S32 line_end = text_len; @@ -3012,9 +3138,13 @@ void LLTextEditor::drawText() { --line_end; } - - F32 text_x = (F32)mTextRect.mLeft; + LLRect text_rect(mTextRect.mLeft - scrolled_view_rect.mLeft, + line.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom, + mTextRect.getWidth() - scrolled_view_rect.mLeft, + line.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom); + + // draw a single line of text S32 seg_start = line_start; while( seg_start < line_end ) { @@ -3024,184 +3154,120 @@ void LLTextEditor::drawText() if (seg_iter == mSegments.end()) { llwarns << "Ran off the segmentation end!" << llendl; + return; } cur_segment = *seg_iter; } - // Draw a segment within the line - S32 clipped_end = llmin( line_end, cur_segment->getEnd() ); - S32 clipped_len = clipped_end - seg_start; - if( clipped_len > 0 ) - { - LLStyleSP style = cur_segment->getStyle(); - if ( style->isImage() && (cur_segment->getStart() >= seg_start) && (cur_segment->getStart() <= clipped_end)) - { - S32 style_image_height = style->mImageHeight; - S32 style_image_width = style->mImageWidth; - LLUIImagePtr image = style->getImage(); - image->draw(llround(text_x), llround(text_y)+line_height-style_image_height, - style_image_width, style_image_height); - } + S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart(); + text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect)); - if (cur_segment == mHoverSegment && style->getIsEmbeddedItem()) - { - style->mUnderline = TRUE; - } - - S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); - - if ( (mParseHTML) && (left_pos > seg_start) && (left_pos < clipped_end) && mIsSelecting && (mSelectionStart == mSelectionEnd) ) - { - mHTML = style->getLinkHREF(); - } - - drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x ); - - // Note: text_x is incremented by drawClippedSegment() - seg_start += clipped_len; - } + seg_start = clipped_end + cur_segment->getStart(); } - // move down one line - text_y -= (F32)line_height; - line_start = next_start; - cur_line++; } } - -// Draws a single text segment, reversing the color for selection if needed. -void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyleSP& style, F32* right_x ) +void LLTextEditor::drawLineNumbers() { - if (!style->isVisible()) - { - return; - } - - const LLFontGL* font = mGLFont; - - LLColor4 color = style->getColor(); + LLGLSUIDefault gls_ui; - if ( style->getFontString()[0] ) + LLRect scrolled_view_rect = mScroller->getVisibleContentRect(); + LLRect content_rect = mScroller->getContentWindowRect(); + LLLocalClipRect clip(content_rect); + S32 first_line = getFirstVisibleLine(); + S32 num_lines = getLineCount(); + if (first_line >= num_lines) { - font = style->getFont(); + return; } - - U8 font_flags = LLFontGL::NORMAL; - if (style->mBold) - { - font_flags |= LLFontGL::BOLD; - } - if (style->mItalic) - { - font_flags |= LLFontGL::ITALIC; - } - if (style->mUnderline) - { - font_flags |= LLFontGL::UNDERLINE; - } + S32 cursor_line = getCurrentLine(); - if (style->getIsEmbeddedItem()) + if (mShowLineNumbers) { - static LLUIColor text_embedded_item_readonly_color = LLUIColorTable::instance().getColor("TextEmbeddedItemReadOnlyColor"); - static LLUIColor text_embedded_item_color = LLUIColorTable::instance().getColor("TextEmbeddedItemColor"); - if (mReadOnly) - { - color = text_embedded_item_readonly_color; - } - else - { - color = text_embedded_item_color; - } - } + S32 last_line_num = -1; - F32 y_top = y + (F32)llround(font->getLineHeight()); + for (S32 cur_line = first_line; cur_line < num_lines; cur_line++) + { + line_info& line = mLineInfoList[cur_line]; - if( selection_left > seg_start ) - { - // Draw normally - S32 start = seg_start; - S32 end = llmin( selection_left, seg_end ); - S32 length = end - start; - font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); - } - x = *right_x; - - if( (selection_left < seg_end) && (selection_right > seg_start) ) - { - // Draw reversed - S32 start = llmax( selection_left, seg_start ); - S32 end = llmin( selection_right, seg_end ); - S32 length = end - start; + if ((line.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom) + { + break; + } - font->render(text, start, x, y_top, - LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), - LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); - } - x = *right_x; - if( selection_right < seg_end ) - { - // Draw normally - S32 start = llmax( selection_right, seg_start ); - S32 end = seg_end; - S32 length = end - start; - font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); + S32 line_bottom = line.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom; + // draw the line numbers + if(line.mLineNum != last_line_num && line.mTop <= scrolled_view_rect.mTop) + { + const LLFontGL *num_font = LLFontGL::getFontMonospace(); + const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum )); + BOOL is_cur_line = cursor_line == line.mLineNum; + const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL; + const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor; + num_font->render( + ltext, // string to draw + 0, // begin offset + UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x + line_bottom, // y + fg_color, + LLFontGL::RIGHT, // horizontal alignment + LLFontGL::BOTTOM, // vertical alignment + style, + LLFontGL::NO_SHADOW, + S32_MAX, // max chars + UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2); // max pixels + last_line_num = line.mLineNum; + } + } } - } - +} void LLTextEditor::draw() { - // do on-demand reflow - if (mReflowNeeded) - { - updateLineStartList(); - mReflowNeeded = FALSE; - } + // reflow if needed, on demand + reflow(); // then update scroll position, as cursor may have moved - if (mScrollNeeded) - { - updateScrollFromCursor(); - mScrollNeeded = FALSE; - } + updateScrollFromCursor(); - { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? scrollbar_size : 0), 0)); + LLColor4 bg_color = mReadOnly + ? mReadOnlyBgColor.get() + : hasFocus() + ? mFocusBgColor.get() + : mWriteableBgColor.get(); + + mDocumentPanel->setBackgroundColor(bg_color); - bindEmbeddedChars( mGLFont ); + drawChildren(); + drawBackground(); //overlays scrolling panel bg + drawLineNumbers(); - drawBackground(); + { + LLLocalClipRect clip(mTextRect); drawSelectionBackground(); drawPreeditMarker(); drawText(); drawCursor(); - - unbindEmbeddedChars( mGLFont ); - - //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret - // when in readonly mode - mBorder->setKeyboardFocusHighlight( gFocusMgr.getKeyboardFocus() == this);// && !mReadOnly); } - - LLView::draw(); // Draw children (scrollbar and border) - // remember if we are supposed to be at the bottom of the buffer - mScrolledToBottom = isScrolledToBottom(); + //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret + // when in readonly mode + mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly); } -void LLTextEditor::onTabInto() +S32 LLTextEditor::getFirstVisibleLine() const { - // selecting all on tabInto causes users to hit tab twice and replace their text with a tab character - // theoretically, one could selectAll if mTabsToNextField is true, but we couldn't think of a use case - // where you'd want to select all anyway - // preserve insertion point when returning to the editor - //selectAll(); + LLRect visible_region = mScroller->getVisibleContentRect(); + + // binary search for line that starts before top of visible buffer + line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); + + return iter - mLineInfoList.begin(); } // virtual @@ -3270,103 +3336,62 @@ S32 LLTextEditor::getPos( S32 line, S32 offset ) void LLTextEditor::changePage( S32 delta ) { + const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10; + if (delta == 0) return; + + //RN: use pixel heights S32 line, offset; getLineAndOffset( mCursorPos, &line, &offset ); - // get desired x position to remember previous position - S32 desired_x_pixel = mDesiredXPixel; + LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos); - // allow one line overlap - S32 page_size = mScrollbar->getPageSize() - 1; if( delta == -1 ) { - line = llmax( line - page_size, 0); - setCursorPos(getPos( line, offset )); - mScrollbar->setDocPos( mScrollbar->getDocPos() - page_size ); + mScroller->pageUp(PIXEL_OVERLAP_ON_PAGE_CHANGE); } else if( delta == 1 ) { - setCursorPos(getPos( line + page_size, offset )); - mScrollbar->setDocPos( mScrollbar->getDocPos() + page_size ); + mScroller->pageDown(PIXEL_OVERLAP_ON_PAGE_CHANGE); } - // put desired position into remember-buffer after setCursorPos() - mDesiredXPixel = desired_x_pixel; - - if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())) + if (getLocalRectFromDocIndex(mCursorPos) == cursor_rect) + { + // cursor didn't change apparent position, so move to top or bottom of document, respectively + if (delta < 0) + { + startOfDoc(); + } + else + { + endOfDoc(); + } + } + else { - mOnScrollEndCallback(mOnScrollEndData); + setCursorAtLocalPos(cursor_rect.getCenterX(), cursor_rect.getCenterY(), true, false); } } void LLTextEditor::changeLine( S32 delta ) { - bindEmbeddedChars(mGLFont); - S32 line, offset; getLineAndOffset( mCursorPos, &line, &offset ); - S32 line_start = getLineStart(line); - - // set desired x position to remembered previous position - S32 desired_x_pixel = mDesiredXPixel; - // if remembered position was reset (thus -1), calculate new one here - if( desired_x_pixel == -1 ) - { - LLWString text(getWText()); - desired_x_pixel = mGLFont->getWidth(text.c_str(), line_start, offset, mAllowEmbeddedItems ); - } - - S32 new_line = 0; + S32 new_line = line; if( (delta < 0) && (line > 0 ) ) { new_line = line - 1; } - else - if( (delta > 0) && (line < (getLineCount() - 1)) ) + else if( (delta > 0) && (line < (getLineCount() - 1)) ) { new_line = line + 1; } - else - { - unbindEmbeddedChars(mGLFont); - return; - } - - S32 num_lines = getLineCount(); - S32 new_line_start = getLineStart(new_line); - S32 new_line_end = getLength(); - if (new_line + 1 < num_lines) - { - new_line_end = getLineStart(new_line + 1) - 1; - } - S32 new_line_len = new_line_end - new_line_start; + LLRect visible_region = mScroller->getVisibleContentRect(); - S32 new_offset; - LLWString text(getWText()); - new_offset = mGLFont->charFromPixelOffset(text.c_str(), new_line_start, - (F32)desired_x_pixel, - (F32)mTextRect.getWidth(), - new_line_len, - mAllowEmbeddedItems); - - setCursorPos (getPos( new_line, new_offset )); - - // put desired position into remember-buffer after setCursorPos() - mDesiredXPixel = desired_x_pixel; - unbindEmbeddedChars(mGLFont); -} - -BOOL LLTextEditor::isScrolledToTop() -{ - return mScrollbar->isAtBeginning(); -} - -BOOL LLTextEditor::isScrolledToBottom() -{ - return mScrollbar->isAtEnd(); + S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mBottom + mTextRect.mBottom - visible_region.mBottom, TRUE); + setCursorPos(new_cursor_pos, true); } @@ -3383,32 +3408,11 @@ void LLTextEditor::setCursorAndScrollToEnd() { deselect(); endOfDoc(); - needsScroll(); } void LLTextEditor::getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap ) { - if( include_wordwrap ) - { - getLineAndOffset( mCursorPos, line, col ); - } - else - { - LLWString text = getWText(); - S32 line_count = 0; - S32 line_start = 0; - S32 i; - for( i = 0; text[i] && (i < position); i++ ) - { - if( '\n' == text[i] ) - { - line_start = i + 1; - line_count++; - } - } - *line = line_count; - *col = i - line_start; - } + getLineAndOffset( mCursorPos, line, col, include_wordwrap ); } void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap ) @@ -3444,64 +3448,39 @@ void LLTextEditor::endOfLine() } } -void LLTextEditor::endOfDoc() +void LLTextEditor::startOfDoc() { - mScrollbar->setDocPos(mScrollbar->getDocPosMax()); - mScrolledToBottom = true; + setCursorPos(0); +} - S32 len = getLength(); - if( len ) - { - setCursorPos(len); - } - if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())) - { - mOnScrollEndCallback(mOnScrollEndData); - } +void LLTextEditor::endOfDoc() +{ + setCursorPos(getLength()); } // Sets the scrollbar from the cursor position void LLTextEditor::updateScrollFromCursor() { - mScrollbar->setDocSize( getLineCount() ); - if (mReadOnly) { // no cursor in read only mode return; } - S32 line, offset; - getLineAndOffset( mCursorPos, &line, &offset ); - - S32 page_size = mScrollbar->getPageSize(); - - if( line < mScrollbar->getDocPos() ) - { - // scroll so that the cursor is at the top of the page - mScrollbar->setDocPos( line ); - } - else if( line >= mScrollbar->getDocPos() + page_size - 1 ) + if (!mScrollNeeded) { - S32 new_pos = 0; - if( line < mScrollbar->getDocSize() - 1 ) - { - // scroll so that the cursor is one line above the bottom of the page, - new_pos = line - page_size + 1; - } - else - { - // if there is less than a page of text remaining, scroll so that the cursor is at the bottom - new_pos = mScrollbar->getDocPosMax(); - } - mScrollbar->setDocPos( new_pos ); + return; } + mScrollNeeded = FALSE; - // Check if we've scrolled to bottom for callback if asked for callback - if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())) - { - mOnScrollEndCallback(mOnScrollEndData); - } + S32 line, offset; + getLineAndOffset( mCursorPos, &line, &offset ); + + // scroll so that the cursor is at the top of the page + LLRect scroller_doc_window = mScroller->getVisibleContentRect(); + LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos); + cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom); + mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5)); } void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -3513,13 +3492,6 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent) updateTextRect(); needsReflow(); - - // propagate shape information to scrollbar - mScrollbar->setDocSize( getLineCount() ); - - S32 line_height = llround( mGLFont->getLineHeight() ); - S32 page_lines = mTextRect.getHeight() / line_height; - mScrollbar->setPageSize( page_lines ); } void LLTextEditor::autoIndent() @@ -3564,7 +3536,7 @@ void LLTextEditor::insertText(const std::string &new_text) deleteSelection(TRUE); } - setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE )); + setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() )); needsReflow(); @@ -3585,17 +3557,23 @@ void LLTextEditor::appendColoredText(const std::string &new_text, highlight->parseFullLineHighlights(new_text, &lcolor); } - LLStyleSP style(new LLStyle); - style->setVisible(true); - style->setColor(lcolor); - style->setFontName(font_name); - appendStyledText(new_text, allow_undo, prepend_newline, style); + LLStyle::Params style_params; + style_params.color = lcolor; + if (font_name.empty()) + { + style_params.font = mDefaultFont; + } + else + { + style_params.font.name = font_name; + } + appendStyledText(new_text, allow_undo, prepend_newline, style_params); } void LLTextEditor::appendStyledText(const std::string &new_text, bool allow_undo, bool prepend_newline, - LLStyleSP stylep) + const LLStyle::Params& style_params) { S32 part = (S32)LLTextParser::WHOLE; if(mParseHTML) @@ -3605,14 +3583,10 @@ void LLTextEditor::appendStyledText(const std::string &new_text, std::string text = new_text; while ( findHTML(text, &start, &end) ) { - LLStyleSP html(new LLStyle); - html->setVisible(true); - html->setColor(mLinkColor); - if (stylep) - { - html->setFontName(stylep->getFontString()); - } - html->mUnderline = TRUE; + LLStyle::Params link_params = style_params; + link_params.color = mLinkColor; + link_params.font.style = "UNDERLINE"; + link_params.link_href = text.substr(start,end-start); if (start > 0) { @@ -3626,11 +3600,10 @@ void LLTextEditor::appendStyledText(const std::string &new_text, part = (S32)LLTextParser::MIDDLE; } std::string subtext=text.substr(0,start); - appendHighlightedText(subtext,allow_undo, prepend_newline, part, stylep); + appendHighlightedText(subtext,allow_undo, prepend_newline, part, style_params); } - html->setLinkHREF(text.substr(start,end-start)); - appendText(text.substr(start, end-start),allow_undo, prepend_newline, html); + appendText(text.substr(start, end-start),allow_undo, prepend_newline, link_params); if (end < (S32)text.length()) { text = text.substr(end,text.length() - end); @@ -3643,11 +3616,11 @@ void LLTextEditor::appendStyledText(const std::string &new_text, } } if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END; - if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, stylep); + if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, style_params); } else { - appendHighlightedText(new_text, allow_undo, prepend_newline, part, stylep); + appendHighlightedText(new_text, allow_undo, prepend_newline, part, style_params); } } @@ -3655,38 +3628,40 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text, bool allow_undo, bool prepend_newline, S32 highlight_part, - LLStyleSP stylep) + const LLStyle::Params& style_params) { if (mParseHighlights) { LLTextParser* highlight = LLTextParser::getInstance(); - if (highlight && stylep) + if (highlight && !style_params.isDefault()) { - LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), highlight_part); + LLStyle::Params highlight_params = style_params; + + LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), highlight_part); bool lprepend=prepend_newline; for (S32 i=0;isetColor(lcolor); + highlight_params.color = lcolor; if (i != 0 && (pieces.size() > 1) ) lprepend=FALSE; - appendText((std::string)pieces[i]["text"], allow_undo, lprepend, lstylep); + appendText((std::string)pieces[i]["text"], allow_undo, lprepend, highlight_params); } return; } } - appendText(new_text, allow_undo, prepend_newline, stylep); + appendText(new_text, allow_undo, prepend_newline, style_params); } // Appends new text to end of document void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, - const LLStyleSP stylep) + const LLStyle::Params& stylep) { + if (new_text.empty()) return; + // Save old state - BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); S32 selection_start = mSelectionStart; S32 selection_end = mSelectionEnd; BOOL was_selecting = mIsSelecting; @@ -3698,49 +3673,93 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool setCursorPos(old_length); + LLWString wide_text; + // Add carriage return if not first line if (getLength() != 0 && prepend_newline) { - std::string final_text = "\n"; - final_text += new_text; - append(utf8str_to_wstring(final_text), TRUE); + wide_text = utf8str_to_wstring(std::string("\n") + new_text); } else { - append(utf8str_to_wstring(new_text), TRUE ); + wide_text = utf8str_to_wstring(new_text); } - if (stylep) + LLTextSegmentPtr segmentp; + if (!stylep.isDefault()) { S32 segment_start = old_length; - S32 segment_end = getLength(); - LLTextSegment* segment = new LLTextSegment(stylep, segment_start, segment_end ); - mSegments.push_back(segment); + S32 segment_end = old_length + wide_text.size(); + segmentp = new LLNormalTextSegment(new LLStyle(stylep), segment_start, segment_end, *this ); } + + append(wide_text, TRUE, segmentp); needsReflow(); // Set the cursor and scroll position - // Maintain the scroll position unless the scroll was at the end of the doc (in which - // case, move it to the new end of the doc) or unless the user was doing actively selecting - if( was_scrolled_to_bottom && !was_selecting ) - { - if( selection_start != selection_end ) - { - // maintain an existing non-active selection - mSelectionStart = selection_start; - mSelectionEnd = selection_end; - } - endOfDoc(); - } - else if( selection_start != selection_end ) + if( selection_start != selection_end ) { mSelectionStart = selection_start; mSelectionEnd = selection_end; + mIsSelecting = was_selecting; + setCursorPos(cursor_pos); + } + else if( cursor_was_at_end ) + { + setCursorPos(getLength()); + } + else + { + setCursorPos(cursor_pos); + } + + if( !allow_undo ) + { + blockUndo(); + } +} + + +void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline) +{ + // Save old state + S32 selection_start = mSelectionStart; + S32 selection_end = mSelectionEnd; + BOOL was_selecting = mIsSelecting; + S32 cursor_pos = mCursorPos; + S32 old_length = getLength(); + BOOL cursor_was_at_end = (mCursorPos == old_length); + + deselect(); + + setCursorPos(old_length); + + LLWString widget_wide_text; + // Add carriage return if not first line + if (getLength() != 0 + && prepend_newline) + { + widget_wide_text = utf8str_to_wstring(std::string("\n") + widget_text); + } + else + { + widget_wide_text = utf8str_to_wstring(widget_text); + } + LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size()); + append(widget_wide_text, FALSE, segment); + + needsReflow(); + + // Set the cursor and scroll position + if( selection_start != selection_end ) + { + mSelectionStart = selection_start; + mSelectionEnd = selection_end; mIsSelecting = was_selecting; setCursorPos(cursor_pos); @@ -3767,26 +3786,79 @@ void LLTextEditor::removeTextFromEnd(S32 num_chars) remove(getLength() - num_chars, num_chars, FALSE); S32 len = getLength(); - mCursorPos = llclamp(mCursorPos, 0, len); + setCursorPos (llclamp(mCursorPos, 0, len)); mSelectionStart = llclamp(mSelectionStart, 0, len); mSelectionEnd = llclamp(mSelectionEnd, 0, len); - pruneSegments(); - - // pruneSegments will invalidate mLineStartList. - updateLineStartList(); + reflow(); needsScroll(); } /////////////////////////////////////////////////////////////////// // Returns change in number of characters in mWText -S32 LLTextEditor::insertStringNoUndo(const S32 pos, const LLWString &wstr) +S32 LLTextEditor::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextEditor::segment_vec_t* segments ) { - LLWString text(getWText()); + LLWString text(getWText()); S32 old_len = text.length(); // length() returns character length S32 insert_len = wstr.length(); + pos = getEditableIndex(pos, true); + + segment_set_t::iterator seg_iter = getSegIterContaining(pos); + + LLTextSegmentPtr default_segment; + + LLTextSegmentPtr segmentp; + if (seg_iter != mSegments.end()) + { + segmentp = *seg_iter; + } + else + { + //segmentp = mSegments.back(); + return pos; + } + + if (segmentp->canEdit()) + { + segmentp->setEnd(segmentp->getEnd() + insert_len); + if (seg_iter != mSegments.end()) + { + ++seg_iter; + } + } + else + { + // create default editable segment to hold new text + default_segment = new LLNormalTextSegment( getDefaultStyle(), pos, pos + insert_len, *this); + } + + // shift remaining segments to right + for(;seg_iter != mSegments.end(); ++seg_iter) + { + LLTextSegmentPtr segmentp = *seg_iter; + segmentp->setStart(segmentp->getStart() + insert_len); + segmentp->setEnd(segmentp->getEnd() + insert_len); + } + + // insert new segments + if (segments) + { + if (default_segment.notNull()) + { + // potentially overwritten by segments passed in + insertSegment(default_segment); + } + for (segment_vec_t::iterator seg_iter = segments->begin(); + seg_iter != segments->end(); + ++seg_iter) + { + LLTextSegment* segmentp = *seg_iter; + insertSegment(segmentp); + } + } + text.insert(pos, wstr); getViewModel()->setDisplay(text); @@ -3797,14 +3869,67 @@ S32 LLTextEditor::insertStringNoUndo(const S32 pos, const LLWString &wstr) insert_len = getLength() - old_len; } + onValueChange(pos, pos + insert_len); + return insert_len; } S32 LLTextEditor::removeStringNoUndo(S32 pos, S32 length) { LLWString text(getWText()); + segment_set_t::iterator seg_iter = getSegIterContaining(pos); + while(seg_iter != mSegments.end()) + { + LLTextSegmentPtr segmentp = *seg_iter; + S32 end = pos + length; + if (segmentp->getStart() < pos) + { + // deleting from middle of segment + if (segmentp->getEnd() > end) + { + segmentp->setEnd(segmentp->getEnd() - length); + } + // truncating segment + else + { + segmentp->setEnd(pos); + } + } + else if (segmentp->getStart() < end) + { + // deleting entire segment + if (segmentp->getEnd() <= end) + { + // remove segment + segmentp->unlinkFromDocument(this); + segment_set_t::iterator seg_to_erase(seg_iter++); + mSegments.erase(seg_to_erase); + continue; + } + // deleting head of segment + else + { + segmentp->setStart(pos); + segmentp->setEnd(segmentp->getEnd() - length); + } + } + else + { + // shifting segments backward to fill deleted portion + segmentp->setStart(segmentp->getStart() - length); + segmentp->setEnd(segmentp->getEnd() - length); + } + ++seg_iter; + } + text.erase(pos, length); getViewModel()->setDisplay(text); + + // recreate default segment in case we erased everything + createDefaultSegment(); + + onValueChange(pos, pos); + return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length } @@ -3817,6 +3942,9 @@ S32 LLTextEditor::overwriteCharNoUndo(S32 pos, llwchar wc) LLWString text(getWText()); text[pos] = wc; getViewModel()->setDisplay(text); + + onValueChange(pos, pos + 1); + return 1; } @@ -3887,21 +4015,25 @@ void LLTextEditor::updateTextRect() { static LLUICachedControl texteditor_border ("UITextEditorBorder", 0); static LLUICachedControl texteditor_h_pad ("UITextEditorHPad", 0); - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - static LLUICachedControl texteditor_vpad_top ("UITextEditorVPadTop", 0); - - mTextRect.setOriginAndSize( - texteditor_border + texteditor_h_pad, - texteditor_border, - getRect().getWidth() - scrollbar_size - 2 * (texteditor_border + texteditor_h_pad), - getRect().getHeight() - 2 * texteditor_border - texteditor_vpad_top ); + + LLRect old_text_rect = mTextRect; + mTextRect = mScroller->getContentWindowRect(); + mTextRect.stretch(texteditor_border * -1); + mTextRect.mLeft += texteditor_h_pad; + mTextRect.mLeft += mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0; + if (mTextRect != old_text_rect) + { + needsReflow(); + } } +LLFastTimer::DeclareTimer FTM_TEXT_EDITOR_LOAD_KEYWORD("Text Editor Load Keywords"); void LLTextEditor::loadKeywords(const std::string& filename, const std::vector& funcs, const std::vector& tooltips, const LLColor3& color) { + LLFastTimer ft(FTM_TEXT_EDITOR_LOAD_KEYWORD); if(mKeywords.loadFromFile(filename)) { S32 count = llmin(funcs.size(), tooltips.size()); @@ -3910,133 +4042,115 @@ void LLTextEditor::loadKeywords(const std::string& filename, std::string name = utf8str_trim(funcs[i]); mKeywords.addToken(LLKeywordToken::WORD, name, color, tooltips[i] ); } + segment_vec_t segment_list; + mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); - mKeywords.findSegments( &mSegments, getWText(), mDefaultColor.get() ); - - llassert( mSegments.front()->getStart() == 0 ); - llassert( mSegments.back()->getEnd() == getLength() ); + mSegments.clear(); + segment_set_t::iterator insert_it = mSegments.begin(); + for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) + { + insert_it = mSegments.insert(insert_it, *list_it); + } } } -void LLTextEditor::updateSegments() +void LLTextEditor::createDefaultSegment() { - if (mKeywords.isLoaded()) - { - // HACK: No non-ascii keywords for now - mKeywords.findSegments(&mSegments, getWText(), mDefaultColor.get()); - } - else if (mAllowEmbeddedItems) - { - findEmbeddedItemSegments(); - } - - // Make sure we have at least one segment - if (mSegments.size() == 1 && mSegments[0]->getIsDefault()) - { - delete mSegments[0]; - mSegments.clear(); // create default segment - } + // ensures that there is always at least one segment if (mSegments.empty()) { - LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() ); - LLTextSegment* default_segment = new LLTextSegment( text_color, 0, getLength() ); - default_segment->setIsDefault(TRUE); - mSegments.push_back(default_segment); + LLTextSegmentPtr default_segment = new LLNormalTextSegment( getDefaultStyle(), 0, getLength() + 1, *this); + mSegments.insert(default_segment); + default_segment->linkToDocument(this); } } -// Only effective if text was removed from the end of the editor -// *NOTE: Using this will invalidate references to mSegments from mLineStartList. -void LLTextEditor::pruneSegments() +LLStyleSP LLTextEditor::getDefaultStyle() { - S32 len = getLength(); - // Find and update the first valid segment - segment_list_t::iterator iter = mSegments.end(); - while(iter != mSegments.begin()) - { - --iter; - LLTextSegment* seg = *iter; - if (seg->getStart() < len) - { - // valid segment - if (seg->getEnd() > len) - { - seg->setEnd(len); - } - break; // done - } - } - if (iter != mSegments.end()) - { - // erase invalid segments - ++iter; - std::for_each(iter, mSegments.end(), DeletePointer()); - mSegments.erase(iter, mSegments.end()); - } - else - { - llwarns << "Tried to erase end of empty LLTextEditor" << llendl; - } + LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() ); + return LLStyleSP(new LLStyle(LLStyle::Params().color(text_color).font(mDefaultFont))); } -void LLTextEditor::findEmbeddedItemSegments() +LLFastTimer::DeclareTimer FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments"); +void LLTextEditor::updateSegments() { - mHoverSegment = NULL; - std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); - mSegments.clear(); - - BOOL found_embedded_items = FALSE; - LLWString text = getWText(); - S32 idx = 0; - while( text[idx] ) + LLFastTimer ft(FTM_UPDATE_TEXT_SEGMENTS); + if (mKeywords.isLoaded()) { - if( text[idx] >= FIRST_EMBEDDED_CHAR && text[idx] <= LAST_EMBEDDED_CHAR ) - { - found_embedded_items = TRUE; - break; + // HACK: No non-ascii keywords for now + segment_vec_t segment_list; + mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); + + mSegments.clear(); + segment_set_t::iterator insert_it = mSegments.begin(); + for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) + { + insert_it = mSegments.insert(insert_it, *list_it); } - ++idx; } - if( !found_embedded_items ) + createDefaultSegment(); + +} + +void LLTextEditor::insertSegment(LLTextSegmentPtr segment_to_insert) +{ + if (segment_to_insert.isNull()) { return; } - S32 text_len = text.length(); - - BOOL in_text = FALSE; - - LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() ); + segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart()); - if( idx > 0 ) + if (cur_seg_iter == mSegments.end()) { - mSegments.push_back( new LLTextSegment( text_color, 0, text_len ) ); // text - in_text = TRUE; + mSegments.insert(segment_to_insert); + segment_to_insert->linkToDocument(this); } - - LLStyleSP embedded_style(new LLStyle); - embedded_style->setIsEmbeddedItem( TRUE ); - - // Start with i just after the first embedded item - while ( text[idx] ) + else { - if( text[idx] >= FIRST_EMBEDDED_CHAR && text[idx] <= LAST_EMBEDDED_CHAR ) + LLTextSegmentPtr cur_segmentp = *cur_seg_iter; + if (cur_segmentp->getStart() < segment_to_insert->getStart()) { - if( in_text ) - { - mSegments.back()->setEnd( idx ); - } - mSegments.push_back( new LLTextSegment( embedded_style, idx, idx + 1 ) ); // item - in_text = FALSE; + S32 old_segment_end = cur_segmentp->getEnd(); + // split old at start point for new segment + cur_segmentp->setEnd(segment_to_insert->getStart()); + // advance to next segment + ++cur_seg_iter; + // insert remainder of old segment + LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this); + cur_seg_iter = mSegments.insert(cur_seg_iter, remainder_segment); + remainder_segment->linkToDocument(this); + // insert new segment before remainder of old segment + cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert); + + segment_to_insert->linkToDocument(this); + // move to "remanider" segment and start truncation there + ++cur_seg_iter; } else - if( !in_text ) { - mSegments.push_back( new LLTextSegment( text_color, idx, text_len ) ); // text - in_text = TRUE; + cur_seg_iter = mSegments.insert(cur_seg_iter, segment_to_insert); + ++cur_seg_iter; + segment_to_insert->linkToDocument(this); + } + + // now delete/truncate remaining segments as necessary + while(cur_seg_iter != mSegments.end()) + { + cur_segmentp = *cur_seg_iter; + if (cur_segmentp->getEnd() <= segment_to_insert->getEnd()) + { + cur_segmentp->unlinkFromDocument(this); + segment_set_t::iterator seg_to_erase(cur_seg_iter++); + mSegments.erase(seg_to_erase); + } + else + { + cur_segmentp->setStart(segment_to_insert->getEnd()); + break; + } } - ++idx; } } @@ -4050,9 +4164,9 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask) if (mParseHTML && mHTML.length() > 0) { //Special handling for slurls - if ( (mSecondlifeURLcallback!=NULL) && !(*mSecondlifeURLcallback)(mHTML) ) + if ( (sSecondlifeURLcallback!=NULL) && !(*sSecondlifeURLcallback)(mHTML) ) { - if (mURLcallback!=NULL) (*mURLcallback)(mHTML); + if (sURLcallback!=NULL) (*sURLcallback)(mHTML); } mHTML.clear(); } @@ -4063,44 +4177,37 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask) // Finds the text segment (if any) at the give local screen position -const LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const +LLTextSegmentPtr LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) { // Find the cursor position at the requested local screen position - S32 offset = getCursorPosFromLocalCoord( x, y, FALSE ); - S32 idx = getSegmentIdxAtOffset(offset); - return idx >= 0 ? mSegments[idx] : NULL; -} - -const LLTextSegment* LLTextEditor::getSegmentAtOffset(S32 offset) const -{ - S32 idx = getSegmentIdxAtOffset(offset); - return idx >= 0 ? mSegments[idx] : NULL; -} - -S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset) const -{ - if (mSegments.empty() || offset < 0 || offset >= getLength()) + S32 offset = getDocIndexFromLocalCoord( x, y, FALSE ); + segment_set_t::iterator seg_iter = getSegIterContaining(offset); + if (seg_iter != mSegments.end()) { - return -1; + return *seg_iter; } else { - S32 segidx, segoff; - getSegmentAndOffset(offset, &segidx, &segoff); - return segidx; + return LLTextSegmentPtr(); } } -void LLTextEditor::onMouseCaptureLost() +LLTextEditor::segment_set_t::iterator LLTextEditor::getSegIterContaining(S32 index) { - endSelection(); + segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index)); + return it; +} + +LLTextEditor::segment_set_t::const_iterator LLTextEditor::getSegIterContaining(S32 index) const +{ + LLTextEditor::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index)); + return it; } -void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdata) + +void LLTextEditor::onMouseCaptureLost() { - mOnScrollEndCallback = callback; - mOnScrollEndData = userdata; - mScrollbar->setOnScrollEndCallback(callback, userdata); + endSelection(); } /////////////////////////////////////////////////////////////////// @@ -4186,7 +4293,7 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length ) delete[] text; - setCursorPos(0); + startOfDoc(); deselect(); needsReflow(); @@ -4207,74 +4314,6 @@ BOOL LLTextEditor::exportBuffer(std::string &buffer ) return TRUE; } -////////////////////////////////////////////////////////////////////////// -// LLTextSegment - -LLTextSegment::LLTextSegment(S32 start) : - mStart(start), - mEnd(0), - mToken(NULL), - mIsDefault(FALSE) -{ -} -LLTextSegment::LLTextSegment( const LLStyleSP& style, S32 start, S32 end ) : - mStyle( style ), - mStart( start), - mEnd( end ), - mToken(NULL), - mIsDefault(FALSE) -{ -} -LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible) : - mStyle(new LLStyle(is_visible,color,LLStringUtil::null)), - mStart( start), - mEnd( end ), - mToken(NULL), - mIsDefault(FALSE) -{ -} -LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end ) : - mStyle(new LLStyle(TRUE, color,LLStringUtil::null )), - mStart( start), - mEnd( end ), - mToken(NULL), - mIsDefault(FALSE) -{ -} -LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) : - mStyle(new LLStyle(TRUE, color,LLStringUtil::null )), - mStart( start), - mEnd( end ), - mToken(NULL), - mIsDefault(FALSE) -{ -} - -BOOL LLTextSegment::getToolTip(std::string& msg) const -{ - if (mToken && !mToken->getToolTip().empty()) - { - const LLWString& wmsg = mToken->getToolTip(); - msg = wstring_to_utf8str(wmsg); - return TRUE; - } - return FALSE; -} - - - -void LLTextSegment::dump() const -{ - llinfos << "Segment [" << -// mColor.mV[VX] << ", " << -// mColor.mV[VY] << ", " << -// mColor.mV[VZ] << "]\t[" << - mStart << ", " << - getEnd() << "]" << - llendl; - -} - /////////////////////////////////////////////////////////////////// // Refactoring note: We may eventually want to replace this with boost::regex or // boost::tokenizer capabilities since we've already fixed at least two JIRAs @@ -4473,7 +4512,7 @@ void LLTextEditor::resetPreedit() deselect(); } - mCursorPos = mPreeditPositions.front(); + setCursorPos(mPreeditPositions.front()); removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos); insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString); @@ -4557,7 +4596,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect return FALSE; } - const S32 first_visible_line = mScrollbar->getDocPos(); + const S32 first_visible_line = getFirstVisibleLine(); if (query < getLineStart(first_visible_line)) { return FALSE; @@ -4583,11 +4622,11 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect const LLWString textString(getWText()); const llwchar * const text = textString.c_str(); - const S32 line_height = llround(mGLFont->getLineHeight()); + const S32 line_height = llround(mDefaultFont->getLineHeight()); if (coord) { - const S32 query_x = mTextRect.mLeft + mGLFont->getWidth(text, current_line_start, query - current_line_start, mAllowEmbeddedItems); + const S32 query_x = mTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start); const S32 query_y = mTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2; S32 query_screen_x, query_screen_y; localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y); @@ -4599,17 +4638,17 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect S32 preedit_left = mTextRect.mLeft; if (preedit_left_position > current_line_start) { - preedit_left += mGLFont->getWidth(text, current_line_start, preedit_left_position - current_line_start, mAllowEmbeddedItems); + preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start); } S32 preedit_right = mTextRect.mLeft; if (preedit_right_position < current_line_end) { - preedit_right += mGLFont->getWidth(text, current_line_start, preedit_right_position - current_line_start, mAllowEmbeddedItems); + preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start); } else { - preedit_right += mGLFont->getWidth(text, current_line_start, current_line_end - current_line_start, mAllowEmbeddedItems); + preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start); } const S32 preedit_top = mTextRect.mTop - (current_line - first_visible_line) * line_height; @@ -4686,10 +4725,267 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length) S32 LLTextEditor::getPreeditFontSize() const { - return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround(mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); } LLWString LLTextEditor::getWText() const { return getViewModel()->getDisplay(); } + +void LLTextEditor::onValueChange(S32 start, S32 end) +{ +} + +// +// LLTextSegment +// + +LLTextSegment::~LLTextSegment() +{} + +S32 LLTextSegment::getWidth(S32 first_char, S32 num_chars) const { return 0; } +S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; } +S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; } +void LLTextSegment::updateLayout(const LLTextEditor& editor) {} +F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { return draw_rect.mLeft; } +S32 LLTextSegment::getMaxHeight() const { return 0; } +bool LLTextSegment::canEdit() const { return false; } +void LLTextSegment::unlinkFromDocument(LLTextEditor*) {} +void LLTextSegment::linkToDocument(LLTextEditor*) {} +void LLTextSegment::setHasMouseHover(bool hover) {} +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::setToken( LLKeywordToken* token ) {} +LLKeywordToken* LLTextSegment::getToken() const { return NULL; } +BOOL LLTextSegment::getToolTip( std::string& msg ) const { return FALSE; } +void LLTextSegment::dump() const {} + + +// +// LLNormalTextSegment +// + +LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextEditor& editor ) +: LLTextSegment(start, end), + mStyle( style ), + mToken(NULL), + mHasMouseHover(false), + mEditor(editor) +{ + mMaxHeight = llceil(mStyle->getFont()->getLineHeight()); +} + +LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextEditor& editor, BOOL is_visible) +: LLTextSegment(start, end), + mToken(NULL), + mHasMouseHover(false), + mEditor(editor) +{ + mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color)); + + mMaxHeight = llceil(mStyle->getFont()->getLineHeight()); +} + +F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) +{ + if( end - start > 0 ) + { + if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart)) + { + S32 style_image_height = mStyle->mImageHeight; + S32 style_image_width = mStyle->mImageWidth; + LLUIImagePtr image = mStyle->getImage(); + image->draw(draw_rect.mLeft, draw_rect.mTop-style_image_height, + style_image_width, style_image_height); + } + + return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect.mLeft, draw_rect.mBottom); + } + return draw_rect.mLeft; +} + +// Draws a single text segment, reversing the color for selection if needed. +F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y) +{ + const LLWString &text = mEditor.getWText(); + + F32 right_x = x; + if (!mStyle->isVisible()) + { + return right_x; + } + + const LLFontGL* font = mStyle->getFont(); + + LLColor4 color = mStyle->getColor(); + + font = mStyle->getFont(); + + if( selection_start > seg_start ) + { + // Draw normally + S32 start = seg_start; + S32 end = llmin( selection_start, seg_end ); + S32 length = end - start; + font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems()); + } + x = right_x; + + if( (selection_start < seg_end) && (selection_end > seg_start) ) + { + // Draw reversed + S32 start = llmax( selection_start, seg_start ); + S32 end = llmin( selection_end, seg_end ); + S32 length = end - start; + + font->render(text, start, x, y, + LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), + LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems()); + } + x = right_x; + if( selection_end < seg_end ) + { + // Draw normally + S32 start = llmax( selection_end, seg_start ); + S32 end = seg_end; + S32 length = end - start; + font->render(text, start, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, length, S32_MAX, &right_x, mEditor.allowsEmbeddedItems()); + } + return right_x; +} + +S32 LLNormalTextSegment::getMaxHeight() const +{ + return mMaxHeight; +} + +BOOL LLNormalTextSegment::getToolTip(std::string& msg) const +{ + if (mToken && !mToken->getToolTip().empty()) + { + const LLWString& wmsg = mToken->getToolTip(); + msg = wstring_to_utf8str(wmsg); + return TRUE; + } + return FALSE; +} + + +S32 LLNormalTextSegment::getWidth(S32 first_char, S32 num_chars) const +{ + LLWString text = mEditor.getWText(); + return mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); +} + +S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const +{ + LLWString text = mEditor.getWText(); + return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset, + (F32)segment_local_x_coord, + F32_MAX, + num_chars, + round); +} + +S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +{ + LLWString text = mEditor.getWText(); + S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart, + (F32)num_pixels, + max_chars, + mEditor.getWordWrap()); + + if (num_chars == 0 + && line_offset == 0 + && max_chars > 0) + { + // If at the beginning of a line, and a single character won't fit, draw it anyway + num_chars = 1; + } + if (mStart + segment_offset + num_chars == mEditor.getLength()) + { + // include terminating NULL + num_chars++; + } + return num_chars; +} + +void LLNormalTextSegment::dump() const +{ + llinfos << "Segment [" << +// mColor.mV[VX] << ", " << +// mColor.mV[VY] << ", " << +// mColor.mV[VZ] << "]\t[" << + mStart << ", " << + getEnd() << "]" << + llendl; +} + +// +// LLInlineViewSegment +// + +LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end) +: LLTextSegment(start, end), + mView(view) +{ +} + +LLInlineViewSegment::~LLInlineViewSegment() +{ + mView->die(); +} + +S32 LLInlineViewSegment::getWidth(S32 first_char, S32 num_chars) const +{ + if (first_char == 0 && num_chars == 0) + { + return 0; + } + else + { + return mView->getRect().getWidth(); + } +} + +S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +{ + if (line_offset != 0 && num_pixels < mView->getRect().getWidth()) + { + return 0; + } + else + { + return mEnd - mStart; + } +} + +void LLInlineViewSegment::updateLayout(const LLTextEditor& editor) +{ + LLRect start_rect = editor.getLocalRectFromDocIndex(mStart); + LLRect doc_rect = editor.getDocumentPanel()->getRect(); + mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom); +} + +F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) +{ + return (F32)(draw_rect.mLeft + mView->getRect().getWidth()); +} + +S32 LLInlineViewSegment::getMaxHeight() const +{ + return mView->getRect().getHeight(); +} + +void LLInlineViewSegment::unlinkFromDocument(LLTextEditor* editor) +{ + editor->removeDocumentChild(mView); +} + +void LLInlineViewSegment::linkToDocument(LLTextEditor* editor) +{ + editor->addDocumentChild(mView); +} diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 0babd7ba58..67c67d0f67 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -53,6 +53,101 @@ class LLScrollbar; class LLKeywordToken; class LLTextCmd; class LLUICtrlFactory; +class LLScrollContainer; + +class LLTextSegment : public LLRefCount +{ +public: + LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){}; + virtual ~LLTextSegment(); + + virtual S32 getWidth(S32 first_char, S32 num_chars) const; + virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; + virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; + virtual void updateLayout(const class LLTextEditor& editor); + virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); + virtual S32 getMaxHeight() const; + virtual bool canEdit() const; + virtual void unlinkFromDocument(class LLTextEditor* editor); + virtual void linkToDocument(class LLTextEditor* editor); + + virtual void setHasMouseHover(bool hover); + virtual const LLColor4& getColor() const; + virtual void setColor(const LLColor4 &color); + virtual const LLStyleSP getStyle() const; + virtual void setStyle(const LLStyleSP &style); + virtual void setToken( LLKeywordToken* token ); + virtual LLKeywordToken* getToken() const; + virtual BOOL getToolTip( std::string& msg ) const; + virtual void dump() const; + + S32 getStart() const { return mStart; } + void setStart(S32 start) { mStart = start; } + S32 getEnd() const { return mEnd; } + void setEnd( S32 end ) { mEnd = end; } + +protected: + S32 mStart; + S32 mEnd; +}; + +class LLNormalTextSegment : public LLTextSegment +{ +public: + LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextEditor& editor ); + LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextEditor& editor, BOOL is_visible = TRUE); + + /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const; + /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; + /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; + /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); + /*virtual*/ S32 getMaxHeight() const; + /*virtual*/ bool canEdit() const { return true; } + /*virtual*/ void setHasMouseHover(bool hover) { mHasMouseHover = hover; } + /*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*/ void setToken( LLKeywordToken* token ) { mToken = token; } + /*virtual*/ LLKeywordToken* getToken() const { return mToken; } + /*virtual*/ BOOL getToolTip( std::string& msg ) const; + /*virtual*/ void dump() const; + +protected: + F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, F32 x, F32 y); + + class LLTextEditor& mEditor; + LLStyleSP mStyle; + S32 mMaxHeight; + LLKeywordToken* mToken; + bool mHasMouseHover; +}; + +typedef LLPointer LLTextSegmentPtr; + +class LLInlineViewSegment : public LLTextSegment +{ +public: + LLInlineViewSegment(LLView* widget, S32 start, S32 end); + ~LLInlineViewSegment(); + /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const; + /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; + /*virtual*/ void updateLayout(const class LLTextEditor& editor); + /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); + /*virtuaL*/ S32 getMaxHeight() const; + /*virtual*/ bool canEdit() const { return false; } + /*virtual*/ void unlinkFromDocument(class LLTextEditor* editor); + /*virtual*/ void linkToDocument(class LLTextEditor* editor); + +private: + LLView* mView; +}; + +class LLIndexSegment : public LLTextSegment +{ +public: + LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {} +}; class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor { @@ -64,12 +159,13 @@ public: Optional read_only, embedded_items, - hide_scrollbar, word_wrap, ignore_tab, hide_border, track_bottom, - takes_non_scroll_clicks; + handle_edit_keys_directly, + show_line_numbers, + commit_on_focus_lost; //colors Optional cursor_color, @@ -78,13 +174,15 @@ public: text_readonly_color, bg_readonly_color, bg_writeable_color, - bg_focus_color; + bg_focus_color, + link_color; Optional border; Ignored type, length, - is_unicode; + is_unicode, + hide_scrollbar; Params(); }; @@ -101,6 +199,17 @@ public: static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff; static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1; + + struct compare_segment_end + { + bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const + { + return a->getEnd() < b->getEnd(); + } + }; + + typedef std::multiset segment_set_t; + virtual ~LLTextEditor(); void setParseHTML(BOOL parsing) {mParseHTML=parsing;} @@ -110,7 +219,6 @@ public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask ); virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask); @@ -128,14 +236,15 @@ public: virtual void draw(); virtual void onFocusReceived(); virtual void onFocusLost(); + virtual void onCommit(); virtual void setEnabled(BOOL enabled); // uictrl overrides - virtual void onTabInto(); virtual void clear(); virtual void setFocus( BOOL b ); virtual BOOL acceptsTextInput() const; - virtual BOOL isDirty() const { return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) ); } + virtual BOOL isDirty() const { return isPristine(); } + virtual void setValue(const LLSD& value); // LLEditMenuHandler interface virtual void undo(); @@ -162,9 +271,12 @@ public: virtual void deselect(); virtual BOOL canDeselect() const; + virtual void onValueChange(S32 start, S32 end); + void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE); void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive); + BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); } // Undo/redo stack void blockUndo(); @@ -173,12 +285,20 @@ public: virtual void makePristine(); BOOL isPristine() const; BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } + BOOL getWordWrap() { return mWordWrap; } + S32 getLength() const { return getWText().length(); } + void setReadOnly(bool read_only) { mReadOnly = read_only; } + bool getReadOnly() { return mReadOnly; } + + // + // Text manipulation + // // inserts text at cursor void insertText(const std::string &text); // appends text at end void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline, - const LLStyleSP stylep = NULL); + const LLStyle::Params& style = LLStyle::Params()); void appendColoredText(const std::string &wtext, bool allow_undo, bool prepend_newline, @@ -187,19 +307,24 @@ public: // if styled text starts a line, you need to prepend a newline. void appendStyledText(const std::string &new_text, bool allow_undo, bool prepend_newline, - LLStyleSP stylep = NULL); + const LLStyle::Params& style); void appendHighlightedText(const std::string &new_text, bool allow_undo, bool prepend_newline, S32 highlight_part, - LLStyleSP stylep); - + const LLStyle::Params& style); + void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline); + // Non-undoable + void setText(const LLStringExplicit &utf8str); + void setWText(const LLWString &wtext); + + // Removes text from the end of document // Does not change highlight or cursor position. void removeTextFromEnd(S32 num_chars); BOOL tryToRevertToPristineState(); - void setCursor(S32 row, S32 column); - void setCursorPos(S32 offset); + bool setCursor(S32 row, S32 column); + bool setCursorPos(S32 offset, bool keep_cursor_offset = false); void setCursorAndScrollToEnd(); void getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap ); @@ -214,90 +339,57 @@ public: LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); } LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); } - // Color support - void setCursorColor(const LLColor4& c) { mCursorColor = c; } - void setFgColor( const LLColor4& c ) { mFgColor = c; } - void setTextDefaultColor( const LLColor4& c ) { mDefaultColor = c; } - void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; } - void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; } - void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; } - void setTrackColor( const LLColor4& color ); - void setThumbColor( const LLColor4& color ); - // Hacky methods to make it into a word-wrapping, potentially scrolling, // read-only text box. - void setBorderVisible(BOOL b); - BOOL isBorderVisible() const; - void setTakesNonScrollClicks(BOOL b) { mTakesNonScrollClicks = b; } - void setHideScrollbarForShortDocs(BOOL b); - - void setWordWrap( BOOL b ); - void setTabsToNextField(BOOL b) { mTabsToNextField = b; } - BOOL tabsToNextField() const { return mTabsToNextField; } void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; } // Hack to handle Notecards virtual BOOL importBuffer(const char* buffer, S32 length ); virtual BOOL exportBuffer(std::string& buffer ); - // If takes focus, will take keyboard focus on click. - void setTakesFocus(BOOL b) { mTakesFocus = b; } + const class DocumentPanel* getDocumentPanel() const { return mDocumentPanel; } - void setSourceID(const LLUUID& id) { mSourceID = id; } const LLUUID& getSourceID() const { return mSourceID; } - void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; } - // Callbacks - static void setLinkColor(LLColor4 color) { mLinkColor = color; } static void setURLCallbacks(void (*callback1) (const std::string& url), bool (*callback2) (const std::string& url), bool (*callback3) (const std::string& url) ) - { mURLcallback = callback1; mSecondlifeURLcallback = callback2; mSecondlifeURLcallbackRightClick = callback3;} - - void setOnScrollEndCallback(void (*callback)(void*), void* userdata); - - // new methods - void setValue(const LLSD& value); + { sURLcallback = callback1; sSecondlifeURLcallback = callback2; sSecondlifeURLcallbackRightClick = callback3;} std::string getText() const; - // Non-undoable - void setText(const LLStringExplicit &utf8str); - void setWText(const LLWString &wtext); - - // Returns byte length limit - S32 getMaxLength() const { return mMaxTextByteLength; } - - // Change cursor - void startOfLine(); - void endOfLine(); - void endOfDoc(); - - BOOL isScrolledToTop(); - BOOL isScrolledToBottom(); - // Getters LLWString getWText() const; llwchar getWChar(S32 pos) const { return getWText()[pos]; } LLWString getWSubString(S32 pos, S32 len) const { return getWText().substr(pos, len); } - const LLTextSegment* getCurrentSegment() const { return getSegmentAtOffset(mCursorPos); } - const LLTextSegment* getPreviousSegment() const; - void getSelectedSegments(std::vector& segments) const; + typedef std::vector segment_vec_t; + + const LLTextSegmentPtr getPreviousSegment() const; + void getSelectedSegments(segment_vec_t& segments) const; + + void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const; + LLRect getLocalRectFromDocIndex(S32 index) const; - static bool isPartOfWord(llwchar c) { return (c == '_') || LLStringOps::isAlnum((char)c); } + void addDocumentChild(LLView* view); + void removeDocumentChild(LLView* view); protected: - // - // Methods - // + // Change cursor + void startOfLine(); + void endOfLine(); + void startOfDoc(); + void endOfDoc(); - S32 getLength() const { return getWText().length(); } - void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const; + 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 ) ; void drawPreeditMarker(); - void updateLineStartList(S32 startpos = 0); + void needsReflow() { mReflowNeeded = TRUE; } + void needsScroll() { mScrollNeeded = TRUE; } + void updateCursorXPos(); + void updateScrollFromCursor(); void updateTextRect(); const LLRect& getTextRect() const { return mTextRect; } @@ -306,16 +398,16 @@ protected: BOOL truncate(); // Returns true if truncation occurs void removeCharOrTab(); - void setCursorAtLocalPos(S32 x, S32 y, BOOL round); - S32 getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const; + void setCursorAtLocalPos(S32 x, S32 y, bool round, bool keep_cursor_offset = false); + S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const; void indentSelectedLines( S32 spaces ); S32 indentLine( S32 pos, S32 spaces ); void unindentLineBeforeCloseBrace(); - S32 getSegmentIdxAtOffset(S32 offset) const; - const LLTextSegment* getSegmentAtLocalPos(S32 x, S32 y) const; - const LLTextSegment* getSegmentAtOffset(S32 offset) const; + LLTextSegmentPtr getSegmentAtLocalPos(S32 x, S32 y); + segment_set_t::iterator getSegIterContaining(S32 index); + segment_set_t::const_iterator getSegIterContaining(S32 index) const; void reportBadKeystroke() { make_ui_sound("UISndBadKeystroke"); } @@ -325,7 +417,6 @@ protected: BOOL handleControlKey(const KEY key, const MASK mask); BOOL handleEditKey(const KEY key, const MASK mask); - BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); } BOOL selectionContainsLineBreaks(); void startSelection(); void endSelection(); @@ -334,9 +425,10 @@ protected: S32 prevWordPos(S32 cursorPos) const; S32 nextWordPos(S32 cursorPos) const; - S32 getLineCount() const { return mLineStartList.size(); } + S32 getLineCount() const { return mLineInfoList.size(); } S32 getLineStart( S32 line ) const; - void getLineAndOffset(S32 pos, S32* linep, S32* offsetp) const; + S32 getLineHeight( S32 line ) const; + void getLineAndOffset(S32 pos, S32* linep, S32* offsetp, bool include_wordwrap = true) const; S32 getPos(S32 line, S32 offset); void changePage(S32 delta); @@ -344,13 +436,13 @@ protected: void autoIndent(); - void findEmbeddedItemSegments(); + void findEmbeddedItemSegments(S32 start, S32 end); + void insertSegment(LLTextSegmentPtr segment_to_insert); + virtual BOOL handleMouseUpOverSegment(S32 x, S32 y, MASK mask); virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } - virtual void bindEmbeddedChars(const LLFontGL* font) const {} - virtual void unbindEmbeddedChars(const LLFontGL* font) const {} S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const; BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const; @@ -361,7 +453,15 @@ protected: class LLTextCmd { public: - LLTextCmd( S32 pos, BOOL group_with_next ) : mPos(pos), mGroupWithNext(group_with_next) {} + LLTextCmd( S32 pos, BOOL group_with_next, LLTextSegmentPtr segment = LLTextSegmentPtr() ) + : mPos(pos), + mGroupWithNext(group_with_next) + { + if (segment.notNull()) + { + mSegments.push_back(segment); + } + } virtual ~LLTextCmd() {} virtual BOOL execute(LLTextEditor* editor, S32* delta) = 0; virtual S32 undo(LLTextEditor* editor) = 0; @@ -372,16 +472,17 @@ protected: virtual BOOL hasExtCharValue( llwchar value ) const { return FALSE; } // Defined here so they can access protected LLTextEditor editing methods - S32 insert(LLTextEditor* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr ); } + S32 insert(LLTextEditor* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr, &mSegments ); } S32 remove(LLTextEditor* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); } S32 overwrite(LLTextEditor* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); } S32 getPosition() const { return mPos; } BOOL groupWithNext() const { return mGroupWithNext; } - private: - const S32 mPos; - BOOL mGroupWithNext; + protected: + const S32 mPos; + BOOL mGroupWithNext; + segment_vec_t mSegments; }; // Here's the method that takes and applies text commands. S32 execute(LLTextCmd* cmd); @@ -392,12 +493,12 @@ protected: S32 overwriteChar(S32 pos, llwchar wc); void removeChar(); S32 removeChar(S32 pos); - S32 insert(const S32 pos, const LLWString &wstr, const BOOL group_with_next_op); - S32 remove(const S32 pos, const S32 length, const BOOL group_with_next_op); - S32 append(const LLWString &wstr, const BOOL group_with_next_op); + S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment); + S32 remove(S32 pos, S32 length, bool group_with_next_op); + S32 append(const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment); // Direct operations - S32 insertStringNoUndo(S32 pos, const LLWString &wstr); // returns num of chars actually inserted + S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted S32 removeStringNoUndo(S32 pos, S32 length); S32 overwriteCharNoUndo(S32 pos, llwchar wc); @@ -441,22 +542,38 @@ protected: BOOL mParseHighlights; std::string mHTML; - typedef std::vector segment_list_t; - segment_list_t mSegments; - const LLTextSegment* mHoverSegment; + segment_set_t mSegments; + LLTextSegmentPtr mHoverSegment; // Scrollbar data - class LLScrollbar* mScrollbar; - BOOL mHideScrollbarForShortDocs; - BOOL mTakesNonScrollClicks; - void (*mOnScrollEndCallback)(void*); + class DocumentPanel* mDocumentPanel; + LLScrollContainer* mScroller; + void *mOnScrollEndData; LLWString mPreeditWString; LLWString mPreeditOverwrittenWString; std::vector mPreeditPositions; std::vector mPreeditStandouts; - + + S32 mScrollIndex; // index into document that controls default scroll position + +protected: + LLUIColor mCursorColor; + LLUIColor mFgColor; + LLUIColor mDefaultColor; + LLUIColor mReadOnlyFgColor; + LLUIColor mWriteableBgColor; + LLUIColor mReadOnlyBgColor; + LLUIColor mFocusBgColor; + LLUIColor mLinkColor; + + BOOL mReadOnly; + BOOL mWordWrap; + BOOL mShowLineNumbers; + + void updateSegments(); + private: // @@ -465,32 +582,28 @@ private: void pasteHelper(bool is_primary); virtual LLTextViewModel* getViewModel() const; - - void updateSegments(); - void pruneSegments(); + void reflow(S32 startpos = 0); + + void clearSegments(); + void createDefaultSegment(); + LLStyleSP getDefaultStyle(); + S32 getEditableIndex(S32 index, bool increasing_direction); void drawBackground(); void drawSelectionBackground(); void drawCursor(); void drawText(); - void drawClippedSegment(const LLWString &wtext, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyleSP& color, F32* right_x); - - void needsReflow() - { - mReflowNeeded = TRUE; - // cursor might have moved, need to scroll - mScrollNeeded = TRUE; - } - void needsScroll() { mScrollNeeded = TRUE; } + void drawLineNumbers(); + + S32 getFirstVisibleLine() const; // // Data // LLKeywords mKeywords; - static LLUIColor mLinkColor; - static void (*mURLcallback) (const std::string& url); - static bool (*mSecondlifeURLcallback) (const std::string& url); - static bool (*mSecondlifeURLcallbackRightClick) (const std::string& url); + static void (*sURLcallback) (const std::string& url); + static bool (*sSecondlifeURLcallback) (const std::string& url); + static bool (*sSecondlifeURLcallbackRightClick) (const std::string& url); // Concrete LLTextCmd sub-classes used by the LLTextEditor base class class LLTextCmdInsert; @@ -500,7 +613,7 @@ private: S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes - const LLFontGL* mGLFont; + const LLFontGL* mDefaultFont; class LLViewBorder* mBorder; @@ -515,49 +628,35 @@ private: S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be LLRect mTextRect; // The rect in which text is drawn. Excludes borders. // List of offsets and segment index of the start of each line. Always has at least one node (0). - struct pred; struct line_info { - line_info(S32 segment, S32 offset) : mSegment(segment), mOffset(offset) {} - S32 mSegment; - S32 mOffset; - }; - struct line_info_compare - { - bool operator()(const line_info& a, const line_info& b) const - { - if (a.mSegment < b.mSegment) - return true; - else if (a.mSegment > b.mSegment) - return false; - else - return a.mOffset < b.mOffset; - } + line_info(S32 index_start, S32 index_end, S32 top, S32 bottom, S32 line_num) + : mDocIndexStart(index_start), + mDocIndexEnd(index_end), + mTop(top), + mBottom(bottom), + mLineNum(line_num) + {} + S32 mDocIndexStart; + S32 mDocIndexEnd; + S32 mTop; + S32 mBottom; + S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap) }; + struct compare_bottom; + struct compare_top; + struct line_end_compare; typedef std::vector line_list_t; - line_list_t mLineStartList; + line_list_t mLineInfoList; BOOL mReflowNeeded; BOOL mScrollNeeded; LLFrameTimer mKeystrokeTimer; - LLUIColor mCursorColor; - LLUIColor mFgColor; - LLUIColor mDefaultColor; - LLUIColor mReadOnlyFgColor; - LLUIColor mWriteableBgColor; - LLUIColor mReadOnlyBgColor; - LLUIColor mFocusBgColor; - - BOOL mReadOnly; - BOOL mWordWrap; - BOOL mShowLineNumbers; - BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces BOOL mCommitOnFocusLost; BOOL mTakesFocus; BOOL mTrackBottom; // if true, keeps scroll position at bottom during resize - BOOL mScrolledToBottom; BOOL mAllowEmbeddedItems; @@ -571,47 +670,4 @@ private: }; // end class LLTextEditor - -class LLTextSegment -{ -public: - // for creating a compare value - LLTextSegment(S32 start); - LLTextSegment( const LLStyleSP& style, S32 start, S32 end ); - LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible); - LLTextSegment( const LLColor4& color, S32 start, S32 end ); - LLTextSegment( const LLColor3& color, S32 start, S32 end ); - - S32 getStart() const { return mStart; } - S32 getEnd() const { return mEnd; } - void setEnd( S32 end ) { mEnd = end; } - const LLColor4& getColor() const { return mStyle->getColor(); } - void setColor(const LLColor4 &color) { mStyle->setColor(color); } - const LLStyleSP& getStyle() const { return mStyle; } - void setStyle(const LLStyleSP &style) { mStyle = style; } - void setIsDefault(BOOL b) { mIsDefault = b; } - BOOL getIsDefault() const { return mIsDefault; } - void setToken( LLKeywordToken* token ) { mToken = token; } - LLKeywordToken* getToken() const { return mToken; } - BOOL getToolTip( std::string& msg ) const; - - void dump() const; - - struct compare - { - bool operator()(const LLTextSegment* a, const LLTextSegment* b) const - { - return a->mStart < b->mStart; - } - }; - -private: - LLStyleSP mStyle; - S32 mStart; - S32 mEnd; - LLKeywordToken* mToken; - BOOL mIsDefault; -}; - - #endif // LL_TEXTEDITOR_ diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index fab8f61356..7e4df892c4 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -71,9 +71,6 @@ // const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f); -// Used to hide the flashing text cursor when window doesn't have focus. -BOOL gShowTextEditCursor = TRUE; - // Language for UI construction std::map gTranslation; std::list gUntranslated; @@ -1898,6 +1895,12 @@ void LLScreenClipRect::pushClipRect(const LLRect& rect) { LLRect top = sClipRectStack.top(); combined_clip_rect.intersectWith(top); + + if(combined_clip_rect.isEmpty()) + { + // avoid artifacts where zero area rects show up as lines + combined_clip_rect = LLRect::null; + } } sClipRectStack.push(combined_clip_rect); } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index b1943a7b02..1f9b0b2dbc 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -151,9 +151,6 @@ inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled ); } -// Used to hide the flashing text cursor when window doesn't have focus. -extern BOOL gShowTextEditCursor; - class LLImageProviderInterface; typedef void (*LLUIAudioCallback)(const LLUUID& uuid); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 8aa7540446..4a9fec3191 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -278,24 +278,46 @@ void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask) { mMouseLeaveSignal(this, getValue()); } + //virtual -BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask){ +BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask) +{ BOOL handled = LLView::handleMouseDown(x,y,mask); mMouseDownSignal(this,x,y,mask); return handled; } + //virtual -BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask){ +BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ BOOL handled = LLView::handleMouseUp(x,y,mask); mMouseUpSignal(this,x,y,mask); return handled; } + +//virtual +BOOL LLUICtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLView::handleRightMouseDown(x,y,mask); + mRightMouseDownSignal(this,x,y,mask); + return handled; +} + //virtual -BOOL LLUICtrl::handleRightMouseUp(S32 x, S32 y, MASK mask){ +BOOL LLUICtrl::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ BOOL handled = LLView::handleRightMouseUp(x,y,mask); - mRightClickSignal(this,x,y,mask); + mRightMouseUpSignal(this,x,y,mask); return handled; } + +// can't tab to children of a non-tab-stop widget +BOOL LLUICtrl::canFocusChildren() const +{ + return hasTabStop(); +} + + void LLUICtrl::onCommit() { mCommitSignal(this, getValue()); diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 6ba3b01fcb..a4f539af14 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -186,8 +186,10 @@ public: /*virtual*/ BOOL getTentative() const; /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL canFocusChildren() const; /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); // From LLFocusableElement @@ -258,7 +260,8 @@ public: boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ) { return mMouseDownSignal.connect(cb); } boost::signals2::connection setMouseUpCallback( const mouse_signal_t::slot_type& cb ) { return mMouseUpSignal.connect(cb); } - boost::signals2::connection setRightClickedCallback( const mouse_signal_t::slot_type& cb ) { return mRightClickSignal.connect(cb); } + boost::signals2::connection setRightMouseDownCallback( const mouse_signal_t::slot_type& cb ) { return mRightMouseDownSignal.connect(cb); } + boost::signals2::connection setRightMouseUpCallback( const mouse_signal_t::slot_type& cb ) { return mRightMouseUpSignal.connect(cb); } // *TODO: Deprecate; for backwards compatability only: boost::signals2::connection setCommitCallback( boost::function cb, void* data); @@ -292,7 +295,8 @@ protected: mouse_signal_t mMouseDownSignal; mouse_signal_t mMouseUpSignal; - mouse_signal_t mRightClickSignal; + mouse_signal_t mRightMouseDownSignal; + mouse_signal_t mRightMouseUpSignal; LLViewModelPtr mViewModel; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 2bbede8c13..1161101f90 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -45,31 +45,7 @@ #include "llquaternion.h" // this library includes -#include "llbutton.h" -#include "llcheckboxctrl.h" -//#include "llcolorswatch.h" -#include "llcombobox.h" -#include "llcontrol.h" -#include "lldir.h" -#include "llevent.h" #include "llfloater.h" -#include "lliconctrl.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llradiogroup.h" -#include "llscrollcontainer.h" -#include "llscrollingpanellist.h" -#include "llscrolllistctrl.h" -#include "llslider.h" -#include "llsliderctrl.h" -#include "llmultislider.h" -#include "llmultisliderctrl.h" -#include "llspinctrl.h" -#include "lltabcontainer.h" -#include "lltextbox.h" -#include "lltexteditor.h" -#include "llui.h" -#include "llviewborder.h" LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction"); LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams"); @@ -149,7 +125,7 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const wid } -LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing"); +static LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing"); //----------------------------------------------------------------------------- // getLayeredXMLNode() //----------------------------------------------------------------------------- @@ -177,14 +153,14 @@ bool LLUICtrlFactory::getLocalizedXMLNode(const std::string &xui_filename, LLXML } } -static LLFastTimer::DeclareTimer BUILD_FLOATERS("Build Floaters"); +static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters"); //----------------------------------------------------------------------------- // buildFloater() //----------------------------------------------------------------------------- void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, LLXMLNodePtr output_node) { - LLFastTimer timer(BUILD_FLOATERS); + LLFastTimer timer(FTM_BUILD_FLOATERS); LLXMLNodePtr root; //if exporting, only load the language being exported, @@ -248,14 +224,14 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename) return 0; } -static LLFastTimer::DeclareTimer BUILD_PANELS("Build Panels"); +static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels"); //----------------------------------------------------------------------------- // buildPanel() //----------------------------------------------------------------------------- BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, LLXMLNodePtr output_node) { - LLFastTimer timer(BUILD_PANELS); + LLFastTimer timer(FTM_BUILD_PANELS); BOOL didPost = FALSE; LLXMLNodePtr root; @@ -317,7 +293,7 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, L //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget"); +static LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget"); LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node) { diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 0ba028e1c8..e2dc85d03f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1300,6 +1300,11 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask) } void LLView::draw() +{ + drawChildren(); +} + +void LLView::drawChildren() { if (sDebugRects) { @@ -1329,7 +1334,7 @@ void LLView::draw() { // Only draw views that are within the root view localRectToScreen(viewp->getRect(),&screenRect); - if ( rootRect.rectInRect(&screenRect) ) + if ( rootRect.overlaps(screenRect) ) { glMatrixMode(GL_MODELVIEW); LLUI::pushMatrix(); @@ -1540,7 +1545,7 @@ void LLView::updateBoundingRect() LLRect child_bounding_rect = childp->getBoundingRect(); - if (local_bounding_rect.isNull()) + if (local_bounding_rect.isEmpty()) { // start out with bounding rect equal to first visible child's bounding rect local_bounding_rect = child_bounding_rect; @@ -1548,7 +1553,7 @@ void LLView::updateBoundingRect() else { // accumulate non-null children rectangles - if (!child_bounding_rect.isNull()) + if (!child_bounding_rect.isEmpty()) { local_bounding_rect.unionWith(child_bounding_rect); } @@ -1639,7 +1644,7 @@ BOOL LLView::hasAncestor(const LLView* parentp) const BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const { - LLView *child = getChildView(childname, TRUE, FALSE); + LLView *child = findChildView(childname, TRUE); if (child) { return gFocusMgr.childHasKeyboardFocus(child); @@ -1654,13 +1659,27 @@ BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const BOOL LLView::hasChild(const std::string& childname, BOOL recurse) const { - return getChildView(childname, recurse, FALSE) != NULL; + return findChildView(childname, recurse) != NULL; } //----------------------------------------------------------------------------- // getChildView() //----------------------------------------------------------------------------- -LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const +LLView* LLView::getChildView(const std::string& name, BOOL recurse) const +{ + LLView* child = findChildView(name, recurse); + if (!child) + { + child = getDefaultWidget(name); + if (!child) + { + child = LLUICtrlFactory::createDefaultWidget(name); + } + } + return child; +} + +LLView* LLView::findChildView(const std::string& name, BOOL recurse) const { //richard: should we allow empty names? //if(name.empty()) @@ -1681,23 +1700,13 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) { LLView* childp = *child_it; - LLView* viewp = childp->getChildView(name, recurse, FALSE); + LLView* viewp = childp->findChildView(name, recurse); if ( viewp ) { return viewp; } } } - - if (create_if_missing) - { - LLView* view = getDefaultWidget(name); - if (!view) - { - view = LLUICtrlFactory::createDefaultWidget(name); - } - return view; - } return NULL; } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index ee49276139..6247bf036c 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -213,6 +213,9 @@ protected: LLView(const LLView::Params&); friend class LLUICtrlFactory; +private: + // widgets in general are not copyable + LLView(const LLView& other) {}; public: #if LL_DEBUG static BOOL sIsDrawing; @@ -421,6 +424,7 @@ public: virtual std::string getShowNamesToolTip(); virtual void draw(); + void drawChildren(); void parseFollowsFlags(const LLView::Params& params); @@ -484,19 +488,20 @@ public: template T* findChild(const std::string& name, BOOL recurse = TRUE) const { - LLView* child = getChildView(name, recurse, FALSE); + LLView* child = findChildView(name, recurse); T* result = dynamic_cast(child); return result; } - template T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; + template T* getChild(const std::string& name, BOOL recurse = TRUE) const; template T& getChildRef(const std::string& name, BOOL recurse = TRUE) const { - return *getChild(name, recurse, TRUE); + return *getChild(name, recurse); } - virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; + virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const; + virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const; template T* getDefaultWidget(const std::string& name) const { @@ -636,9 +641,9 @@ private: LLView::child_tab_order_t mTabOrder; }; -template T* LLView::getChild(const std::string& name, BOOL recurse, BOOL create_if_missing) const +template T* LLView::getChild(const std::string& name, BOOL recurse) const { - LLView* child = getChildView(name, recurse, FALSE); + LLView* child = findChildView(name, recurse); T* result = dynamic_cast(child); if (!result) { @@ -647,28 +652,25 @@ template T* LLView::getChild(const std::string& name, BOOL recurse, BO { llwarns << "Found child named " << name << " but of wrong type " << typeid(child).name() << ", expecting " << typeid(T*).name() << llendl; } - if (create_if_missing) + result = getDefaultWidget(name); + if (!result) { - result = getDefaultWidget(name); - if (!result) + result = LLUICtrlFactory::getDefaultWidget(name); + + if (result) { - result = LLUICtrlFactory::getDefaultWidget(name); - - if (result) - { - // *NOTE: You cannot call mFoo = getChild("bar") - // in a floater or panel constructor. The widgets will not - // be ready. Instead, put it in postBuild(). - llwarns << "Making dummy " << typeid(T).name() << " named \"" << name << "\" in " << getName() << llendl; - } - else - { - llwarns << "Failed to create dummy " << typeid(T).name() << llendl; - return NULL; - } - - getDefaultWidgetMap()[name] = result; + // *NOTE: You cannot call mFoo = getChild("bar") + // in a floater or panel constructor. The widgets will not + // be ready. Instead, put it in postBuild(). + llwarns << "Making dummy " << typeid(T).name() << " named \"" << name << "\" in " << getName() << llendl; } + else + { + llwarns << "Failed to create dummy " << typeid(T).name() << llendl; + return NULL; + } + + getDefaultWidgetMap()[name] = result; } } return result; diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp index 860aa3302e..f41c98f7b3 100644 --- a/indra/llui/llviewborder.cpp +++ b/indra/llui/llviewborder.cpp @@ -134,9 +134,7 @@ void LLViewBorder::draw() } } - // draw the children - LLView::draw(); - + drawChildren(); } void LLViewBorder::drawOnePixelLines() diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index 6b1563bab1..5fdf41188d 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -44,6 +44,8 @@ const S32 LLVFile::WRITE = 0x00000002; const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE +static LLFastTimer::DeclareTimer FTM_VFILE_WAIT("VFile Wait"); + //---------------------------------------------------------------------------- LLVFSThread* LLVFile::sVFSThread = NULL; BOOL LLVFile::sAllocdVFSThread = FALSE; @@ -318,7 +320,7 @@ BOOL LLVFile::setMaxSize(S32 size) if (!mVFS->checkAvailable(size)) { - LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT); + LLFastTimer t(FTM_VFILE_WAIT); S32 count = 0; while (sVFSThread->getPending() > 1000) { @@ -426,7 +428,7 @@ bool LLVFile::isLocked(EVFSLock lock) void LLVFile::waitForLock(EVFSLock lock) { - LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT); + LLFastTimer t(FTM_VFILE_WAIT); // spin until the lock clears while (isLocked(lock)) { diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index ce1bc82168..9936b24292 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1645,6 +1645,9 @@ void LLWindowWin32::gatherInput() mMousePositionModified = FALSE; } +static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard"); +static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse"); + LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA); @@ -1878,7 +1881,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_KEYUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); - LLFastTimer t2(LLFastTimer::FTM_KEYHANDLER); + LLFastTimer t2(FTM_KEYHANDLER); if (gDebugWindowProc) { @@ -1987,7 +1990,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONDOWN: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); - LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER); + LLFastTimer t2(FTM_MOUSEHANDLER); if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); @@ -2051,7 +2054,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); - LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER); + LLFastTimer t2(FTM_MOUSEHANDLER); //if (gDebugClicks) //{ // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; @@ -2085,7 +2088,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_RBUTTONDOWN: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN"); - LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER); + LLFastTimer t2(FTM_MOUSEHANDLER); if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); @@ -2119,7 +2122,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_RBUTTONUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP"); - LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER); + LLFastTimer t2(FTM_MOUSEHANDLER); // Because we move the cursor position in the app, we need to query // to find out where the cursor at the time the event is handled. // If we don't do this, many clicks could get buffered up, and if the @@ -2149,7 +2152,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // case WM_MBUTTONDBLCLK: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); - LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER); + LLFastTimer t2(FTM_MOUSEHANDLER); if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); @@ -2183,7 +2186,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MBUTTONUP: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); - LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER); + LLFastTimer t2(FTM_MOUSEHANDLER); // Because we move the cursor position in tllviewerhe app, we need to query // to find out where the cursor at the time the event is handled. // If we don't do this, many clicks could get buffered up, and if the diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 0864940866..7d94601568 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -96,7 +96,7 @@ typedef enum e_control_type TYPE_COUNT } eControlType; -class LLControlVariable : public LLRefCount, boost::noncopyable +class LLControlVariable : public LLRefCount { friend class LLControlGroup; diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index cb56049ae2..a1d0831939 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -430,6 +430,7 @@ namespace LLInitParam const Param* getLastChangedParam() const { return mLastChangedParam ? getParamFromHandle(mLastChangedParam) : NULL; } S32 getLastChangeVersion() const { return mChangeVersion; } + bool isDefault() const { return mChangeVersion == 0; } bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack); bool serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const; diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp index db7421575c..2efc475f57 100644 --- a/indra/llxuixml/lltrans.cpp +++ b/indra/llxuixml/lltrans.cpp @@ -169,3 +169,28 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil:: } } +//static +bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) +{ + LLFastTimer timer(FTM_GET_TRANS); + + template_map_t::iterator iter = sStringTemplates.find(xml_desc); + if (iter != sStringTemplates.end()) + { + std::string text = iter->second.mText; + LLStringUtil::format_map_t args = sDefaultArgs; + args.insert(msg_args.begin(), msg_args.end()); + LLStringUtil::format(text, args); + result = text; + return true; + } + else + { + LLSD args; + args["STRING_NAME"] = xml_desc; + LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; + //LLNotifications::instance().add("MissingString", args); + + return false; + } +} diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h index 6423c88245..340d70e434 100644 --- a/indra/llxuixml/lltrans.h +++ b/indra/llxuixml/lltrans.h @@ -78,6 +78,7 @@ public: * @returns Translated string */ static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); + static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args); /** * @brief Returns a translated string @@ -89,7 +90,14 @@ public: LLStringUtil::format_map_t empty; return getString(xml_desc, empty); } - + + static bool findString(std::string &result, const std::string &xml_desc) + { + LLStringUtil::format_map_t empty; + return findString(result, xml_desc, empty); + } + + // get the default args static const LLStringUtil::format_map_t& getDefaultArgs() { diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index e1f61906e2..e28e52fd16 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -399,11 +399,11 @@ LLXUIParser::LLXUIParser() boost::bind(&LLXUIParser::writeSDValue, this, _1, _2)); } -static LLFastTimer::DeclareTimer PARSE_XUI("XUI Parsing"); +static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing"); void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent) { - LLFastTimer timer(PARSE_XUI); + LLFastTimer timer(FTM_PARSE_XUI); mNameStack.clear(); mCurReadDepth = 0; setParseSilently(silent); diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index 05fee9a419..d7f445d3d8 100644 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -4280,7 +4280,6 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) } { - // LLFastTimer time_in_libraries1(LLFastTimer::FTM_TEMP7); gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id); } add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse); @@ -4351,7 +4350,6 @@ BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &i } { - // LLFastTimer time_in_libraries2(LLFastTimer::FTM_TEMP8); gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id); } add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5045f18784..fe9eae04a1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -290,9 +290,9 @@ static std::set default_trans_args; void init_default_trans_args() { default_trans_args.insert("SECOND_LIFE"); // World - default_trans_args.insert("SECOND_LIFE_VIEWER"); + default_trans_args.insert("APP_NAME"); default_trans_args.insert("SECOND_LIFE_GRID"); - default_trans_args.insert("SECOND_LIFE_SUPPORT"); + default_trans_args.insert("SUPPORT_SITE"); } //---------------------------------------------------------------------------- @@ -863,6 +863,11 @@ bool LLAppViewer::init() return true; } +static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages"); +static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); +static LLFastTimer::DeclareTimer FTM_IDLE("Idle"); +static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); + bool LLAppViewer::mainLoop() { LLMemType mt1(LLMemType::MTYPE_MAIN); @@ -905,7 +910,7 @@ bool LLAppViewer::mainLoop() if (gViewerWindow) { - LLFastTimer t2(LLFastTimer::FTM_MESSAGES); + LLFastTimer t2(FTM_MESSAGES); gViewerWindow->mWindow->processMiscNativeEvents(); } @@ -913,7 +918,7 @@ bool LLAppViewer::mainLoop() if (gViewerWindow) { - LLFastTimer t2(LLFastTimer::FTM_MESSAGES); + LLFastTimer t2(FTM_MESSAGES); if (!restoreErrorTrap()) { llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl; @@ -963,14 +968,14 @@ bool LLAppViewer::mainLoop() { pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! - LLFastTimer t3(LLFastTimer::FTM_IDLE); + LLFastTimer t3(FTM_IDLE); idle(); if (gAres != NULL && gAres->isInitialized()) { LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP); pingMainloopTimeout("Main:ServicePump"); - LLFastTimer t4(LLFastTimer::FTM_PUMP); + LLFastTimer t4(FTM_PUMP); gAres->process(); // this pump is necessary to make the login screen show up gServicePump->pump(); @@ -1007,7 +1012,7 @@ bool LLAppViewer::mainLoop() // Sleep and run background threads { LLMemType mt_sleep(LLMemType::MTYPE_SLEEP); - LLFastTimer t2(LLFastTimer::FTM_SLEEP); + LLFastTimer t2(FTM_SLEEP); bool run_multiple_threads = gSavedSettings.getBOOL("RunMultipleThreads"); // yield some time to the os based on command line option @@ -2025,7 +2030,7 @@ bool LLAppViewer::initConfiguration() #if LL_DARWIN // Initialize apple menubar and various callbacks - init_apple_menu(LLTrans::getString("SECOND_LIFE_VIEWER").c_str()); + init_apple_menu(LLTrans::getString("APP_NAME").c_str()); #if __ppc__ // If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further. @@ -2064,7 +2069,7 @@ bool LLAppViewer::initConfiguration() // // Set the name of the window // - gWindowTitle = LLTrans::getString("SECOND_LIFE_VIEWER"); + gWindowTitle = LLTrans::getString("APP_NAME"); #if LL_DEBUG gWindowTitle += std::string(" [DEBUG] ") + gArgs; #else @@ -2181,7 +2186,7 @@ void LLAppViewer::checkForCrash(void) { std::ostringstream msg; msg << LLTrans::getString("MBFrozenCrashed"); - std::string alert = LLTrans::getString("SECOND_LIFE_VIEWER") + " " + LLTrans::getString("MBAlert"); + std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert"); choice = OSMessageBox(msg.str(), alert, OSMB_YESNO); @@ -2391,7 +2396,7 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; // Dump some debugging info - LL_INFOS("SystemInfo") << LLTrans::getString("SECOND_LIFE_VIEWER") + LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") << " version " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << LL_ENDL; @@ -3069,7 +3074,7 @@ void LLAppViewer::purgeCache() std::string LLAppViewer::getSecondLifeTitle() const { - return LLTrans::getString("SECOND_LIFE_VIEWER"); + return LLTrans::getString("APP_NAME"); } std::string LLAppViewer::getWindowTitle() const @@ -3234,6 +3239,15 @@ public: } }; +static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio"); +static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup"); +static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks"); +static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD"); +static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist"); +static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region"); +static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World"); +static LLFastTimer::DeclareTimer FTM_NETWORK("Network"); + /////////////////////////////////////////////////////// // idle() // @@ -3300,7 +3314,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(LLFastTimer::FTM_NETWORK); + LLFastTimer t(FTM_NETWORK); // Update spaceserver timeinfo LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC)); @@ -3381,7 +3395,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(LLFastTimer::FTM_NETWORK); + LLFastTimer t(FTM_NETWORK); //////////////////////////////////////////////// // @@ -3410,7 +3424,7 @@ void LLAppViewer::idle() // { -// LLFastTimer t(LLFastTimer::FTM_IDLE_CB); +// LLFastTimer t(FTM_IDLE_CB); // Do event notifications if necessary. Yes, we may want to move this elsewhere. gEventNotifier.update(); @@ -3445,7 +3459,7 @@ void LLAppViewer::idle() } { - LLFastTimer t(LLFastTimer::FTM_OBJECTLIST_UPDATE); // Actually "object update" + LLFastTimer t(FTM_OBJECTLIST_UPDATE); // Actually "object update" if (!(logoutRequestSent() && hasSavedFinalSnapshot())) { @@ -3460,7 +3474,7 @@ void LLAppViewer::idle() // { - LLFastTimer t(LLFastTimer::FTM_CLEANUP); + LLFastTimer t(FTM_CLEANUP); gObjectList.cleanDeadObjects(); LLDrawable::cleanupDeadDrawables(); } @@ -3492,7 +3506,7 @@ void LLAppViewer::idle() // { - LLFastTimer t(LLFastTimer::FTM_NETWORK); + LLFastTimer t(FTM_NETWORK); gVLManager.unpackData(); } @@ -3504,7 +3518,7 @@ void LLAppViewer::idle() LLWorld::getInstance()->updateVisibilities(); { const F32 max_region_update_time = .001f; // 1ms - LLFastTimer t(LLFastTimer::FTM_REGION_UPDATE); + LLFastTimer t(FTM_REGION_UPDATE); LLWorld::getInstance()->updateRegions(max_region_update_time); } @@ -3551,7 +3565,7 @@ void LLAppViewer::idle() if (!gNoRender) { - LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE); + LLFastTimer t(FTM_WORLD_UPDATE); gPipeline.updateMove(); LLWorld::getInstance()->updateParticles(); @@ -3574,12 +3588,12 @@ void LLAppViewer::idle() // objects and camera should be in sync, do LOD calculations now { - LLFastTimer t(LLFastTimer::FTM_LOD_UPDATE); + LLFastTimer t(FTM_LOD_UPDATE); gObjectList.updateApparentAngles(gAgent); } { - LLFastTimer t(LLFastTimer::FTM_AUDIO_UPDATE); + LLFastTimer t(FTM_AUDIO_UPDATE); if (gAudiop) { @@ -3719,6 +3733,8 @@ void LLAppViewer::sendLogoutRequest() static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; #endif +static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Network"); + void LLAppViewer::idleNetwork() { LLMemType mt_in(LLMemType::MTYPE_IDLE_NETWORK); @@ -3731,7 +3747,7 @@ void LLAppViewer::idleNetwork() if (!gSavedSettings.getBOOL("SpeedTest")) { - LLFastTimer t(LLFastTimer::FTM_IDLE_NETWORK); // decode + LLFastTimer t(FTM_IDLE_NETWORK); // decode // deal with any queued name requests and replies. gCacheName->processPending(); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index a85f8710c7..f557adf6a6 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -200,7 +200,7 @@ BOOL LLAvatarList::update(const std::vector& all_buddies, const std::str // Changed item in place, need to request sort and update columns // because we might have changed data in a column on which the user // has already sorted. JC - sortItems(); + updateSort(); // re-select items selectMultiple(selected_ids); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 2687feb68b..2403e891f6 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -164,7 +164,7 @@ void LLBottomTray::setVisible(BOOL visible) { LLPanel::setVisible(visible); - // *NOTE: we must check mToolbarStack against NULL because sewtVisible is called from the + // *NOTE: we must check mToolbarStack against NULL because setVisible is called from the // LLPanel::initFromParams BEFORE postBuild is called and child controls are not exist yet if (NULL != mToolbarStack) { diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 7a118deb8a..bea11ecfeb 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -103,10 +103,6 @@ LLChatBar::LLChatBar() mObserver(NULL) { setIsChrome(TRUE); - -#if !LL_RELEASE_FOR_DOWNLOAD - childDisplayNotFound(); -#endif } @@ -125,7 +121,7 @@ BOOL LLChatBar::postBuild() // * NOTE: mantipov: getChild with default parameters returns dummy widget. // Seems this class will be completle removed // attempt to bind to an existing combo box named gesture - setGestureCombo(getChild( "Gesture", TRUE, FALSE)); + setGestureCombo(findChild( "Gesture")); mInputEditor = getChild("Chat Editor"); mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke, this); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 45b322e106..05c574b154 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -93,13 +93,11 @@ void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) caption->reshape( width - 4, caption_rect.getHeight(), 1); caption->setRect(caption_rect); - LLRect msg_text_rect = msg_text->getRect(); msg_text_rect.setLeftTopAndSize( msg_left_offset, height - caption_rect.getHeight() , width - msg_left_offset - msg_right_offset, height - caption_rect.getHeight()); msg_text->reshape( width - msg_left_offset - msg_right_offset, height - caption_rect.getHeight(), 1); msg_text->setRect(msg_text_rect); } - } BOOL LLChatItemCtrl::postBuild() diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp index 933d9b8771..9399e1f68d 100644 --- a/indra/newview/llchatmsgbox.cpp +++ b/indra/newview/llchatmsgbox.cpp @@ -371,7 +371,7 @@ void LLChatMsgBox::drawText( S32 x, S32 y, const LLColor4& color ) mHAlign, mVAlign, mFontStyle, mShadowType, - line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses ); + line_length, getRect().getWidth(), NULL, mUseEllipses ); cur_pos += line_length + 1; y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index d8bd32382f..7cc78aff92 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -60,6 +60,9 @@ const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; const F32 OBJECT_DAMPING_TIME_CONSTANT = 0.06f; const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; +static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); + + //////////////////////// // // Inline implementations. @@ -188,7 +191,7 @@ BOOL LLDrawable::isLight() const void LLDrawable::cleanupReferences() { - LLFastTimer t(LLFastTimer::FTM_PIPELINE); + LLFastTimer t(FTM_PIPELINE); std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); mFaces.clear(); @@ -1033,7 +1036,7 @@ void LLSpatialBridge::updateSpatialExtents() LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); { - LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); + LLFastTimer ftm(FTM_CULL_REBOUND); root->rebound(); } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 940e1fc968..c765980c30 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -63,7 +63,6 @@ class LLViewerTexture; // Can have multiple silhouettes for each object const U32 SILHOUETTE_HIGHLIGHT = 0; - // All data for new renderer goes into this class. class LLDrawable : public LLRefCount { diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 267f83f295..de97e2406d 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -90,7 +90,7 @@ void LLDrawPoolAlpha::endDeferredPass(S32 pass) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f); { - LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLFastTimer t(FTM_RENDER_GRASS); gDeferredTreeProgram.bind(); LLGLEnable test(GL_ALPHA_TEST); //render alpha masked objects @@ -112,7 +112,7 @@ S32 LLDrawPoolAlpha::getNumPostDeferredPasses() void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + LLFastTimer t(FTM_RENDER_ALPHA); simple_shader = &gDeferredAlphaProgram; fullbright_shader = &gDeferredFullbrightProgram; @@ -139,7 +139,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) void LLDrawPoolAlpha::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + LLFastTimer t(FTM_RENDER_ALPHA); if (LLPipeline::sUnderWaterRender) { @@ -163,7 +163,7 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) void LLDrawPoolAlpha::endRenderPass( S32 pass ) { - LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + LLFastTimer t(FTM_RENDER_ALPHA); LLRenderPass::endRenderPass(pass); if(gPipeline.canUseWindLightShaders()) @@ -174,7 +174,7 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass ) void LLDrawPoolAlpha::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + LLFastTimer t(FTM_RENDER_ALPHA); LLGLSPipelineAlpha gls_pipeline_alpha; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index b15cd0b0dc..a2d8c965ec 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -89,12 +89,13 @@ S32 AVATAR_OFFSET_TEX0 = 32; S32 AVATAR_OFFSET_TEX1 = 40; S32 AVATAR_VERTEX_BYTES = 48; - BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; +static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); + LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) { @@ -154,7 +155,7 @@ S32 LLDrawPoolAvatar::getNumDeferredPasses() void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + LLFastTimer t(FTM_RENDER_CHARACTERS); if (LLPipeline::sImpostorRender) { @@ -178,7 +179,7 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) void LLDrawPoolAvatar::endDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + LLFastTimer t(FTM_RENDER_CHARACTERS); if (LLPipeline::sImpostorRender) { @@ -248,7 +249,7 @@ S32 LLDrawPoolAvatar::getNumShadowPasses() void LLDrawPoolAvatar::beginShadowPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + LLFastTimer t(FTM_SHADOW_AVATAR); sVertexProgram = &gDeferredAvatarShadowProgram; if (sShaderLevel > 0) @@ -270,7 +271,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) void LLDrawPoolAvatar::endShadowPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + LLFastTimer t(FTM_SHADOW_AVATAR); if (sShaderLevel > 0) { @@ -284,7 +285,7 @@ void LLDrawPoolAvatar::endShadowPass(S32 pass) void LLDrawPoolAvatar::renderShadow(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + LLFastTimer t(FTM_SHADOW_AVATAR); if (mDrawFace.empty()) { @@ -320,7 +321,7 @@ S32 LLDrawPoolAvatar::getNumPasses() void LLDrawPoolAvatar::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + LLFastTimer t(FTM_RENDER_CHARACTERS); if (LLPipeline::sImpostorRender) { renderAvatars(NULL, 2); @@ -332,7 +333,7 @@ void LLDrawPoolAvatar::render(S32 pass) void LLDrawPoolAvatar::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + LLFastTimer t(FTM_RENDER_CHARACTERS); //reset vertex buffer mappings LLVertexBuffer::unbind(); @@ -358,7 +359,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) void LLDrawPoolAvatar::endRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + LLFastTimer t(FTM_RENDER_CHARACTERS); if (LLPipeline::sImpostorRender) { diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 971949e885..2cb4d5d6d5 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -74,6 +74,7 @@ const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEX U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY; + static LLGLSLShader* shader = NULL; static S32 cube_channel = -1; static S32 diffuse_channel = -1; @@ -220,7 +221,7 @@ S32 LLDrawPoolBump::getNumPasses() void LLDrawPoolBump::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer t(FTM_RENDER_BUMP); switch( pass ) { case 0: @@ -247,7 +248,7 @@ void LLDrawPoolBump::beginRenderPass(S32 pass) void LLDrawPoolBump::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer t(FTM_RENDER_BUMP); if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE)) { @@ -280,7 +281,7 @@ void LLDrawPoolBump::render(S32 pass) void LLDrawPoolBump::endRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer t(FTM_RENDER_BUMP); switch( pass ) { case 0: @@ -308,7 +309,7 @@ void LLDrawPoolBump::endRenderPass(S32 pass) //static void LLDrawPoolBump::beginShiny(bool invisible) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + LLFastTimer t(FTM_RENDER_SHINY); if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { @@ -383,7 +384,7 @@ void LLDrawPoolBump::beginShiny(bool invisible) void LLDrawPoolBump::renderShiny(bool invisible) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + LLFastTimer t(FTM_RENDER_SHINY); if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { @@ -410,7 +411,7 @@ void LLDrawPoolBump::renderShiny(bool invisible) void LLDrawPoolBump::endShiny(bool invisible) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + LLFastTimer t(FTM_RENDER_SHINY); if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { @@ -450,7 +451,7 @@ void LLDrawPoolBump::endShiny(bool invisible) void LLDrawPoolBump::beginFullbrightShiny() { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + LLFastTimer t(FTM_RENDER_SHINY); if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) { return; @@ -499,7 +500,7 @@ void LLDrawPoolBump::beginFullbrightShiny() void LLDrawPoolBump::renderFullbrightShiny() { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + LLFastTimer t(FTM_RENDER_SHINY); if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) { return; @@ -514,7 +515,7 @@ void LLDrawPoolBump::renderFullbrightShiny() void LLDrawPoolBump::endFullbrightShiny() { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + LLFastTimer t(FTM_RENDER_SHINY); if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) { return; @@ -624,7 +625,7 @@ void LLDrawPoolBump::beginBump() } sVertexMask = VERTEX_MASK_BUMP; - LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer t(FTM_RENDER_BUMP); // Optional second pass: emboss bump map stop_glerror(); @@ -668,7 +669,7 @@ void LLDrawPoolBump::renderBump() return; } - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer ftm(FTM_RENDER_BUMP); LLGLDisable fog(GL_FOG); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL); LLGLEnable blend(GL_BLEND); @@ -705,7 +706,7 @@ void LLDrawPoolBump::beginDeferredPass(S32 pass) { return; } - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer ftm(FTM_RENDER_BUMP); mShiny = TRUE; gDeferredBumpProgram.bind(); diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); @@ -720,7 +721,7 @@ void LLDrawPoolBump::endDeferredPass(S32 pass) { return; } - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer ftm(FTM_RENDER_BUMP); mShiny = FALSE; gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP); @@ -734,7 +735,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass) { return; } - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + LLFastTimer ftm(FTM_RENDER_BUMP); U32 type = LLRenderPass::PASS_BUMP; LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); @@ -1250,7 +1251,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) void LLDrawPoolInvisible::render(S32 pass) { //render invisiprims - LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE); + LLFastTimer t(FTM_RENDER_INVISIBLE); U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; glStencilMask(0); @@ -1279,7 +1280,7 @@ void LLDrawPoolInvisible::endDeferredPass( S32 pass ) void LLDrawPoolInvisible::renderDeferred( S32 pass ) { //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff - LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE); + LLFastTimer t(FTM_RENDER_INVISIBLE); U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; glStencilMask(0); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 1fdf87f6d2..d084bda2ea 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -50,7 +50,7 @@ static LLGLSLShader* fullbright_shader = NULL; void LLDrawPoolGlow::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_GLOW); + LLFastTimer t(FTM_RENDER_GLOW); LLGLEnable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); gGL.setSceneBlendType(LLRender::BT_ADD); @@ -98,7 +98,7 @@ void LLDrawPoolSimple::prerender() void LLDrawPoolSimple::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLFastTimer t(FTM_RENDER_SIMPLE); if (LLPipeline::sUnderWaterRender) { @@ -125,7 +125,7 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) void LLDrawPoolSimple::endRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLFastTimer t(FTM_RENDER_SIMPLE); LLRenderPass::endRenderPass(pass); if (mVertexShaderLevel > 0){ @@ -140,7 +140,7 @@ void LLDrawPoolSimple::render(S32 pass) LLGLDisable alpha_test(GL_ALPHA_TEST); { //render simple - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLFastTimer t(FTM_RENDER_SIMPLE); gPipeline.enableLightsDynamic(); renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); @@ -157,13 +157,13 @@ void LLDrawPoolSimple::render(S32 pass) void LLDrawPoolSimple::beginDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLFastTimer t(FTM_RENDER_SIMPLE); gDeferredDiffuseProgram.bind(); } void LLDrawPoolSimple::endDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLFastTimer t(FTM_RENDER_SIMPLE); LLRenderPass::endRenderPass(pass); gDeferredDiffuseProgram.unbind(); @@ -175,7 +175,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass) LLGLDisable alpha_test(GL_ALPHA_TEST); { //render simple - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLFastTimer t(FTM_RENDER_SIMPLE); renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); } } @@ -195,7 +195,7 @@ void LLDrawPoolGrass::prerender() void LLDrawPoolGrass::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLFastTimer t(FTM_RENDER_GRASS); if (LLPipeline::sUnderWaterRender) { @@ -222,7 +222,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) void LLDrawPoolGrass::endRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLFastTimer t(FTM_RENDER_GRASS); LLRenderPass::endRenderPass(pass); if (mVertexShaderLevel > 0) @@ -237,7 +237,7 @@ void LLDrawPoolGrass::render(S32 pass) gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); { - LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLFastTimer t(FTM_RENDER_GRASS); LLGLEnable test(GL_ALPHA_TEST); gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass @@ -262,7 +262,7 @@ void LLDrawPoolGrass::renderDeferred(S32 pass) gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); { - LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLFastTimer t(FTM_RENDER_GRASS); gDeferredTreeProgram.bind(); LLGLEnable test(GL_ALPHA_TEST); //render grass @@ -286,7 +286,7 @@ void LLDrawPoolFullbright::prerender() void LLDrawPoolFullbright::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + LLFastTimer t(FTM_RENDER_FULLBRIGHT); if (LLPipeline::sUnderWaterRender) { @@ -300,7 +300,7 @@ void LLDrawPoolFullbright::beginRenderPass(S32 pass) void LLDrawPoolFullbright::endRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + LLFastTimer t(FTM_RENDER_FULLBRIGHT); LLRenderPass::endRenderPass(pass); if (mVertexShaderLevel > 0) @@ -311,7 +311,7 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass) void LLDrawPoolFullbright::render(S32 pass) { //render fullbright - LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + LLFastTimer t(FTM_RENDER_FULLBRIGHT); if (mVertexShaderLevel > 0) { fullbright_shader->bind(); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index a01c9026c8..345dd6bb84 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -61,6 +61,8 @@ int DebugDetailMap = 0; S32 LLDrawPoolTerrain::sDetailMode = 1; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; static LLGLSLShader* sShader = NULL; +static LLFastTimer::DeclareTimer FTM_SHADOW_TERRAIN("Terrain Shadow"); + LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : LLFacePool(POOL_TERRAIN), @@ -131,7 +133,7 @@ void LLDrawPoolTerrain::prerender() void LLDrawPoolTerrain::beginRenderPass( S32 pass ) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFastTimer t(FTM_RENDER_TERRAIN); LLFacePool::beginRenderPass(pass); sShader = LLPipeline::sUnderWaterRender ? @@ -146,7 +148,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass ) void LLDrawPoolTerrain::endRenderPass( S32 pass ) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFastTimer t(FTM_RENDER_TERRAIN); LLFacePool::endRenderPass(pass); if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) { @@ -162,7 +164,7 @@ S32 LLDrawPoolTerrain::getDetailMode() void LLDrawPoolTerrain::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFastTimer t(FTM_RENDER_TERRAIN); if (mDrawFace.empty()) { @@ -235,7 +237,7 @@ void LLDrawPoolTerrain::render(S32 pass) void LLDrawPoolTerrain::beginDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFastTimer t(FTM_RENDER_TERRAIN); LLFacePool::beginRenderPass(pass); sShader = &gDeferredTerrainProgram; @@ -245,14 +247,14 @@ void LLDrawPoolTerrain::beginDeferredPass(S32 pass) void LLDrawPoolTerrain::endDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFastTimer t(FTM_RENDER_TERRAIN); LLFacePool::endRenderPass(pass); sShader->unbind(); } void LLDrawPoolTerrain::renderDeferred(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFastTimer t(FTM_RENDER_TERRAIN); if (mDrawFace.empty()) { return; @@ -262,7 +264,7 @@ void LLDrawPoolTerrain::renderDeferred(S32 pass) void LLDrawPoolTerrain::beginShadowPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFastTimer t(FTM_SHADOW_TERRAIN); LLFacePool::beginRenderPass(pass); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gDeferredShadowProgram.bind(); @@ -270,14 +272,14 @@ void LLDrawPoolTerrain::beginShadowPass(S32 pass) void LLDrawPoolTerrain::endShadowPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFastTimer t(FTM_SHADOW_TERRAIN); LLFacePool::endRenderPass(pass); gDeferredShadowProgram.unbind(); } void LLDrawPoolTerrain::renderShadow(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFastTimer t(FTM_SHADOW_TERRAIN); if (mDrawFace.empty()) { return; diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index f572e2cb44..5cb1fcb635 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -46,6 +46,7 @@ S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; +static LLFastTimer::DeclareTimer FTM_SHADOW_TREE("Tree Shadow"); LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) : LLFacePool(POOL_TREE), @@ -67,7 +68,7 @@ void LLDrawPoolTree::prerender() void LLDrawPoolTree::beginRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(FTM_RENDER_TREES); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); if (LLPipeline::sUnderWaterRender) @@ -91,7 +92,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) void LLDrawPoolTree::render(S32 pass) { - LLFastTimer t(LLPipeline::sShadowRender ? LLFastTimer::FTM_SHADOW_TREE : LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); if (mDrawFace.empty()) { @@ -122,7 +123,7 @@ void LLDrawPoolTree::render(S32 pass) void LLDrawPoolTree::endRenderPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(FTM_RENDER_TREES); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); if (gPipeline.canUseWindLightShadersOnObjects()) @@ -136,7 +137,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass) //============================================ void LLDrawPoolTree::beginDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(FTM_RENDER_TREES); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); shader = &gDeferredTreeProgram; @@ -150,7 +151,7 @@ void LLDrawPoolTree::renderDeferred(S32 pass) void LLDrawPoolTree::endDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(FTM_RENDER_TREES); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); shader->unbind(); @@ -161,7 +162,7 @@ void LLDrawPoolTree::endDeferredPass(S32 pass) //============================================ void LLDrawPoolTree::beginShadowPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); + LLFastTimer t(FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); gDeferredShadowProgram.bind(); } @@ -173,7 +174,7 @@ void LLDrawPoolTree::renderShadow(S32 pass) void LLDrawPoolTree::endShadowPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); + LLFastTimer t(FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gDeferredShadowProgram.unbind(); } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 16623ca2b6..fd4dc123d5 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -138,7 +138,7 @@ void LLDrawPoolWater::endPostDeferredPass(S32 pass) void LLDrawPoolWater::render(S32 pass) { - LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); + LLFastTimer ftm(FTM_RENDER_WATER); if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) { return; diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 917b6fafbc..9b52ddb73c 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -260,7 +260,7 @@ void LLDrawPoolWLSky::render(S32 pass) { return; } - LLFastTimer ftm(LLFastTimer::FTM_RENDER_WL_SKY); + LLFastTimer ftm(FTM_RENDER_WL_SKY); const F32 camHeightLocal = LLWLParamManager::instance()->getDomeOffset() * LLWLParamManager::instance()->getDomeRadius(); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 0aef3123d6..8ceb41c27a 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -195,7 +195,8 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) { - mHoverBarIndex = llmin(LLFastTimer::getCurFrameIndex() - 1, MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight())); + mHoverBarIndex = llmin(LLFastTimer::getCurFrameIndex() - 1, + MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight())); if (mHoverBarIndex == 0) { return TRUE; @@ -217,9 +218,9 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverID = (*it); mHoverTimer = (*it); mToolTipRect.set(mBarStart[mHoverBarIndex][i], - mBarRect.mBottom + llround(((F32)mHoverBarIndex + 1.f) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f))), + mBarRect.mBottom + llround(((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex + 1)) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f))), mBarEnd[mHoverBarIndex][i], - mBarRect.mBottom + llround((F32)mHoverBarIndex * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f)))); + mBarRect.mBottom + llround((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f)))); } if ((*it)->getCollapsed()) @@ -248,6 +249,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* stic // tooltips for timer bars if (mHoverTimer) { + localRectToScreen(mToolTipRect, sticky_rect_screen); msg = mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex); return TRUE; } @@ -960,9 +962,14 @@ void LLFastTimerView::draw() LLView::draw(); } -F64 LLFastTimerView::getTime(LLFastTimer::NamedTimer::FrameState& id) +F64 LLFastTimerView::getTime(const std::string& name) { - return (F64)id.mTimer->getCountAverage() / (F64)LLFastTimer::countsPerSecond(); + const LLFastTimer::NamedTimer* timerp = LLFastTimer::getTimerByName(name); + if (timerp) + { + return (F64)timerp->getCountAverage() / (F64)LLFastTimer::countsPerSecond(); + } + return 0.0; } //static diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 78ca7b50d6..f301888984 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -62,7 +62,7 @@ public: virtual void draw(); LLFastTimer::NamedTimer* getLegendID(S32 y); - F64 getTime(LLFastTimer::NamedTimer::FrameState& id); + F64 getTime(const std::string& name); private: typedef std::vector > bar_positions_t; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 7fc127f803..9c1a7ecb04 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -36,6 +36,7 @@ #include "llbutton.h" #include "llfloaterreg.h" +#include "llfocusmgr.h" #include "llinventory.h" #include "lluictrlfactory.h" #include "llmenugl.h" @@ -292,7 +293,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) if (mFirstDropDownItem != count) { // Chevron button should stay right aligned - LLView *chevron_button = getChildView(std::string(">>"), FALSE, FALSE); + LLView *chevron_button = findChildView(std::string(">>"), FALSE); if (chevron_button) { LLRect rect; @@ -335,7 +336,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) else { // Hide chevron button if all items are visible on bar - LLView *chevron_button = getChildView(std::string(">>"), FALSE, FALSE); + LLView *chevron_button = findChildView(std::string(">>"), FALSE); if (chevron_button) { chevron_button->setVisible(FALSE); @@ -366,7 +367,7 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite fav_btn->setLabel(item->getName()); fav_btn->setToolTip(item->getName()); fav_btn->setCommitCallback(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); - fav_btn->setRightClickedCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 )); + fav_btn->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 )); sendChildToBack(fav_btn); curr_x += buttonWidth + buttonHGap; @@ -486,7 +487,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); LLMenuItemCallGL *menu_item = LLUICtrlFactory::create(item_params); - menu_item->setRightClickedCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4)); + menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4)); // Check whether item name wider than menu if ((S32) menu_item->getNominalWidth() > bar_width) { @@ -545,6 +546,10 @@ void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S return; } + // Release mouse capture so hover events go to the popup menu + // because this is happening during a mouse down. + gFocusMgr.setMouseCapture(NULL); + menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(fav_button, menu, x, y); } diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index bafb69a835..216bca8262 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -261,6 +261,7 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons // updated every time step. In the future, perhaps there could be an // optimization similar to what Havok does for objects that are stationary. //--------------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { if (mVO->mDrawable.isNull()) @@ -279,7 +280,7 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 parent->mDrawable->mQuietCount = 0; } - LLFastTimer ftm(LLFastTimer::FTM_FLEXIBLE_UPDATE); + LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); S32 new_res = mAttributes->getSimulateLOD(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 7332ca4b5c..3c27d37ee9 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -61,6 +61,8 @@ #include "llmediamanager.h" #include "llwindow.h" +#include "llbutton.h" + #if LL_WINDOWS #include "lldxhardware.h" #endif @@ -102,20 +104,18 @@ BOOL LLFloaterAbout::postBuild() support_widget->setParseHTML(TRUE); // Text styles for release notes hyperlinks - LLStyleSP viewer_link_style(new LLStyle); - viewer_link_style->setVisible(true); - viewer_link_style->setFontName(LLStringUtil::null); - viewer_link_style->setLinkHREF(get_viewer_release_notes_url()); - viewer_link_style->setColor(LLUIColorTable::instance().getColor("HTMLLinkColor")); + LLStyle::Params link_style_params; + link_style_params.color.control = "HTMLLinkColor"; + link_style_params.link_href = get_viewer_release_notes_url(); // Version string - std::string version = LLTrans::getString("SECOND_LIFE_VIEWER") + std::string version = LLTrans::getString("APP_NAME") + llformat(" %d.%d.%d (%d) %s %s (%s)\n", LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD, __DATE__, __TIME__, gSavedSettings.getString("VersionChannelName").c_str()); support_widget->appendColoredText(version, FALSE, FALSE, LLUIColorTable::instance().getColor("TextFgReadOnlyColor")); - support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, viewer_link_style); + support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, link_style_params); std::string support; support.append("\n\n"); @@ -132,11 +132,9 @@ BOOL LLFloaterAbout::postBuild() LLViewerRegion* region = gAgent.getRegion(); if (region) { - LLStyleSP server_link_style(new LLStyle); - server_link_style->setVisible(true); - server_link_style->setFontName(LLStringUtil::null); - server_link_style->setLinkHREF(region->getCapability("ServerReleaseNotes")); - server_link_style->setColor(LLUIColorTable::instance().getColor("HTMLLinkColor")); + LLStyle::Params server_link_style_params; + server_link_style_params.color.control = "HTMLLinkColor"; + server_link_style_params.link_href = region->getCapability("ServerReleaseNotes"); const LLVector3d &pos = gAgent.getPositionGlobal(); LLUIString pos_text = getString("you_are_at"); @@ -159,7 +157,7 @@ BOOL LLFloaterAbout::postBuild() support.append("\n"); support_widget->appendColoredText(support, FALSE, FALSE, LLUIColorTable::instance().getColor("TextFgReadOnlyColor")); - support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style); + support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style_params); support = "\n\n"; } @@ -251,13 +249,9 @@ BOOL LLFloaterAbout::postBuild() // Fix views support_widget->setCursorPos(0); support_widget->setEnabled(FALSE); - support_widget->setTakesFocus(TRUE); - support_widget->setHandleEditKeysDirectly(TRUE); credits_widget->setCursorPos(0); credits_widget->setEnabled(FALSE); - credits_widget->setTakesFocus(TRUE); - credits_widget->setHandleEditKeysDirectly(TRUE); return TRUE; } diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 3d1b7965a1..7075719299 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -566,32 +566,25 @@ void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data) void LLFloaterBuyLandUI::updateFloaterCovenantText(const std::string &string, const LLUUID& asset_id) { LLViewerTextEditor* editor = getChild("covenant_editor"); - if (editor) - { - editor->setHandleEditKeysDirectly(FALSE); - editor->setText(string); + editor->setText(string); - LLCheckBoxCtrl* check = getChild("agree_covenant"); - LLTextBox* box = getChild("covenant_text"); - if(check && box) - { - if (asset_id.isNull()) - { - check->set(true); - check->setEnabled(false); - refreshUI(); + LLCheckBoxCtrl* check = getChild("agree_covenant"); + LLTextBox* box = getChild("covenant_text"); + if (asset_id.isNull()) + { + check->set(true); + check->setEnabled(false); + refreshUI(); - // remove the line stating that you must agree - box->setVisible(FALSE); - } - else - { - check->setEnabled(true); + // remove the line stating that you must agree + box->setVisible(FALSE); + } + else + { + check->setEnabled(true); - // remove the line stating that you must agree - box->setVisible(TRUE); - } - } + // remove the line stating that you must agree + box->setVisible(TRUE); } } diff --git a/indra/newview/llfloaterbuyland.h b/indra/newview/llfloaterbuyland.h index 7df07f752d..00d44035ae 100644 --- a/indra/newview/llfloaterbuyland.h +++ b/indra/newview/llfloaterbuyland.h @@ -35,7 +35,6 @@ class LLFloater; class LLViewerRegion; -class LLViewerTextEditor; class LLParcelSelection; class LLFloaterBuyLand diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 742cc5c5de..8c09ee7d48 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -172,8 +172,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& { std::string start_line = line.substr(0, chat.mFromName.length() + 1); line = line.substr(chat.mFromName.length() + 1); - const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL); - edit->appendStyledText(start_line, false, prepend_newline, sourceStyle); + edit->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL)); prepend_newline = false; } edit->appendColoredText(line, false, prepend_newline, color); diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index e8af48d095..6ba3165d6a 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -42,14 +42,8 @@ #include "lllogchat.h" class LLChat; -class LLViewerTextEditor; -class LLMessageSystem; -class LLUUID; -class LLCheckBoxCtrl; class LLPanelActiveSpeakers; class LLLogChat; -class LLVector3d; -class LLWindow; enum ELogOptions { diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 1e8e7bad74..eb73bd6d8f 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -404,7 +404,7 @@ void LLPanelFriends::refreshNames(U32 changed_mask) // Changed item in place, need to request sort and update columns // because we might have changed data in a column on which the user // has already sorted. JC - mFriendsList->sortItems(); + mFriendsList->updateSort(); // re-select items mFriendsList->selectMultiple(selected_ids); diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index 3c66a2add1..45a42f994d 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -1000,7 +1000,7 @@ BOOL LLFloaterInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { // Check to see if we are auto scrolling from the last frame LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); - BOOL needsToScroll = panel->getScrollableContainer()->needsToScroll(x, y, LLScrollContainer::VERTICAL); + BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y); if(mFilterTabs) { if(needsToScroll) @@ -1320,9 +1320,11 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() return mFolders->getFilter()->getShowFolderState(); } +static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); + void LLInventoryPanel::modelChanged(U32 mask) { - LLFastTimer t2(LLFastTimer::FTM_REFRESH); + LLFastTimer t2(FTM_REFRESH); bool handled = false; if(mask & LLInventoryObserver::LABEL) diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index c5e07c6596..1746d6d435 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2847,11 +2847,7 @@ void LLPanelLandCovenant::updateCovenantText(const std::string &string) if (self) { LLViewerTextEditor* editor = self->getChild("covenant_editor"); - if (editor) - { - editor->setHandleEditKeysDirectly(TRUE); - editor->setText(string); - } + editor->setText(string); } } diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 7fc5ed0c9e..29d1c4dd84 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -59,7 +59,6 @@ class LLTextBox; class LLTextEditor; class LLTextureCtrl; class LLUIImage; -class LLViewerTextEditor; class LLParcelSelection; class LLPanelLandGeneral; diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 0a3d97245b..f2dff55044 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -39,7 +39,6 @@ #include "llscrolllistitem.h" #include "llpanel.h" #include "llcombobox.h" -#include "llviewertexteditor.h" const S32 NOTIFICATION_PANEL_HEADER_HEIGHT = 20; const S32 HEADER_PADDING = 38; @@ -250,7 +249,7 @@ LLFloaterNotification::LLFloaterNotification(LLNotification* note) BOOL LLFloaterNotification::postBuild() { setTitle(mNote->getName()); - getChild("payload")->setText(mNote->getMessage()); + getChild("payload")->setValue(mNote->getMessage()); LLComboBox* responses_combo = getChild("response"); LLCtrlListInterface* response_list = responses_combo->getListInterface(); diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index aa68a1b229..ac687ed3e9 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -43,8 +43,8 @@ #include "llagent.h" #include "llui.h" #include "lllineeditor.h" -#include "llviewertexteditor.h" #include "llbutton.h" +#include "lltexteditor.h" #include "llfloaterreg.h" #include "llviewercontrol.h" #include "llviewernetwork.h" @@ -104,14 +104,8 @@ BOOL LLFloaterPostcard::postBuild() gAgent.buildFullname(name_string); childSetValue("name_form", LLSD(name_string)); - LLTextEditor* MsgField = getChild("msg_form"); - if (MsgField) - { - MsgField->setWordWrap(TRUE); - - // For the first time a user focusess to .the msg box, all text will be selected. - MsgField->setFocusChangedCallback(onMsgFormFocusRecieved, this); - } + // For the first time a user focusess to .the msg box, all text will be selected. + getChild("msg_form")->setFocusChangedCallback(onMsgFormFocusRecieved, this); childSetFocus("to_form", TRUE); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 1a7f72d49c..79f8f412fd 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -62,13 +62,11 @@ #include "llpanellogin.h" #include "llradiogroup.h" #include "llsky.h" -#include "llstylemap.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llsliderctrl.h" #include "lltabcontainer.h" #include "lltrans.h" -#include "lltexteditor.h" #include "llviewercontrol.h" #include "llviewercamera.h" #include "llviewerwindow.h" @@ -169,7 +167,6 @@ void LLVoiceSetKeyDialog::onCancel(void* user_data) // a static member and update all our static callbacks void free_web_media(LLMediaBase *media_source); -void handleHTMLLinkColorChanged(const LLSD& newvalue); void handleNameTagOptionChanged(const LLSD& newvalue); LLMediaBase *get_web_media(); bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response); @@ -239,12 +236,6 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response return false; } -void handleHTMLLinkColorChanged(const LLSD& newvalue) -{ - LLTextEditor::setLinkColor(LLColor4(newvalue)); - LLStyleMap::instance().update(); - -} void handleNameTagOptionChanged(const LLSD& newvalue) { S32 name_tag_option = S32(newvalue); @@ -458,14 +449,12 @@ void LLFloaterPreference::apply() } free_web_media(media_source); - LLTextEditor* busy = getChild("busy_response"); - LLWString busy_response; - if (busy) busy_response = busy->getWText(); - LLWStringUtil::replaceTabsWithSpaces(busy_response, 4); +// LLWString busy_response = utf8str_to_wstring(getChild("busy_response")->getValue().asString()); +// LLWStringUtil::replaceTabsWithSpaces(busy_response, 4); if(mGotPersonalInfo) { - gSavedPerAccountSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response))); +// gSavedSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response))); bool new_im_via_email = childGetValue("send_im_to_email").asBoolean(); bool new_hide_online = childGetValue("online_visibility").asBoolean(); @@ -1172,13 +1161,13 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im childSetValue("send_im_to_email", im_via_email); childEnable("log_instant_messages"); // childEnable("log_chat"); - childEnable("busy_response"); +// childEnable("busy_response"); // childEnable("log_instant_messages_timestamp"); // childEnable("log_chat_timestamp"); childEnable("log_chat_IM"); childEnable("log_date_timestamp"); - childSetText("busy_response", gSavedPerAccountSettings.getString("BusyModeResponse2")); +// childSetText("busy_response", gSavedSettings.getString("BusyModeResponse2")); enableHistory(); std::string display_email(email); @@ -1349,8 +1338,7 @@ static LLRegisterPanelClassWrapper t_places("panel_preference LLPanelPreference::LLPanelPreference() : LLPanel() { - // - mCommitCallbackRegistrar.add("setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2)); + mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2)); } static void applyUIColor(const std::string& color_name, LLUICtrl* ctrl, const LLSD& param) @@ -1422,23 +1410,17 @@ BOOL LLPanelPreference::postBuild() ////// if(hasChild("online_visibility") && hasChild("send_im_to_email")) { - requires("online_visibility"); - requires("send_im_to_email"); - if (!checkRequirements()) - { - return FALSE; - } childSetText("email_address",getString("log_in_to_change") ); - childSetText("busy_response", getString("log_in_to_change")); +// childSetText("busy_response", getString("log_in_to_change")); } - if(hasChild("fullscreen combo")) + if(hasChild("aspect_ratio")) { //============================================================================ // Resolution - +/* S32 num_resolutions = 0; LLWindow::LLWindowResolution* supported_resolutions = gViewerWindow->getWindow()->getSupportedResolutions(num_resolutions); @@ -1481,7 +1463,7 @@ BOOL LLPanelPreference::postBuild() ctrl_full_screen->setCurrentByIndex(0); } } - + */ LLFloaterPreference::initWindowSizeControls(this); if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio")) diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp index 8ac00832c9..ab281e9f9f 100644 --- a/indra/newview/llfloaterproperties.cpp +++ b/indra/newview/llfloaterproperties.cpp @@ -46,6 +46,7 @@ #include "llavataractions.h" #include "llinventorymodel.h" #include "lllineeditor.h" +#include "llspinctrl.h" #include "llradiogroup.h" #include "llresmgr.h" #include "roles_constants.h" @@ -151,7 +152,7 @@ BOOL LLFloaterProperties::postBuild() getChild("CheckPurchase")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this)); getChild("RadioSaleType")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleType, this)); // "Price" label for edit - getChild("EditPrice")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this)); + getChild("Edit Cost")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this)); // The UI has been built, now fill in all the values refresh(); @@ -195,7 +196,7 @@ void LLFloaterProperties::refresh() "CheckNextOwnerTransfer", "CheckPurchase", "RadioSaleType", - "EditPrice" + "Edit Cost" }; for(size_t t=0; tsetSelectedIndex((S32)sale_info.getSaleType() - 1); S32 numerical_price; numerical_price = sale_info.getSalePrice(); - childSetText("EditPrice",llformat("%d",numerical_price)); + childSetText("Edit Cost",llformat("%d",numerical_price)); } else { radioSaleType->setSelectedIndex(-1); - childSetText("EditPrice",llformat("%d",0)); + childSetText("Edit Cost",llformat("%d",0)); } } @@ -790,12 +793,13 @@ void LLFloaterProperties::updateSaleInfo() sale_type = LLSaleInfo::FS_ORIGINAL; } - LLLineEditor* EditPrice = getChild("EditPrice"); + // LLLineEditor* EditPrice = getChild("EditPrice"); + LLSpinCtrl *EditPrice = getChild("Edit Cost"); S32 price = -1; if(EditPrice) { - price = atoi(EditPrice->getText().c_str()); + price = EditPrice->getValue().asInteger();; } // Invalid data - turn off the sale if (price < 0) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 94d25aa0c8..a50bcaa098 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -2746,7 +2746,6 @@ BOOL LLPanelEstateCovenant::postBuild() mEstateOwnerText = getChild("estate_owner_text"); mLastModifiedText = getChild("covenant_timestamp_text"); mEditor = getChild("covenant_editor"); - if (mEditor) mEditor->setHandleEditKeysDirectly(TRUE); LLButton* reset_button = getChild("reset_covenant"); reset_button->setEnabled(gAgent.canManageEstate()); reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, NULL); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 00cbc2f0c8..e2176350c9 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -48,6 +48,7 @@ #include "llversionviewer.h" #include "message.h" #include "v3math.h" +#include "lltexteditor.h" // viewer project includes #include "llagent.h" @@ -61,7 +62,6 @@ #include "llimview.h" #include "lltextbox.h" #include "lldispatcher.h" -#include "llviewertexteditor.h" #include "llviewerobject.h" #include "llviewerregion.h" #include "llcombobox.h" diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index c8690de68c..328fb6450e 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -80,9 +80,6 @@ BOOL LLFloaterScriptDebug::postBuild() if (mTabContainer) { - // *FIX: apparantly fails for tab containers? -// mTabContainer->requires("all_scripts"); -// mTabContainer->checkRequirements(); return TRUE; } diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index 53b40f8b7a..616e9bac35 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -39,6 +39,7 @@ #include "llspinctrl.h" #include "llcolorswatch.h" #include "llviewercontrol.h" +#include "lltexteditor.h" LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key) diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h index e7dda3a5f4..65803fbf70 100644 --- a/indra/newview/llfloatersettingsdebug.h +++ b/indra/newview/llfloatersettingsdebug.h @@ -35,7 +35,6 @@ #include "llcontrol.h" #include "llfloater.h" -#include "lltexteditor.h" class LLFloaterSettingsDebug : public LLFloater @@ -60,7 +59,7 @@ private: virtual ~LLFloaterSettingsDebug(); protected: - LLTextEditor* mComment; + class LLTextEditor* mComment; }; #endif //LLFLOATERDEBUGSETTINGS_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 371dfa50cd..814395395c 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -41,7 +41,6 @@ #include "llcallbacklist.h" #include "llcriticaldamp.h" #include "llui.h" -#include "llviewertexteditor.h" #include "llfocusmgr.h" #include "llbutton.h" #include "llcombobox.h" diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 1e84902594..f61d5cb077 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -39,7 +39,6 @@ #include "llappviewer.h" #include "llstartup.h" #include "llviewerstats.h" -#include "llviewertexteditor.h" #include "llviewerwindow.h" // linden library includes @@ -118,12 +117,10 @@ BOOL LLFloaterTOS::postBuild() if (hasChild("tos_text")) { // this displays the critical message - LLTextEditor *editor = getChild("tos_text"); - editor->setHandleEditKeysDirectly( TRUE ); - editor->setEnabled( FALSE ); - editor->setWordWrap(TRUE); - editor->setFocus(TRUE); - editor->setValue(LLSD(mMessage)); + LLUICtrl *tos_text = getChild("tos_text"); + tos_text->setEnabled( FALSE ); + tos_text->setFocus(TRUE); + tos_text->setValue(LLSD(mMessage)); return TRUE; } @@ -133,7 +130,7 @@ BOOL LLFloaterTOS::postBuild() tos_agreement->setEnabled( false ); // hide the SL text widget if we're displaying TOS with using a browser widget. - LLTextEditor *editor = getChild("tos_text"); + LLUICtrl *editor = getChild("tos_text"); editor->setVisible( FALSE ); LLWebBrowserCtrl* web_browser = getChild("tos_html"); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index e5b4657742..2eb4e7580e 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -747,8 +747,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) panel->updateBoundingRect(); // update bounding rect LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect - LLRect panel_rect = panel->getRect(); // get the panel's rect - LLRect new_rect = panel_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible + LLRect new_rect = panel->getRect(); // get the panel's rect + new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible (*floaterp)->reshape(new_rect.getWidth(), new_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed) (*floaterp)->addChild(panel); // add panel as child @@ -1274,7 +1274,7 @@ void LLFloaterUIPreview::highlightChangedElements() BOOL failed = FALSE; for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) { - element = element->getChild(*token_iter,FALSE,FALSE); // try to find element: don't recur, and don't create if missing + element = element->findChild(*token_iter,FALSE); // try to find element: don't recur, and don't create if missing // if we still didn't find it... if(NULL == element) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 4a5a775a05..d1f0f94fa0 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -176,7 +176,7 @@ LLFolderView::LLFolderView(const Params& p) mSourceID(p.task_id), mRenameItem( NULL ), mNeedsScroll( FALSE ), - mLastScrollItem( NULL ), + mPinningSelectedItem(FALSE), mNeedsAutoSelect( FALSE ), mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), @@ -191,7 +191,6 @@ LLFolderView::LLFolderView(const Params& p) mDragAndDropThisFrame(FALSE), mCallbackRegistrar(NULL), mParentPanel(p.parent_panel) - { LLRect rect = p.rect; LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); @@ -290,11 +289,13 @@ void LLFolderView::checkTreeResortForModelChanged() } } +static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); + void LLFolderView::setSortOrder(U32 order) { if (order != mSortOrder) { - LLFastTimer t(LLFastTimer::FTM_SORT); + LLFastTimer t(FTM_SORT); mSortOrder = order; for (folders_t::iterator iter = mFolders.begin(); @@ -359,10 +360,12 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse mIsOpen = TRUE; } +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); + // This view grows and shinks to enclose all of its children items and folders. S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) { - LLFastTimer t2(LLFastTimer::FTM_ARRANGE); + LLFastTimer t2(FTM_ARRANGE); filter_generation = mFilter->getMinRequiredGeneration(); mMinWidth = 0; @@ -431,17 +434,13 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen } } - S32 dummy_s32; - BOOL dummy_bool; - S32 min_width; - mScrollContainer->calcVisibleSize( &min_width, &dummy_s32, &dummy_bool, &dummy_bool); - reshape( llmax(min_width, total_width), running_height ); + LLRect scroll_rect = mScrollContainer->getContentWindowRect(); + reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); - S32 new_min_width; - mScrollContainer->calcVisibleSize( &new_min_width, &dummy_s32, &dummy_bool, &dummy_bool); - if (new_min_width != min_width) + LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); + if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) { - reshape( llmax(min_width, total_width), running_height ); + reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); } // move item renamer text field to item's new position @@ -456,9 +455,11 @@ const std::string LLFolderView::getFilterSubString(BOOL trim) return mFilter->getFilterSubString(trim); } +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); + void LLFolderView::filter( LLInventoryFilter& filter ) { - LLFastTimer t2(LLFastTimer::FTM_FILTER); + LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) @@ -467,18 +468,20 @@ void LLFolderView::filter( LLInventoryFilter& filter ) mMinWidth = 0; LLFolderViewFolder::filter(filter); } + else + { + mFiltered = TRUE; + } } void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) { - S32 min_width = 0; - S32 dummy_height; - BOOL dummy_bool; + LLRect scroll_rect; if (mScrollContainer) { - mScrollContainer->calcVisibleSize( &min_width, &dummy_height, &dummy_bool, &dummy_bool); + scroll_rect = mScrollContainer->getContentWindowRect(); } - width = llmax(mMinWidth, min_width); + width = llmax(mMinWidth, scroll_rect.getWidth()); LLView::reshape(width, height, called_from_parent); mReshapeSignal(mSelectedItems, FALSE); @@ -1127,7 +1130,9 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) mAutoOpenItems.push(item); item->setOpen(TRUE); - scrollToShowItem(item); + LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); + scrollToShowItem(item, constraint_rect); } void LLFolderView::closeAutoOpenedFolders() @@ -1791,49 +1796,41 @@ void LLFolderView::scrollToShowSelection() // If the parent is scroll containter, scroll it to make the selection // is maximally visible. -void LLFolderView::scrollToShowItem(LLFolderViewItem* item) +void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) { + if (!mScrollContainer) return; + // don't scroll to items when mouse is being used to scroll/drag and drop if (gFocusMgr.childHasMouseCapture(mScrollContainer)) { mNeedsScroll = FALSE; return; } - if(item && mScrollContainer) + + // if item exists and is in visible portion of parent folder... + if(item) { - LLRect local_rect = item->getRect(); + LLRect local_rect = item->getLocalRect(); LLRect item_scrolled_rect; // item position relative to display area of scroller + LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); S32 label_height = llround(sFont->getLineHeight()); // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder - S32 max_height_to_show = gFocusMgr.childHasKeyboardFocus(this) ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); - item->localPointToOtherView(item->getIndentation(), llmax(0, local_rect.getHeight() - max_height_to_show), &item_scrolled_rect.mLeft, &item_scrolled_rect.mBottom, mScrollContainer); - item->localPointToOtherView(local_rect.getWidth(), local_rect.getHeight(), &item_scrolled_rect.mRight, &item_scrolled_rect.mTop, mScrollContainer); - - item_scrolled_rect.mRight = llmin(item_scrolled_rect.mLeft + MIN_ITEM_WIDTH_VISIBLE, item_scrolled_rect.mRight); - LLCoordGL scroll_offset(-mScrollContainer->getBorderWidth() - item_scrolled_rect.mLeft, - mScrollContainer->getRect().getHeight() - item_scrolled_rect.mTop - 1); - - S32 max_scroll_offset = getVisibleRect().getHeight() - item_scrolled_rect.getHeight(); - if (item != mLastScrollItem || // if we're scrolling to focus on a new item - // or the item has just appeared on screen and it wasn't onscreen before - (scroll_offset.mY > 0 && scroll_offset.mY < max_scroll_offset && - (mLastScrollOffset.mY < 0 || mLastScrollOffset.mY > max_scroll_offset))) - { - // we now have a position on screen that we want to keep stable - // offset of selection relative to top of visible area - mLastScrollOffset = scroll_offset; - mLastScrollItem = item; - } + S32 max_height_to_show = mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + + // get portion of item that we want to see... + LLRect item_local_rect = LLRect(item->getIndentation(), + local_rect.getHeight(), + llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()), + llmax(0, local_rect.getHeight() - max_height_to_show)); + + LLRect item_doc_rect; + + item->localRectToOtherView(item_local_rect, &item_doc_rect, this); - mScrollContainer->scrollToShowRect( item_scrolled_rect, mLastScrollOffset ); + mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); - // after scrolling, store new offset - // in case we don't have room to maintain the original position - LLCoordGL new_item_left_top; - item->localPointToOtherView(item->getIndentation(), item->getRect().getHeight(), &new_item_left_top.mX, &new_item_left_top.mY, mScrollContainer); - mLastScrollOffset.set(-mScrollContainer->getBorderWidth() - new_item_left_top.mX, mScrollContainer->getRect().getHeight() - new_item_left_top.mY - 1); } } @@ -1973,10 +1970,13 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) return true; } +static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); +static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); + // Main idle routine void LLFolderView::doIdle() { - LLFastTimer t2(LLFastTimer::FTM_INVENTORY); + LLFastTimer t2(FTM_INVENTORY); BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); if (debug_filters != getDebugFilters()) @@ -1990,7 +1990,7 @@ void LLFolderView::doIdle() mFilter->isNotDefault(); mNeedsAutoSelect = filter_modified_and_active && !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); - + // filter to determine visiblity before arranging filterFromRoot(); @@ -2001,7 +2001,7 @@ void LLFolderView::doIdle() // potentially changed if (mNeedsAutoSelect) { - LLFastTimer t3(LLFastTimer::FTM_AUTO_SELECT); + LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride) @@ -2013,6 +2013,59 @@ void LLFolderView::doIdle() scrollToShowSelection(); } + // during filtering process, try to pin selected item's location on screen + // this will happen when searching your inventory and when new items arrive + if (filter_modified_and_active) + { + // calculate rectangle to pin item to at start of animated rearrange + if (!mPinningSelectedItem && !mSelectedItems.empty()) + { + // lets pin it! + mPinningSelectedItem = TRUE; + + LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); + LLFolderViewItem* selected_item = mSelectedItems.back(); + + LLRect item_rect; + selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); + // if item is visible in scrolled region + if (visible_content_rect.overlaps(item_rect)) + { + // then attempt to keep it in same place on screen + mScrollConstraintRect = item_rect; + mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); + } + else + { + // otherwise we just want it onscreen somewhere + LLRect content_rect = mScrollContainer->getContentWindowRect(); + mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + } + } + else + { + // stop pinning selected item after folders stop rearranging + if (!needsArrange()) + { + mPinningSelectedItem = FALSE; + } + } + + LLRect constraint_rect; + if (mPinningSelectedItem) + { + // use last known constraint rect for pinned item + constraint_rect = mScrollConstraintRect; + } + else + { + // during normal use (page up/page down, etc), just try to fit item on screen + LLRect content_rect = mScrollContainer->getContentWindowRect(); + constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + + BOOL is_visible = isInVisibleChain(); if ( is_visible ) @@ -2026,10 +2079,10 @@ void LLFolderView::doIdle() if (mSelectedItems.size() && mNeedsScroll) { - scrollToShowItem(mSelectedItems.back()); + scrollToShowItem(mSelectedItems.back(), constraint_rect); // continue scrolling until animated layout change is done - if (getCompletedFilterGeneration() >= mFilter->getMinRequiredGeneration() && - (!needsArrange() || !is_visible)) + if (!filter_modified_and_active + && (!needsArrange() || !is_visible)) { mNeedsScroll = FALSE; } @@ -2077,15 +2130,13 @@ void LLFolderView::updateRenamerPosition() screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); - S32 scroller_height = 0; - S32 scroller_width = gViewerWindow->getWindowWidth(); - BOOL dummy_bool; + LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidth(), 0); if (mScrollContainer) { - mScrollContainer->calcVisibleSize( &scroller_width, &scroller_height, &dummy_bool, &dummy_bool); + scroller_rect = mScrollContainer->getContentWindowRect(); } - S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_width - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); + S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); S32 height = llfloor(sFont->getLineHeight() + RENAME_HEIGHT_PAD); mRenamer->reshape( width, height, TRUE ); } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8d9d52cd17..a05dec3193 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -240,7 +240,7 @@ public: virtual void deleteAllChildren(); void scrollToShowSelection(); - void scrollToShowItem(LLFolderViewItem* item); + void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } LLRect getVisibleRect(); @@ -299,8 +299,8 @@ protected: LLLineEditor* mRenamer; BOOL mNeedsScroll; - LLFolderViewItem* mLastScrollItem; - LLCoordGL mLastScrollOffset; + BOOL mPinningSelectedItem; + LLRect mScrollConstraintRect; BOOL mNeedsAutoSelect; BOOL mAutoSelectOverride; BOOL mNeedsAutoRename; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index de6a1a097d..8961508bcc 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -233,7 +233,7 @@ void LLFolderViewItem::refreshFromListener() // temporary attempt to display the inventory folder in the user locale. if (LLAssetType::lookupIsProtectedCategoryType(preferred_type)) { - mLabel = LLTrans::getString("InvFolder " + mLabel); + LLTrans::findString(mLabel, "InvFolder " + mLabel); }; setIcon(mListener->getIcon()); diff --git a/indra/newview/llhudmanager.cpp b/indra/newview/llhudmanager.cpp index 8588de0fa0..bdb8dadfb4 100644 --- a/indra/newview/llhudmanager.cpp +++ b/indra/newview/llhudmanager.cpp @@ -62,10 +62,11 @@ LLHUDManager::~LLHUDManager() { } +static LLFastTimer::DeclareTimer FTM_HUD_EFFECTS("Hud Effects"); void LLHUDManager::updateEffects() { - LLFastTimer ftm(LLFastTimer::FTM_HUD_EFFECTS); + LLFastTimer ftm(FTM_HUD_EFFECTS); S32 i; for (i = 0; i < mHUDEffects.count(); i++) { diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index bdff492948..dc55aba0db 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -254,10 +254,12 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type) return hud_objectp; } +static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("Update Hud"); + // static void LLHUDObject::updateAll() { - LLFastTimer ftm(LLFastTimer::FTM_HUD_UPDATE); + LLFastTimer ftm(FTM_HUD_UPDATE); LLHUDText::updateAll(); LLHUDIcon::updateAll(); sortObjects(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index c71262c311..8086400493 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -957,7 +957,7 @@ void LLHUDText::updateAll() { continue; } - if (src_textp->mSoftScreenRect.rectInRect(&dst_textp->mSoftScreenRect)) + if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect)) { LLRectf intersect_rect = src_textp->mSoftScreenRect; intersect_rect.intersectWith(dst_textp->mSoftScreenRect); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 0b4e0f9317..72e2bb02d5 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1097,66 +1097,58 @@ BOOL LLFloaterIMPanel::postBuild() mVisibleSignal.connect(boost::bind(&LLFloaterIMPanel::onVisibilityChange, this, _2)); - requires("chat_editor"); - requires("im_history"); - - if (checkRequirements()) - { - mInputEditor = getChild("chat_editor"); - mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); - mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); - mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); - mInputEditor->setCommitCallback( onCommitChat, this ); - mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setRevertOnEsc( FALSE ); - mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); - - childSetAction("profile_callee_btn", onClickProfile, this); - childSetAction("group_info_btn", onClickGroupInfo, this); + mInputEditor = getChild("chat_editor"); + mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); + mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); + mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); + mInputEditor->setCommitCallback( onCommitChat, this ); + mInputEditor->setCommitOnFocusLost( FALSE ); + mInputEditor->setRevertOnEsc( FALSE ); + mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); - childSetAction("start_call_btn", onClickStartCall, this); - childSetAction("end_call_btn", onClickEndCall, this); - childSetAction("send_btn", onClickSend, this); - childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this); + childSetAction("profile_callee_btn", onClickProfile, this); + childSetAction("group_info_btn", onClickGroupInfo, this); - childSetAction("moderator_kick_speaker", onKickSpeaker, this); - //LLButton* close_btn = getChild("close_btn"); - //close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); + childSetAction("start_call_btn", onClickStartCall, this); + childSetAction("end_call_btn", onClickEndCall, this); + childSetAction("send_btn", onClickSend, this); + childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this); - mHistoryEditor = getChild("im_history"); - mHistoryEditor->setParseHTML(TRUE); - mHistoryEditor->setParseHighlights(TRUE); + childSetAction("moderator_kick_speaker", onKickSpeaker, this); + //LLButton* close_btn = getChild("close_btn"); + //close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); - if ( IM_SESSION_GROUP_START == mDialog ) - { - childSetEnabled("profile_btn", FALSE); - } - - if(!mProfileButtonEnabled) - { - childSetEnabled("profile_callee_btn", FALSE); - } + mHistoryEditor = getChild("im_history"); + mHistoryEditor->setParseHTML(TRUE); + mHistoryEditor->setParseHighlights(TRUE); - sTitleString = getString("title_string"); - sTypingStartString = getString("typing_start_string"); - sSessionStartString = getString("session_start_string"); + if ( IM_SESSION_GROUP_START == mDialog ) + { + childSetEnabled("profile_btn", FALSE); + } + + if(!mProfileButtonEnabled) + { + childSetEnabled("profile_callee_btn", FALSE); + } - if (mSpeakerPanel) - { - mSpeakerPanel->refreshSpeakers(); - } + sTitleString = getString("title_string"); + sTypingStartString = getString("typing_start_string"); + sSessionStartString = getString("session_start_string"); - if (mDialog == IM_NOTHING_SPECIAL) - { - childSetAction("mute_btn", onClickMuteVoice, this); - childSetCommitCallback("speaker_volume", onVolumeChange, this); - } + if (mSpeakerPanel) + { + mSpeakerPanel->refreshSpeakers(); + } - setDefaultBtn("send_btn"); - return TRUE; + if (mDialog == IM_NOTHING_SPECIAL) + { + childSetAction("mute_btn", onClickMuteVoice, this); + childSetCommitCallback("speaker_volume", onVolumeChange, this); } - return FALSE; + setDefaultBtn("send_btn"); + return TRUE; } void* LLFloaterIMPanel::createSpeakersPanel(void* data) @@ -1385,8 +1377,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 else { // Convert the name to a hotlink and add to message. - const LLStyleSP &source_style = LLStyleMap::instance().lookupAgent(source); - mHistoryEditor->appendStyledText(name + separator_string, false, prepend_newline, source_style); + mHistoryEditor->appendStyledText(name + separator_string, false, prepend_newline, LLStyleMap::instance().lookupAgent(source)); } prepend_newline = false; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6ad483a2f1..e3902bffa0 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -69,7 +69,6 @@ #include "llviewerwindow.h" #include "llnotify.h" #include "llviewerregion.h" -#include "llviewertexteditor.h" #include "lltrans.h" #include "llfirstuse.h" @@ -847,8 +846,13 @@ BOOL LLIncomingCallDialog::postBuild() EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger(); std::string call_type = getString("VoiceInviteP2P"); - std::string caller_name = mPayload["caller_name"].asString() + " "; - setTitle(caller_name + call_type); + std::string caller_name = mPayload["caller_name"].asString(); + if (caller_name == "anonymous") + { + caller_name = getString("anonymous"); + } + + setTitle(caller_name + " " + call_type); // If it is not a P2P invite, then it's an AdHoc invite if ( type != IM_SESSION_P2P_INVITE ) @@ -856,8 +860,8 @@ BOOL LLIncomingCallDialog::postBuild() call_type = getString("VoiceInviteAdHoc"); } - LLViewerTextEditor* text = getChild("caller name"); - text->setEmbeddedText(caller_name + call_type); + LLUICtrl* caller_name_widget = getChild("caller name"); + caller_name_widget->setValue(caller_name + " " + call_type); LLAvatarIconCtrl* icon = getChild("avatar_icon"); icon->setValue(caller_id); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 54802ee762..efa97de692 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3684,8 +3684,8 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // commented out for DEV-32347 //items.push_back(std::string("Restore to Last Position")); - LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE); - LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE); + LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); + LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); LLVOAvatar *avatarp = gAgent.getAvatarObject(); if (attach_menu && (attach_menu->getChildCount() == 0) diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index cdfb15fd71..63a40e40a0 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -227,7 +227,7 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) llwarns << "Error loading navigation bar context menu" << llendl; } - getTextEntry()->setRightClickedCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked,this,_2,_3,_4)); + getTextEntry()->setRightMouseUpCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked,this,_2,_3,_4)); updateWidgetlayout(); // - Make the "Add landmark" button updated when either current parcel gets changed diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 9a66507eae..713c44d366 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -103,7 +103,7 @@ const std::string LLTeleportHistoryMenuItem::ICON_IMG_FORWARD("teleport_history_ LLTeleportHistoryMenuItem::Params::Params(EType type, std::string title) { item_type(type); - font.name("SansSerif"); + font.name("SANSSERIF"); if (type == TYPE_CURRENT) font.style("BOLD"); @@ -123,7 +123,6 @@ LLTeleportHistoryMenuItem::LLTeleportHistoryMenuItem(const Params& p) icon_params.rect(LLRect(0, ICON_HEIGHT, ICON_WIDTH, 0)); icon_params.mouse_opaque(false); icon_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); - icon_params.tab_stop(false); icon_params.visible(false); mArrowIcon = LLUICtrlFactory::create (icon_params); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 32d7bc94ff..da9f50a2bc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -208,8 +208,7 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons { std::string start_line = line.substr(0, chat.mFromName.length() + 1); line = line.substr(chat.mFromName.length() + 1); - const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL); - edit->appendStyledText(start_line, false, prepend_newline, sourceStyle); + edit->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL)); prepend_newline = false; } edit->appendColoredText(line, false, prepend_newline, color); @@ -343,6 +342,7 @@ BOOL LLNearbyChat::handleMouseDown (S32 x, S32 y, MASK mask) S32 local_y = caption_local_y - nearby_speakers_btn->getRect().mBottom; if(nearby_speakers_btn->pointInView(local_x, local_y)) { + onNearbySpeakers(); bringToFront( x, y ); return true; diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 50e31e85e4..0696d41732 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -65,7 +65,7 @@ LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p) , mGestureLabelTimer() , mLabel(p.label) { - setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this, _1)); + setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this)); // now register us as observer since we have a place to put the results LLGestureManager::instance().addObserver(this); @@ -82,41 +82,33 @@ LLGestureComboBox::~LLGestureComboBox() void LLGestureComboBox::refreshGestures() { //store current selection so we can maintain it - std::string cur_gesture = getValue().asString(); + LLSD cur_gesture = getValue(); selectFirstItem(); // clear clearRows(); + mGestures.clear(); - // collect list of unique gestures - std::map unique; LLGestureManager::item_map_t::iterator it; + LLSD::Integer idx(0); for (it = LLGestureManager::instance().mActive.begin(); it != LLGestureManager::instance().mActive.end(); ++it) { LLMultiGesture* gesture = (*it).second; if (gesture) { - if (!gesture->mTrigger.empty()) - { - unique[gesture->mTrigger] = TRUE; - } + addSimpleElement(gesture->mName, ADD_BOTTOM, LLSD(idx)); + mGestures.push_back(gesture); + idx++; } } - // add unique gestures - std::map ::iterator it2; - for (it2 = unique.begin(); it2 != unique.end(); ++it2) - { - addSimpleElement((*it2).first); - } - sortByName(); // Insert label after sorting, at top, with separator below it addSeparator(ADD_TOP); addSimpleElement(mLabel, ADD_TOP); - if (!cur_gesture.empty()) + if (cur_gesture.isDefined()) { - selectByValue(LLSD(cur_gesture)); + selectByValue(cur_gesture); } else { @@ -124,7 +116,7 @@ void LLGestureComboBox::refreshGestures() } } -void LLGestureComboBox::onCommitGesture(LLUICtrl* ctrl) +void LLGestureComboBox::onCommitGesture() { LLCtrlListInterface* gestures = getListInterface(); if (gestures) @@ -134,19 +126,16 @@ void LLGestureComboBox::onCommitGesture(LLUICtrl* ctrl) { return; } - const std::string& trigger = gestures->getSelectedValue().asString(); - // pretend the user chatted the trigger string, to invoke - // substitution and logging. - std::string text(trigger); - std::string revised_text; - LLGestureManager::instance().triggerAndReviseString(text, &revised_text); - - revised_text = utf8str_trim(revised_text); - if (!revised_text.empty()) + index = gestures->getSelectedValue().asInteger(); + LLMultiGesture* gesture = mGestures.at(index); + if(gesture) { - // Don't play nodding animation - LLNearbyChatBar::sendChatFromViewer(revised_text, CHAT_TYPE_NORMAL, FALSE); + LLGestureManager::instance().playGesture(gesture); + if(!gesture->mReplaceText.empty()) + { + LLNearbyChatBar::sendChatFromViewer(gesture->mReplaceText, CHAT_TYPE_NORMAL, FALSE); + } } } @@ -267,9 +256,6 @@ void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - if (!self->mChatBox) - return; - LLWString raw_text = self->mChatBox->getWText(); // Can't trim the end, because that will cause autocompletion @@ -429,7 +415,7 @@ void LLNearbyChatBar::sendChat( EChatType type ) void LLNearbyChatBar::onChatBoxCommit() { - if (mChatBox && mChatBox->getText().length() > 0) + if (mChatBox->getText().length() > 0) { sendChat(CHAT_TYPE_NORMAL); } @@ -501,7 +487,7 @@ void LLNearbyChatBar::startChat(const char* line) LLNearbyChatBar* cb = bt->getNearbyChatBar(); - if (!cb || !cb->mChatBox) + if (!cb ) return; bt->setVisible(TRUE); @@ -527,7 +513,7 @@ void LLNearbyChatBar::stopChat() LLNearbyChatBar* cb = bt->getNearbyChatBar(); - if (!cb || !cb->mChatBox) + if (!cb) return; cb->mChatBox->setFocus(FALSE); diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index 4b0c42c3c0..19177e37b3 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -53,7 +53,7 @@ public: ~LLGestureComboBox(); void refreshGestures(); - void onCommitGesture(LLUICtrl* ctrl); + void onCommitGesture(); virtual void draw(); // LLGestureManagerObserver trigger @@ -61,6 +61,7 @@ public: protected: LLFrameTimer mGestureLabelTimer; + std::vector mGestures; std::string mLabel; }; diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index a56688d862..8124d4b36a 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -68,6 +68,8 @@ LLNearbyChatHandler::~LLNearbyChatHandler() } void LLNearbyChatHandler::processChat(const LLChat& chat_msg) { + if(chat_msg.mMuted == TRUE) + return; if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull()) LLRecentPeople::instance().add(chat_msg.mFromID); diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 42522942f3..f58f993a2e 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -57,8 +57,8 @@ #include "lllineeditor.h" #include "lltextbox.h" #include "llcombobox.h" -#include "llviewertexteditor.h" #include "lltexturectrl.h" +#include "lltexteditor.h" #include "lluiconstants.h" #include "llurldispatcher.h" // for classified HTML detail click teleports #include "lluictrlfactory.h" @@ -246,8 +246,7 @@ BOOL LLPanelClassified::postBuild() mDescEditor->setCommitOnFocusLost(TRUE); mDescEditor->setFocusReceivedCallback(focusReceived, this); mDescEditor->setCommitCallback(onCommitAny, this); - mDescEditor->setTabsToNextField(TRUE); - + mLocationEditor = getChild("location_editor"); mSetBtn = getChild( "set_location_btn"); diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index d95240e30c..8caa7d85eb 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -50,6 +50,7 @@ #include "llscrolllistcell.h" #include "lltextbox.h" #include "lltabcontainer.h" +#include "lltexteditor.h" #include "lltrans.h" #include "lltransactiontypes.h" #include "lltrans.h" diff --git a/indra/newview/llpanelgrouplandmoney.h b/indra/newview/llpanelgrouplandmoney.h index 73c52cdf2e..0f275ea9a8 100644 --- a/indra/newview/llpanelgrouplandmoney.h +++ b/indra/newview/llpanelgrouplandmoney.h @@ -37,10 +37,6 @@ #include "llmap.h" #include "lluuid.h" -#include "llbutton.h" -#include "lltexteditor.h" -#include "llpanel.h" - class LLPanelGroupLandMoney : public LLPanelGroupTab { public: diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index f06342ebfc..56042f6bff 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -508,7 +508,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) mNoticesList->addElement(row, ADD_BOTTOM); } - mNoticesList->sortItems(); + mNoticesList->updateSort(); } void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data) diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index 2cb7fd8c14..c6840721a3 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -48,7 +48,7 @@ #include "lllineeditor.h" #include "lluiconstants.h" #include "lltextbox.h" -#include "llviewertexteditor.h" +#include "lltexteditor.h" #include "lltexturectrl.h" #include "lltrans.h" #include "llworldmap.h" diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 39f7d41a8d..cf91972e8b 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -149,14 +149,12 @@ BOOL LLPanelPlaces::postBuild() } mPlaceInfo = getChild("panel_place_info"); - if (!mPlaceInfo) - return FALSE; LLButton* back_btn = mPlaceInfo->getChild("back_btn"); - if (back_btn) - { - back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); - } + back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); + + // *TODO: Assign the action to an appropriate event. + mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::toggleMediaPanel, this)); return TRUE; } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index ce9fcd9da2..cadab71ba8 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -101,14 +101,6 @@ BOOL LLPreviewNotecard::postBuild() childSetText("desc", item->getDescription()); childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe); - LLViewerTextEditor* editor = getChild("Notecard Editor"); - - if (editor) - { - editor->setWordWrap(TRUE); - editor->setHandleEditKeysDirectly(TRUE); - } - return LLPreview::postBuild(); } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index ad978cc5b3..49b9bbadfb 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -340,10 +340,6 @@ BOOL LLScriptEdCore::postBuild() childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this); mEditor = getChild("Script Editor"); - mEditor->setFollowsAll(); - mEditor->setHandleEditKeysDirectly(TRUE); - mEditor->setEnabled(TRUE); - mEditor->setWordWrap(TRUE); childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE)); @@ -459,12 +455,12 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) return; } - const LLTextSegment* segment = NULL; - std::vector selected_segments; + LLTextSegmentPtr segment = NULL; + std::vector selected_segments; mEditor->getSelectedSegments(selected_segments); // try segments in selection range first - std::vector::iterator segment_iter; + std::vector::iterator segment_iter; for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter) { if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD) @@ -477,7 +473,7 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) // then try previous segment in case we just typed it if (!segment) { - const LLTextSegment* test_segment = mEditor->getPreviousSegment(); + const LLTextSegmentPtr test_segment = mEditor->getPreviousSegment(); if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::WORD) { segment = test_segment; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 9990c22dac..2e005834b5 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -158,7 +158,7 @@ void LLSideTrayTab::arrange(S32 width, S32 height ) S32 offset = 0; - LLView* title_panel = getChildView(TAB_PANEL_CAPTION_NAME, true, false); + LLView* title_panel = findChildView(TAB_PANEL_CAPTION_NAME, true); if(title_panel) { @@ -181,7 +181,7 @@ void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent ) return; S32 offset = 0; - LLView* title_panel = getChildView(TAB_PANEL_CAPTION_NAME, true, false); + LLView* title_panel = findChildView(TAB_PANEL_CAPTION_NAME, true); if(title_panel) { @@ -612,7 +612,7 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para child_vector_const_iter_t child_it; for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLView* view = (*child_it)->getChildView(panel_name,true,false); + LLView* view = (*child_it)->findChildView(panel_name,true); if(view) { onTabButtonClick((*child_it)->getName()); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index c4364ed6ca..c2fce08ae4 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -49,6 +49,9 @@ #include "lloctree.h" #include "llvoavatar.h" +static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling"); +static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); + const F32 SG_OCCLUSION_FUDGE = 0.25f; #define SG_DISCARD_TOLERANCE 0.01f @@ -570,6 +573,8 @@ void LLSpatialGroup::rebuildMesh() } } +static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); + void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { if (!gPipeline.hasRenderType(mDrawableType)) @@ -588,7 +593,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) return; } - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); + LLFastTimer ftm(FTM_REBUILD_VBO); group->clearDrawMap(); @@ -1256,6 +1261,7 @@ BOOL LLSpatialGroup::rebound() return TRUE; } +static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); void LLSpatialGroup::checkOcclusion() { if (LLPipeline::sUseOcclusion > 1) @@ -1267,7 +1273,7 @@ void LLSpatialGroup::checkOcclusion() } else if (isState(QUERY_PENDING)) { //otherwise, if a query is pending, read it back - LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK); + LLFastTimer t(FTM_OCCLUSION_READBACK); GLuint res = 1; if (!isState(DISCARD_QUERY) && mOcclusionQuery) { @@ -1312,7 +1318,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) else { { - LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); + LLFastTimer t(FTM_RENDER_OCCLUSION); if (!mOcclusionQuery) { @@ -1873,7 +1879,7 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result { BOOL temp = sFreezeState; sFreezeState = FALSE; - LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); + LLFastTimer ftm(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); sFreezeState = temp; @@ -1891,19 +1897,19 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result } else if (LLPipeline::sShadowRender) { - LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); + LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCullShadow culler(&camera); culler.traverse(mOctree); } else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) { - LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); + LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCullNoFarClip culler(&camera); culler.traverse(mOctree); } else { - LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); + LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCull culler(&camera); culler.traverse(mOctree); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 04a3b52e98..222672deff 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1001,9 +1001,6 @@ bool idle_startup() } - //For HTML parsing in text boxes. - LLTextEditor::setLinkColor( LLUIColorTable::instance().getColor("HTMLLinkColor") ); - // Load URL History File LLURLHistory::loadFile("url_history.xml"); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 569e7b3397..8a5de61280 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -265,7 +265,7 @@ BOOL LLStatusBar::postBuild() mHideNavbarContextMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gMenuHolder->addChild(mHideNavbarContextMenu); - gMenuBarView->setRightClickedCallback(boost::bind(&LLStatusBar::onMainMenuRightClicked, this, _1, _2, _3, _4)); + gMenuBarView->setRightMouseDownCallback(boost::bind(&LLStatusBar::onMainMenuRightClicked, this, _1, _2, _3, _4)); return TRUE; } diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp index a422db1cc1..fc125dcf9c 100644 --- a/indra/newview/llstylemap.cpp +++ b/indra/newview/llstylemap.cpp @@ -38,83 +38,53 @@ #include "llviewercontrol.h" #include "llagent.h" -LLStyleMap::LLStyleMap() -{ -} - -LLStyleMap::~LLStyleMap() -{ -} - -LLStyleMap &LLStyleMap::instance() -{ - static LLStyleMap style_map; - return style_map; -} - -// This is similar to the [] accessor except that if the entry doesn't already exist, -// then this will create the entry. -const LLStyleSP &LLStyleMap::lookupAgent(const LLUUID &source) +const LLStyle::Params &LLStyleMap::lookupAgent(const LLUUID &source) { // Find this style in the map or add it if not. This map holds links to residents' profiles. - if (find(source) == end()) + if (mMap.find(source) == mMap.end()) { - LLStyleSP style(new LLStyle); - style->setVisible(true); - style->setFontName(LLStringUtil::null); + LLStyle::Params style_params; if (source != LLUUID::null && source != gAgent.getID() ) { - style->setColor(LLUIColorTable::instance().getColor("HTMLLinkColor")); - std::string link = llformat("secondlife:///app/agent/%s/about",source.asString().c_str()); - style->setLinkHREF(link); + style_params.color.control = "HTMLLinkColor"; + style_params.link_href = llformat("secondlife:///app/agent/%s/about",source.asString().c_str()); } else { // Make the resident's own name white and don't make the name clickable. - style->setColor(LLColor4::white); + style_params.color = LLColor4::white; } - (*this)[source] = style; + + mMap[source] = LLStyle::Params(); } - return (*this)[source]; + return mMap[source]; } // This is similar to lookupAgent for any generic URL encoded style. -const LLStyleSP &LLStyleMap::lookup(const LLUUID& id, const std::string& link) +const LLStyle::Params &LLStyleMap::lookup(const LLUUID& id, const std::string& link) { // Find this style in the map or add it if not. - iterator iter = find(id); - if (iter == end()) + style_map_t::iterator iter = mMap.find(id); + if (iter == mMap.end()) { - LLStyleSP style(new LLStyle); - style->setVisible(true); - style->setFontName(LLStringUtil::null); + LLStyle::Params style_params; + if (id != LLUUID::null && !link.empty()) { - style->setColor(LLUIColorTable::instance().getColor("HTMLLinkColor")); - style->setLinkHREF(link); + style_params.color.control = "HTMLLinkColor"; + style_params.link_href = link; } else - style->setColor(LLColor4::white); - (*this)[id] = style; + { + style_params.color = LLColor4::white; + } + mMap[id] = style_params; } else { - LLStyleSP style = (*iter).second; - if ( style->getLinkHREF() != link ) - { - style->setLinkHREF(link); - } + iter->second.link_href = link; } - return (*this)[id]; + return mMap[id]; } -void LLStyleMap::update() -{ - for (style_map_t::iterator iter = begin(); iter != end(); ++iter) - { - LLStyleSP &style = iter->second; - // Update the link color in case it has been changed. - style->setColor(LLUIColorTable::instance().getColor("HTMLLinkColor")); - } -} diff --git a/indra/newview/llstylemap.h b/indra/newview/llstylemap.h index 254509ea1d..d29ff1ae28 100644 --- a/indra/newview/llstylemap.h +++ b/indra/newview/llstylemap.h @@ -36,24 +36,22 @@ #include "llstyle.h" #include "lluuid.h" +#include "llsingleton.h" // Lightweight class for holding and managing mappings between UUIDs and links. // Used (for example) to create clickable name links off of IM chat. -typedef std::map style_map_t; +typedef std::map style_map_t; -class LLStyleMap : public style_map_t +class LLStyleMap : public LLSingleton { public: - LLStyleMap(); - ~LLStyleMap(); // Just like the [] accessor but it will add the entry in if it doesn't exist. - const LLStyleSP &lookupAgent(const LLUUID &source); - const LLStyleSP &lookup(const LLUUID &source, const std::string& link); - static LLStyleMap &instance(); + const LLStyle::Params &lookupAgent(const LLUUID &source); + const LLStyle::Params &lookup(const LLUUID &source, const std::string& link); - // Forces refresh of the entries, call when something changes (e.g. link color). - void update(); +private: + style_map_t mMap; }; #endif // LL_LLSTYLE_MAP_H diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 8a61f6cfda..6f26b4077c 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -40,12 +40,12 @@ #include "lliconctrl.h" #include "llnotify.h" #include "lltextbox.h" -#include "llviewertexteditor.h" +#include "lltexteditor.h" #include "lluiconstants.h" #include "llui.h" #include "llviewercontrol.h" #include "lltrans.h" -#include "llinitparam.h" +#include "llstyle.h" #include "llglheaders.h" #include "llagent.h" @@ -75,23 +75,25 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification const std::string& from_name = payload["sender_name"].asString(); std::stringstream from; from << from_name << "/" << groupData.mName; - LLTextBox* pTitleText = this->getChild("title"); + LLTextBox* pTitleText = getChild("title"); pTitleText->setValue(from.str()); //message body const std::string& subject = payload["subject"].asString(); const std::string& message = payload["message"].asString(); - LLTextEditor* pMessageText = getChild< LLTextEditor>("message"); + LLTextEditor* pMessageText = getChild("message"); pMessageText->setValue(""); pMessageText->setEnabled(FALSE); - pMessageText->setTakesFocus(FALSE); - static const LLStyleSP headerstyle(new LLStyle(true, textColor, - "SansSerifBig")); - static const LLStyleSP datestyle(new LLStyle(true, textColor, "serif")); + LLStyle::Params date_style; + date_style.color = textColor; + date_style.font.name = "SANSSERIF"; - pMessageText->appendStyledText(subject + "\n",false,false,headerstyle); + LLStyle::Params header_style_params; + header_style_params.color = textColor; + header_style_params.font = LLFontGL::getFontSansSerifBig(); + pMessageText->appendStyledText(subject + "\n",false,false,header_style_params); std::string timeStr = "["+LLTrans::getString("UTCTimeWeek")+"],[" +LLTrans::getString("UTCTimeDay")+"] [" @@ -106,7 +108,10 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification LLSD substitution; substitution["datetime"] = (S32) notice_date.secondsSinceEpoch(); LLStringUtil::format(timeStr, substitution); - pMessageText->appendStyledText(timeStr, false, false, datestyle); + LLStyle::Params date_style_params; + date_style_params.color = textColor; + date_style_params.font = LLFontGL::getFontMonospace(); + pMessageText->appendStyledText(timeStr, false, false, date_style); pMessageText->appendColoredText(std::string("\n\n") + message, false, false, textColor); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index a7b57802c1..844c54da6a 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -107,7 +107,6 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas common_params.rect(LLRect(x, y, x+32, TOP-32)); common_params.mouse_opaque(false); common_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); - common_params.tab_stop(false); if (mIsTip) { @@ -180,8 +179,6 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas params.mouse_opaque(false); params.bg_readonly_color(LLColor4::transparent); params.text_readonly_color(LLUIColorTable::instance().getColor("NotifyTextColor")); - params.takes_non_scroll_clicks(false); - params.hide_scrollbar(true); params.enabled(false); params.hide_border(true); text = LLUICtrlFactory::create (params); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index f08c287529..8e65c7e65e 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -207,11 +207,17 @@ void display_stats() } } +static LLFastTimer::DeclareTimer FTM_PICK("Picking"); +static LLFastTimer::DeclareTimer FTM_RENDER("Render", true); +static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky"); +static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures"); +static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images"); + // Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLMemType mt_render(LLMemType::MTYPE_RENDER); - LLFastTimer t(LLFastTimer::FTM_RENDER); + LLFastTimer t(FTM_RENDER); if (LLPipeline::sRenderFrameTest) { @@ -258,7 +264,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gViewerWindow->checkSettings(); { - LLFastTimer ftm(LLFastTimer::FTM_PICK); + LLFastTimer ftm(FTM_PICK); LLAppViewer::instance()->pingMainloopTimeout("Display:Pick"); gViewerWindow->performPick(); } @@ -504,7 +510,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) { LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); - LLFastTimer t(LLFastTimer::FTM_UPDATE_TEXTURES); + LLFastTimer t(FTM_UPDATE_TEXTURES); if (LLViewerDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); @@ -616,7 +622,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP); { - LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); + LLFastTimer ftm(FTM_CLIENT_COPY); LLVertexBuffer::clientCopy(0.016); } @@ -687,7 +693,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE); - LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE); + LLFastTimer t(FTM_IMAGE_UPDATE); LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); @@ -730,7 +736,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY); LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); - LLFastTimer t(LLFastTimer::FTM_UPDATE_SKY); + LLFastTimer t(FTM_UPDATE_SKY); gSky.updateSky(); } @@ -860,7 +866,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); if (!for_snapshot) { - LLFastTimer t(LLFastTimer::FTM_RENDER_UI); + LLFastTimer t(FTM_RENDER_UI); render_ui(); } @@ -1040,6 +1046,7 @@ BOOL setup_hud_matrices(const LLRect& screen_region) } } +static LLFastTimer::DeclareTimer FTM_SWAP("Swap"); void render_ui(F32 zoom_factor, int subfield) { @@ -1075,7 +1082,7 @@ void render_ui(F32 zoom_factor, int subfield) gGL.color4f(1,1,1,1); if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { - LLFastTimer t(LLFastTimer::FTM_RENDER_UI); + LLFastTimer t(FTM_RENDER_UI); if (!gDisconnected) { @@ -1102,7 +1109,7 @@ void render_ui(F32 zoom_factor, int subfield) if (gDisplaySwapBuffers) { - LLFastTimer t(LLFastTimer::FTM_SWAP); + LLFastTimer t(FTM_SWAP); gViewerWindow->mWindow->swapBuffers(); } gDisplaySwapBuffers = TRUE; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 499632def3..207b9592b8 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -458,13 +458,13 @@ void set_underclothes_menu_options() { if (gMenuHolder && gAgent.isTeen()) { - gMenuHolder->getChild("Self Underpants", TRUE)->setVisible(FALSE); - gMenuHolder->getChild("Self Undershirt", TRUE)->setVisible(FALSE); + gMenuHolder->getChild("Self Underpants")->setVisible(FALSE); + gMenuHolder->getChild("Self Undershirt")->setVisible(FALSE); } if (gMenuBarView && gAgent.isTeen()) { - gMenuBarView->getChild("Menu Underpants", TRUE)->setVisible(FALSE); - gMenuBarView->getChild("Menu Undershirt", TRUE)->setVisible(FALSE); + gMenuBarView->getChild("Menu Underpants")->setVisible(FALSE); + gMenuBarView->getChild("Menu Undershirt")->setVisible(FALSE); } } @@ -567,8 +567,8 @@ void init_menus() gAFKMenu = gMenuBarView->getChild("Set Away", TRUE); gBusyMenu = gMenuBarView->getChild("Set Busy", TRUE); - gAttachSubMenu = gMenuBarView->getChildMenuByName("Attach Object", TRUE); - gDetachSubMenu = gMenuBarView->getChildMenuByName("Detach Object", TRUE); + gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); + gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE); gMenuBarView->createJumpKeys(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 33568bf3cb..d83f3d9207 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3302,11 +3302,12 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); } +static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects"); void process_kill_object(LLMessageSystem *mesgsys, void **user_data) { - LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS); + LLFastTimer t(FTM_PROCESS_OBJECTS); LLUUID id; U32 local_id; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index ec11e0aee2..99723f86a7 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -115,11 +115,13 @@ S32 LLViewerObject::sAxisArrowLength(50); BOOL LLViewerObject::sPulseEnabled(FALSE); BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE +static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); + // static LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) { LLViewerObject *res = NULL; - LLFastTimer t1(LLFastTimer::FTM_CREATE_OBJECT); + LLFastTimer t1(FTM_CREATE_OBJECT); switch (pcode) { diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 8939faeb91..a8232e9a9d 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -258,13 +258,15 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, } } +static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects"); + void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type, bool cached, bool compressed) { LLMemType mt(LLMemType::MTYPE_OBJECT_PROCESS_UPDATE); - LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS); + LLFastTimer t(FTM_PROCESS_OBJECTS); LLVector3d camera_global = gAgent.getCameraPositionGlobal(); LLViewerObject *objectp; @@ -1304,12 +1306,13 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi } +static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender) { LLMemType mt(LLMemType::MTYPE_OBJECT); - LLFastTimer t(LLFastTimer::FTM_CREATE_OBJECT); + LLFastTimer t(FTM_CREATE_OBJECT); LLUUID fullid; if (uuid == LLUUID::null) diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index ec39819bc8..cfb8340462 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -631,6 +631,8 @@ void LLViewerPartSim::shift(const LLVector3 &offset) } } +static LLFastTimer::DeclareTimer FTM_SIMULATE_PARTICLES("Simulate Particles"); + void LLViewerPartSim::updateSimulation() { LLMemType mt(LLMemType::MTYPE_PARTICLES); @@ -644,7 +646,7 @@ void LLViewerPartSim::updateSimulation() return; } - LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES); + LLFastTimer ftm(FTM_SIMULATE_PARTICLES); // Start at a random particle system so the same // particle system doesn't always get first pick at the diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 709fcdcf01..444d8e3164 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -594,14 +594,14 @@ void update_statistics(U32 frame_count) LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment")); #endif - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::NamedTimer::getRootNamedTimer().getFrameState())); - F64 idle_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IDLE); - F64 network_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_NETWORK); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame")); + F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle"); + F64 network_secs = gDebugView->mFastTimerView->getTime("Network"); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IMAGE_UPDATE)); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_STATESORT )); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_RENDER_GEOMETRY)); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images")); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State")); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry")); LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 9e0713b494..7565c86696 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -62,6 +62,7 @@ #include "llnotecard.h" #include "llmemorystream.h" #include "llmenugl.h" +#include "llscrollcontainer.h" #include "llavataractions.h" #include "llappviewer.h" // for gPacificDaylightTime @@ -108,6 +109,105 @@ public: } }; +// +// class LLEmbeddedItemSegment +// + +const S32 EMBEDDED_ITEM_LABEL_PADDING = 2; + +class LLEmbeddedItemSegment : public LLTextSegment +{ +public: + LLEmbeddedItemSegment(S32 pos, LLUIImagePtr image, LLPointer inv_item, LLTextEditor& editor) + : LLTextSegment(pos, pos + 1), + mImage(image), + mLabel(utf8str_to_wstring(inv_item->getName())), + mItem(inv_item), + mEditor(editor), + mHasMouseHover(false) + { + + mStyle = new LLStyle(LLStyle::Params().font(LLFontGL::getFontSansSerif())); + mToolTip = inv_item->getName() + '\n' + inv_item->getDescription(); + } + + /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const + { + if (num_chars == 0) + { + return 0; + } + else + { + return EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str()); + } + + } + //virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; + //virtual void updateLayout(const class LLTextEditor& editor); + + /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const + { + return 1; + } + /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) + { + LLRect image_rect = draw_rect; + image_rect.mRight = image_rect.mLeft + mImage->getWidth(); + image_rect.mTop = image_rect.mBottom + mImage->getHeight(); + mImage->draw(image_rect); + + LLColor4 color; + if (mEditor.getReadOnly()) + { + color = LLUIColorTable::instance().getColor("TextEmbeddedItemReadOnlyColor"); + } + else + { + color = LLUIColorTable::instance().getColor("TextEmbeddedItemColor"); + } + + F32 right_x; + mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mBottom, color, LLFontGL::LEFT, LLFontGL::BOTTOM, mHasMouseHover ? LLFontGL::UNDERLINE : 0, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &right_x); + return right_x; + } + + /*virtual*/ S32 getMaxHeight() const + { + return llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight())); + } + /*virtual*/ bool canEdit() const { return false; } + //virtual void unlinkFromDocument(class LLTextEditor* editor); + //virtual void linkToDocument(class LLTextEditor* editor); + + virtual void setHasMouseHover(bool hover) + { + mHasMouseHover = hover; + } + //virtual const LLColor4& getColor() const; + //virtual void setColor(const LLColor4 &color); + //virtual void setStyle(const LLStyleSP &style); + virtual BOOL getToolTip( std::string& msg ) const + { + msg = mToolTip; + return TRUE; + } + + /*virtual*/ const LLStyleSP getStyle() const { return mStyle; } + +private: + LLUIImagePtr mImage; + LLWString mLabel; + LLStyleSP mStyle; + std::string mToolTip; + LLPointer mItem; + LLTextEditor& mEditor; + bool mHasMouseHover; + +}; + + + //////////////////////////////////////////////////////////// // LLEmbeddedItems // @@ -130,13 +230,11 @@ public: // return true if there are no embedded items. bool empty(); - void bindEmbeddedChars(const LLFontGL* font) const; - void unbindEmbeddedChars(const LLFontGL* font) const; - BOOL insertEmbeddedItem(LLInventoryItem* item, llwchar* value, bool is_new); BOOL removeEmbeddedItem( llwchar ext_char ); BOOL hasEmbeddedItem(llwchar ext_char); // returns TRUE if /this/ editor has an entry for this item + LLUIImagePtr getItemImage(llwchar ext_char) const; void getEmbeddedItemList( std::vector >& items ); void addItems(const std::vector >& items); @@ -351,27 +449,13 @@ BOOL LLEmbeddedItems::hasEmbeddedItem(llwchar ext_char) return FALSE; } -void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font ) const -{ - if( sEntries.empty() ) - { - return; - } - for (std::set::const_iterator iter1 = mEmbeddedUsedChars.begin(); iter1 != mEmbeddedUsedChars.end(); ++iter1) +LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const +{ + LLInventoryItem* item = getEmbeddedItem(ext_char); + if (item) { - llwchar wch = *iter1; - item_map_t::iterator iter2 = sEntries.find(wch); - if (iter2 == sEntries.end()) - { - continue; - } - LLInventoryItem* item = iter2->second.mItem; - if (!item) - { - continue; - } - const char* img_name; + const char* img_name = ""; switch( item->getType() ) { case LLAssetType::AT_TEXTURE: @@ -428,27 +512,14 @@ void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font ) const case LLAssetType::AT_GESTURE: img_name = "inv_item_gesture.tga"; break; //TODO need img_name case LLAssetType::AT_FAVORITE: img_name = "inv_item_landmark.tga"; break; - default: llassert(0); continue; + default: llassert(0); } - LLUIImagePtr image = LLUI::getUIImage(img_name); - - font->addEmbeddedChar( wch, image->getImage(), item->getName() ); + return LLUI::getUIImage(img_name); } + return LLUIImagePtr(); } -void LLEmbeddedItems::unbindEmbeddedChars( const LLFontGL* font ) const -{ - if( sEntries.empty() ) - { - return; - } - - for (std::set::const_iterator iter1 = mEmbeddedUsedChars.begin(); iter1 != mEmbeddedUsedChars.end(); ++iter1) - { - font->removeEmbeddedChar(*iter1); - } -} void LLEmbeddedItems::addItems(const std::vector >& items) { @@ -613,30 +684,16 @@ BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* s } const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment ) + if( cur_segment && cur_segment->getToolTip( msg ) ) { - BOOL has_tool_tip = FALSE; - if( cur_segment->getStyle()->getIsEmbeddedItem() ) - { - LLWString wtip; - has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip); - msg = wstring_to_utf8str(wtip); - } - else - { - has_tool_tip = cur_segment->getToolTip( msg ); - } - if( has_tool_tip ) - { - // Just use a slop area around the cursor - // Convert rect local to screen coordinates - S32 SLOP = 8; - localPointToScreen( - x - SLOP, y - SLOP, - &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); - sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; - sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; - } + // Just use a slop area around the cursor + // Convert rect local to screen coordinates + S32 SLOP = 8; + localPointToScreen( + x - SLOP, y - SLOP, + &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); + sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; + sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; } return TRUE; } @@ -648,21 +705,8 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) // Let scrollbar have first dibs handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; - // enable I Agree checkbox if the user scrolled through entire text - BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); - if (mOnScrollEndCallback && was_scrolled_to_bottom) + if( !handled) { - mOnScrollEndCallback(mOnScrollEndData); - } - - if( !handled && mTakesNonScrollClicks) - { - if (!(mask & MASK_SHIFT)) - { - deselect(); - } - - BOOL start_select = TRUE; if( allowsEmbeddedItems() ) { setCursorAtLocalPos( x, y, FALSE ); @@ -685,192 +729,55 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) localPointToScreen(x, y, &screen_x, &screen_y ); LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); - start_select = FALSE; - } - else - { - mDragItem = NULL; - } - } - - if( start_select ) - { - // If we're not scrolling (handled by child), then we're selecting - if (mask & MASK_SHIFT) - { - S32 old_cursor_pos = mCursorPos; - setCursorAtLocalPos( x, y, TRUE ); - - if (hasSelection()) - { - /* Mac-like behavior - extend selection towards the cursor - if (mCursorPos < mSelectionStart - && mCursorPos < mSelectionEnd) - { - // ...left of selection - mSelectionStart = llmax(mSelectionStart, mSelectionEnd); - mSelectionEnd = mCursorPos; - } - else if (mCursorPos > mSelectionStart - && mCursorPos > mSelectionEnd) - { - // ...right of selection - mSelectionStart = llmin(mSelectionStart, mSelectionEnd); - mSelectionEnd = mCursorPos; - } - else - { - mSelectionEnd = mCursorPos; - } - */ - // Windows behavior - mSelectionEnd = mCursorPos; - } - else + if (hasTabStop()) { - mSelectionStart = old_cursor_pos; - mSelectionEnd = mCursorPos; + setFocus( TRUE ); } - // assume we're starting a drag select - mIsSelecting = TRUE; + handled = TRUE; } else { - setCursorAtLocalPos( x, y, TRUE ); - startSelection(); + mDragItem = NULL; } - gFocusMgr.setMouseCapture( this ); } - handled = TRUE; - } - - if (hasTabStop()) - { - setFocus(TRUE); - handled = TRUE; + if (!handled) + { + handled = LLTextEditor::handleMouseDown(x, y, mask); + } } - // Delay cursor flashing - resetKeystrokeTimer(); - return handled; } BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask) { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - BOOL handled = FALSE; + BOOL handled = LLTextEditor::handleHover(x, y, mask); - if (!mDragItem) + if(hasMouseCapture() && mDragItem) { - // leave hover segment active during drag and drop - mHoverSegment = NULL; - } - if(hasMouseCapture() ) - { - if( mIsSelecting ) - { - if (x != mLastSelectionX || y != mLastSelectionY) - { - mLastSelectionX = x; - mLastSelectionY = y; - } + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y ); - if( y > getTextRect().mTop ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 ); - } - else - if( y < getTextRect().mBottom ) - { - mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 ); - } + mScroller->autoScroll(x, y); - setCursorAtLocalPos( x, y, TRUE ); - mSelectionEnd = mCursorPos; - - updateScrollFromCursor(); - getWindow()->setCursor(UI_CURSOR_IBEAM); - } - else if( mDragItem ) + if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) - { - LLToolDragAndDrop::getInstance()->beginDrag( - LLAssetType::lookupDragAndDropType( mDragItem->getType() ), - mDragItem->getUUID(), - LLToolDragAndDrop::SOURCE_NOTECARD, - mPreviewID, mObjectID); + LLToolDragAndDrop::getInstance()->beginDrag( + LLAssetType::lookupDragAndDropType( mDragItem->getType() ), + mDragItem->getUUID(), + LLToolDragAndDrop::SOURCE_NOTECARD, + mPreviewID, mObjectID); - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); - } - getWindow()->setCursor(UI_CURSOR_HAND); + return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); } - - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl; + getWindow()->setCursor(UI_CURSOR_HAND); handled = TRUE; } - if( !handled ) - { - // Pass to children - handled = LLView::childrenHandleHover(x, y, mask) != NULL; - } - - if( handled ) - { - // Delay cursor flashing - resetKeystrokeTimer(); - } - - // Opaque - if( !handled && mTakesNonScrollClicks) - { - // Check to see if we're over an HTML-style link - if( !mSegments.empty() ) - { - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment ) - { - if(cur_segment->getStyle()->isLink()) - { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl; - getWindow()->setCursor(UI_CURSOR_HAND); - handled = TRUE; - } - else - if(cur_segment->getStyle()->getIsEmbeddedItem()) - { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl; - getWindow()->setCursor(UI_CURSOR_HAND); - //getWindow()->setCursor(UI_CURSOR_ARROW); - handled = TRUE; - } - mHoverSegment = cur_segment; - } - } - - if( !handled ) - { - lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl; - if (!mScrollbar->getVisible() || x < getRect().getWidth() - scrollbar_size) - { - getWindow()->setCursor(UI_CURSOR_IBEAM); - } - else - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } - handled = TRUE; - } - } - return handled; } @@ -903,13 +810,6 @@ BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) handled = LLTextEditor::handleMouseUp(x,y,mask); - // Used to enable I Agree checkbox if the user scrolled through entire text - BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); - if (mOnScrollEndCallback && was_scrolled_to_bottom) - { - mOnScrollEndCallback(mOnScrollEndData); - } - return handled; } @@ -949,24 +849,6 @@ BOOL LLViewerTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) return handled; } -BOOL LLViewerTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) -{ - BOOL handled = FALSE; - handled = childrenHandleMiddleMouseDown(x, y, mask) != NULL; - if (!handled) - { - handled = LLTextEditor::handleMiddleMouseDown(x, y, mask); - } - return handled; -} - -BOOL LLViewerTextEditor::handleMiddleMouseUp(S32 x, S32 y, MASK mask) -{ - BOOL handled = childrenHandleMiddleMouseUp(x, y, mask) != NULL; - - return handled; -} - BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -974,14 +856,15 @@ BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) // let scrollbar have first dibs handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL; - if( !handled && mTakesNonScrollClicks) + if( !handled) { if( allowsEmbeddedItems() ) { - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); - if( cur_segment && cur_segment->getStyle()->getIsEmbeddedItem() ) + S32 doc_index = getDocIndexFromLocalCoord(x, y, FALSE); + llwchar doc_char = getWText()[doc_index]; + if (mEmbeddedItemList->hasEmbeddedItem(doc_char)) { - if( openEmbeddedItemAtPos( cur_segment->getStart() ) ) + if( openEmbeddedItemAtPos( doc_index )) { deselect(); setFocus( FALSE ); @@ -989,47 +872,7 @@ BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask) } } } - - setCursorAtLocalPos( x, y, FALSE ); - deselect(); - - const LLWString &text = getWText(); - - if( isPartOfWord( text[mCursorPos] ) ) - { - // Select word the cursor is over - while ((mCursorPos > 0) && isPartOfWord(text[mCursorPos-1])) - { - mCursorPos--; - } - startSelection(); - - while ((mCursorPos < (S32)text.length()) && isPartOfWord( text[mCursorPos] ) ) - { - mCursorPos++; - } - - mSelectionEnd = mCursorPos; - } - else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) ) - { - // Select the character the cursor is over - startSelection(); - mCursorPos++; - mSelectionEnd = mCursorPos; - } - - // We don't want handleMouseUp() to "finish" the selection (and thereby - // set mSelectionEnd to where the mouse is), so we finish the selection here. - mIsSelecting = FALSE; - - // delay cursor flashing - resetKeystrokeTimer(); - - // take selection to 'primary' clipboard - updatePrimary(); - - handled = TRUE; + handled = LLTextEditor::handleDoubleClick(x, y, mask); } return handled; } @@ -1051,80 +894,78 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask, return FALSE; } - if (mTakesNonScrollClicks) + if (getEnabled() && acceptsTextInput()) { - if (getEnabled() && acceptsTextInput()) + switch( cargo_type ) { - switch( cargo_type ) + case DAD_CALLINGCARD: + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_CLOTHING: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: { - case DAD_CALLINGCARD: - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_CLOTHING: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: + LLInventoryItem *item = (LLInventoryItem *)cargo_data; + if( item && allowsEmbeddedItems() ) { - LLInventoryItem *item = (LLInventoryItem *)cargo_data; - if( item && allowsEmbeddedItems() ) + U32 mask_next = item->getPermissions().getMaskNextOwner(); + if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) { - U32 mask_next = item->getPermissions().getMaskNextOwner(); - if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - if( drop ) - { - deselect(); - S32 old_cursor = mCursorPos; - setCursorAtLocalPos( x, y, TRUE ); - S32 insert_pos = mCursorPos; - setCursorPos(old_cursor); - BOOL inserted = insertEmbeddedItem( insert_pos, item ); - if( inserted && (old_cursor > mCursorPos) ) - { - setCursorPos(mCursorPos + 1); - } - - updateLineStartList(); - } - *accept = ACCEPT_YES_COPY_MULTI; - } - else + if( drop ) { - *accept = ACCEPT_NO; - if (tooltip_msg.empty()) + deselect(); + S32 old_cursor = mCursorPos; + setCursorAtLocalPos( x, y, TRUE ); + S32 insert_pos = mCursorPos; + setCursorPos(old_cursor); + BOOL inserted = insertEmbeddedItem( insert_pos, item ); + if( inserted && (old_cursor > mCursorPos) ) { - // *TODO: Translate - tooltip_msg.assign("Only items with unrestricted\n" - "'next owner' permissions \n" - "can be attached to notecards."); + setCursorPos(mCursorPos + 1); } + + needsReflow(); + } + *accept = ACCEPT_YES_COPY_MULTI; } else { *accept = ACCEPT_NO; + if (tooltip_msg.empty()) + { + // *TODO: Translate + tooltip_msg.assign("Only items with unrestricted\n" + "'next owner' permissions \n" + "can be attached to notecards."); + } } - break; } - - default: + else + { *accept = ACCEPT_NO; - break; + } + break; } - } - else - { - // Not enabled + + default: *accept = ACCEPT_NO; + break; } - - handled = TRUE; - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLViewerTextEditor " << getName() << llendl; } + else + { + // Not enabled + *accept = ACCEPT_NO; + } + + handled = TRUE; + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLViewerTextEditor " << getName() << llendl; return handled; } @@ -1244,33 +1085,33 @@ llwchar LLViewerTextEditor::pasteEmbeddedItem(llwchar ext_char) return LL_UNKNOWN_CHAR; // item not found or list full } -void LLViewerTextEditor::bindEmbeddedChars(const LLFontGL* font) const +void LLViewerTextEditor::onValueChange(S32 start, S32 end) { - mEmbeddedItemList->bindEmbeddedChars( font ); + updateSegments(); + findEmbeddedItemSegments(start, end); } -void LLViewerTextEditor::unbindEmbeddedChars(const LLFontGL* font) const +void LLViewerTextEditor::findEmbeddedItemSegments(S32 start, S32 end) { - mEmbeddedItemList->unbindEmbeddedChars( font ); -} + LLWString text = getWText(); -BOOL LLViewerTextEditor::getEmbeddedItemToolTipAtPos(S32 pos, LLWString &msg) const -{ - if (pos < getLength()) + LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() ); + + // Start with i just after the first embedded item + for(S32 idx = start; idx < end; idx++ ) { - LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem(getWChar(pos)); - if( item ) + llwchar embedded_char = text[idx]; + if( embedded_char >= FIRST_EMBEDDED_CHAR + && embedded_char <= LAST_EMBEDDED_CHAR + && mEmbeddedItemList->hasEmbeddedItem(embedded_char) ) { - msg = utf8str_to_wstring(item->getName()); - msg += '\n'; - msg += utf8str_to_wstring(item->getDescription()); - return TRUE; + LLInventoryItem* itemp = mEmbeddedItemList->getEmbeddedItem(embedded_char); + LLUIImagePtr image = mEmbeddedItemList->getItemImage(embedded_char); + insertSegment(new LLEmbeddedItemSegment(idx, image, itemp, *this)); } } - return FALSE; } - BOOL LLViewerTextEditor::openEmbeddedItemAtPos(S32 pos) { if( pos < getLength()) diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h index 1a69c6869d..9567bfbc48 100644 --- a/indra/newview/llviewertexteditor.h +++ b/indra/newview/llviewertexteditor.h @@ -65,8 +65,6 @@ public: // mousehandler overrides virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask ); @@ -80,6 +78,8 @@ public: virtual BOOL importBuffer(const char* buffer, S32 length); virtual bool importStream(std::istream& str); virtual BOOL exportBuffer(std::string& buffer); + virtual void onValueChange(S32 start, S32 end); + void setNotecardInfo(const LLUUID& notecard_item_id, const LLUUID& object_id, const LLUUID& preview_id) { mNotecardInventoryID = notecard_item_id; @@ -106,11 +106,9 @@ public: private: // Embedded object operations + void findEmbeddedItemSegments(S32 start, S32 end); virtual llwchar pasteEmbeddedItem(llwchar ext_char); - virtual void bindEmbeddedChars(const LLFontGL* font) const; - virtual void unbindEmbeddedChars(const LLFontGL* font) const; - BOOL getEmbeddedItemToolTipAtPos(S32 pos, LLWString &wmsg) const; BOOL openEmbeddedItemAtPos( S32 pos ); BOOL openEmbeddedItem(LLInventoryItem* item, llwchar wc); @@ -128,6 +126,7 @@ private: static bool onNotecardDialog(const LLSD& notification, const LLSD& response ); LLPointer mDragItem; + LLTextSegment* mDragSegment; llwchar mDragItemChar; BOOL mDragItemSaved; class LLEmbeddedItems* mEmbeddedItemList; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7b01fe4280..83442dc2bb 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -75,6 +75,7 @@ const S32 IMAGES_MAX_PACKET_UPDATES = 1; // Only send N packets of IMAGES_PER_RE const F32 RESEND_IMAGE_REQUEST_TIME = 15.f; // seconds LLViewerTextureList gTextureList; +static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images"); /////////////////////////////////////////////////////////////////////////////// @@ -542,6 +543,7 @@ void LLViewerTextureList::dirtyImage(LLViewerFetchedTexture *image) } //////////////////////////////////////////////////////////////////////////// +static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images"); void LLViewerTextureList::updateImages(F32 max_time) { @@ -559,7 +561,7 @@ void LLViewerTextureList::updateImages(F32 max_time) max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); if (!mDirtyTextureList.empty()) { - LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY); + LLFastTimer t(FTM_IMAGE_MARK_DIRTY); gPipeline.dirtyPoolObjectTextures(mDirtyTextureList); mDirtyTextureList.clear(); } @@ -697,6 +699,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() return type_from_host; } */ +static LLFastTimer::DeclareTimer FTM_IMAGE_CREATE("Create Images"); F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) { @@ -706,7 +709,7 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) // Create GL textures for all textures that need them (images which have been // decoded, but haven't been pushed into GL). // - LLFastTimer t(LLFastTimer::FTM_IMAGE_CREATE); + LLFastTimer t(FTM_IMAGE_CREATE); LLTimer create_timer; image_list_t::iterator enditer = mCreateTextureList.begin(); @@ -1115,7 +1118,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) // static void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data) { - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + LLFastTimer t(FTM_PROCESS_IMAGES); // Receive image header, copy into image object and decompresses // if this is a one-packet image. @@ -1179,7 +1182,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data) { LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + LLFastTimer t(FTM_PROCESS_IMAGES); // Receives image packet, copy into image object, // checks if all packets received, decompresses if so. @@ -1244,7 +1247,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d // static void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data) { - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + LLFastTimer t(FTM_PROCESS_IMAGES); LLUUID image_id; msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 2b1dbf8e84..74ed5b12fe 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -935,8 +935,6 @@ void LLViewerWindow::handleFocus(LLWindow *window) gAgent.onAppFocusGained(); LLToolMgr::getInstance()->onAppFocusGained(); - gShowTextEditCursor = TRUE; - // See if we're coming in with modifier keys held down if (gKeyboard) { @@ -966,11 +964,6 @@ void LLViewerWindow::handleFocusLost(LLWindow *window) showCursor(); getWindow()->setMouseClipping(FALSE); - // JC - Leave keyboard focus, so if you're popping in and out editing - // a script, you don't have to click in the editor again and again. - // gFocusMgr.setKeyboardFocus( NULL ); - gShowTextEditCursor = FALSE; - // If losing focus while keys are down, reset them. if (gKeyboard) { @@ -2020,6 +2013,11 @@ void LLViewerWindow::draw() // No translation needed, this view is glued to 0,0 mRootView->draw(); + if (mToolTip->getVisible() && LLView::sDebugRects) + { + gl_rect_2d(mToolTipStickyRect, LLColor4::white, false); + } + // Draw optional on-top-of-everyone view LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); if (top_ctrl && top_ctrl->getVisible()) @@ -3320,7 +3318,7 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) return; } - llassert_always(pick_info.mScreenRegion.notNull()); + llassert_always(pick_info.mScreenRegion.notEmpty()); mPicks.push_back(pick_info); // delay further event processing until we receive results of pick diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2b5c3361c4..e98e4f2e6a 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2085,13 +2085,16 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) } } +static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Update Avatar"); +static LLFastTimer::DeclareTimer FTM_JOINT_UPDATE("Update Joints"); + //------------------------------------------------------------------------ // idleUpdate() //------------------------------------------------------------------------ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLMemType mt(LLMemType::MTYPE_AVATAR); - LLFastTimer t(LLFastTimer::FTM_AVATAR_UPDATE); + LLFastTimer t(FTM_AVATAR_UPDATE); if (isDead()) { @@ -2110,7 +2113,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // force asynchronous drawable update if(mDrawable.notNull() && !gNoRender) { - LLFastTimer t(LLFastTimer::FTM_JOINT_UPDATE); + LLFastTimer t(FTM_JOINT_UPDATE); if (mIsSitting && getParent()) { @@ -2272,6 +2275,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) }//if ( voiceEnabled ) } +static LLFastTimer::DeclareTimer FTM_ATTACHMENT_UPDATE("Update Attachments"); + void LLVOAvatar::idleUpdateMisc(bool detailed_update) { if (LLVOAvatar::sJointDebug) @@ -2293,7 +2298,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) // update attachments positions if (detailed_update || !sUseImpostors) { - LLFastTimer t(LLFastTimer::FTM_ATTACHMENT_UPDATE); + LLFastTimer t(FTM_ATTACHMENT_UPDATE); for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ) { @@ -4613,9 +4618,11 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion ) //----------------------------------------------------------------------------- // loadAvatar() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar"); + BOOL LLVOAvatar::loadAvatar() { -// LLFastTimer t(LLFastTimer::FTM_LOAD_AVATAR); +// LLFastTimer t(FTM_LOAD_AVATAR); // avatar_skeleton.xml if( !buildSkeleton(sAvatarSkeletonInfo) ) @@ -5168,9 +5175,10 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) //----------------------------------------------------------------------------- // updateGeometry() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_UPDATE_AVATAR("Update Avatar"); BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_AVATAR); + LLFastTimer ftm(FTM_UPDATE_AVATAR); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) { return TRUE; diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index fbc4e2e609..130e1fd749 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -115,9 +115,11 @@ LLDrawable* LLVOClouds::createDrawable(LLPipeline *pipeline) return mDrawable; } +static LLFastTimer::DeclareTimer FTM_UPDATE_CLOUDS("Update Clouds"); + BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_CLOUDS); + LLFastTimer ftm(FTM_UPDATE_CLOUDS); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS))) { return TRUE; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index cf6eb8e9fd..a2793accea 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -382,9 +382,11 @@ LLDrawable* LLVOGrass::createDrawable(LLPipeline *pipeline) return mDrawable; } +static LLFastTimer::DeclareTimer FTM_UPDATE_GRASS("Update Grass"); + BOOL LLVOGrass::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_GRASS); + LLFastTimer ftm(FTM_UPDATE_GRASS); dirtySpatialGroup(); plantBlades(); return TRUE; diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 29036f4947..38c9ce28c4 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -139,9 +139,10 @@ LLVector3 LLVOPartGroup::getCameraPosition() const return gAgent.getCameraPositionAgent(); } +static LLFastTimer::DeclareTimer FTM_UPDATE_PARTICLES("Update Particles"); BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_PARTICLES); + LLFastTimer ftm(FTM_UPDATE_PARTICLES); dirtySpatialGroup(); @@ -416,12 +417,15 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } } +static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB"); + void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? - LLFastTimer::FTM_REBUILD_GRASS_VB : - LLFastTimer::FTM_REBUILD_PARTICLE_VB); + FTM_REBUILD_GRASS_VB : + FTM_REBUILD_PARTICLE_VB); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 993cf522e9..ae5992099d 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1231,6 +1231,8 @@ void LLVOSky::createDummyVertexBuffer() } } +static LLFastTimer::DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update"); + void LLVOSky::updateDummyVertexBuffer() { if(!LLVertexBuffer::sEnableVBOs) @@ -1242,7 +1244,7 @@ void LLVOSky::updateDummyVertexBuffer() return ; } - LLFastTimer t(LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE) ; + LLFastTimer t(FTM_RENDER_FAKE_VBO_UPDATE) ; if(!mFace[FACE_DUMMY] || mFace[FACE_DUMMY]->mVertexBuffer.isNull()) createDummyVertexBuffer() ; @@ -1255,10 +1257,11 @@ void LLVOSky::updateDummyVertexBuffer() //---------------------------------- //end of fake vertex buffer updating //---------------------------------- +static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry"); BOOL LLVOSky::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY); + LLFastTimer ftm(FTM_GEO_SKY); if (mFace[FACE_REFLECTION] == NULL) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 4980b50de4..157d719fcc 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -176,10 +176,11 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) return mDrawable; } +static LLFastTimer::DeclareTimer FTM_UPDATE_TERRAIN("Update Terrain"); BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN); + LLFastTimer ftm(FTM_UPDATE_TERRAIN); dirtySpatialGroup(); @@ -1028,9 +1029,10 @@ LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage) return new LLVertexBufferTerrain(); } +static LLFastTimer::DeclareTimer FTM_REBUILD_TERRAIN_VB("Terrain VB"); void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_TERRAIN_VB); + LLFastTimer ftm(FTM_REBUILD_TERRAIN_VB); LLVertexBuffer* buffer = group->mVertexBuffer; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index d1cac4c77e..86d9f31d07 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -504,9 +504,11 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) const S32 LEAF_INDICES = 24; const S32 LEAF_VERTICES = 16; +static LLFastTimer::DeclareTimer FTM_UPDATE_TREE("Update Tree"); + BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE); + LLFastTimer ftm(FTM_UPDATE_TREE); if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull()) { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bef38bb669..f7a16571d1 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -79,6 +79,9 @@ F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectiv F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; +static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); +static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); + LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLViewerObject(id, pcode, regionp), mVolumeImpl(NULL) @@ -1130,15 +1133,18 @@ void LLVOVolume::updateRelativeXform() } } +static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies"); +static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives"); + BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { - LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES); + LLFastTimer t(FTM_UPDATE_PRIMITIVES); if (mVolumeImpl != NULL) { BOOL res; { - LLFastTimer t(LLFastTimer::FTM_GEN_FLEX); + LLFastTimer t(FTM_GEN_FLEX); res = mVolumeImpl->doUpdateGeometry(drawable); } updateFaceFlags(); @@ -1162,14 +1168,14 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) if (mVolumeChanged) { - LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME); + LLFastTimer ftm(FTM_GEN_VOLUME); LLVolumeParams volume_params = getVolume()->getParams(); setVolume(volume_params, 0); drawable->setState(LLDrawable::REBUILD_VOLUME); } { - LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); + LLFastTimer t(FTM_GEN_TRIANGLES); regenFaces(); genBBoxes(FALSE); } @@ -1186,7 +1192,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) old_volumep = NULL ; { - LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME); + LLFastTimer ftm(FTM_GEN_VOLUME); LLVolumeParams volume_params = getVolume()->getParams(); setVolume(volume_params, 0); } @@ -1204,7 +1210,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() { - LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); + LLFastTimer t(FTM_GEN_TRIANGLES); if (new_num_faces != old_num_faces) { regenFaces(); @@ -1218,7 +1224,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { compiled = TRUE; // All it did was move or we changed the texture coordinate offset - LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); + LLFastTimer t(FTM_GEN_TRIANGLES); genBBoxes(FALSE); } @@ -2235,6 +2241,9 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); + void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (LLPipeline::sSkipUpdate) @@ -2253,8 +2262,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); - LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB); + LLFastTimer ftm(FTM_REBUILD_VBO); + LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); rebuildMesh(group); } @@ -2262,9 +2271,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } group->mBuilt = 1.f; - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); + LLFastTimer ftm(FTM_REBUILD_VBO); - LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB); + LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); group->clearDrawMap(); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 427119285b..332c9dd952 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -139,9 +139,11 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline) return mDrawable; } +static LLFastTimer::DeclareTimer FTM_UPDATE_WATER("Update Water"); + BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER); + LLFastTimer ftm(FTM_UPDATE_WATER); LLFace *face; if (drawable->getNumFaces() < 1) diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index abd25e6598..8621e5e1d9 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -307,9 +307,11 @@ void LLVOWLSky::restoreGL() gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } +static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry"); + BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { - LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY); + LLFastTimer ftm(FTM_GEO_SKY); LLStrider vertices; LLStrider texCoords; LLStrider indices; diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 92c223e43d..3661be500b 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -263,9 +263,11 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader) } } +static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params"); + void LLWaterParamManager::update(LLViewerCamera * cam) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM); + LLFastTimer ftm(FTM_UPDATE_WLPARAM); // update the shaders and the menu propagateParameters(); diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index c237c0bded..ae476c88c9 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -64,6 +64,7 @@ #include "curl/curl.h" LLWLParamManager * LLWLParamManager::sInstance = NULL; +static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params"); LLWLParamManager::LLWLParamManager() : @@ -292,7 +293,7 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader) void LLWLParamManager::propagateParameters(void) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM); + LLFastTimer ftm(FTM_UPDATE_WLPARAM); LLVector4 sunDir; LLVector4 moonDir; @@ -363,7 +364,7 @@ void LLWLParamManager::propagateParameters(void) void LLWLParamManager::update(LLViewerCamera * cam) { - LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM); + LLFastTimer ftm(FTM_UPDATE_WLPARAM); // update clouds, sun, and general mCurParams.updateCloudScrolling(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f422791868..bf00957212 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -138,6 +138,33 @@ BOOL gDebugPipeline = FALSE; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; +LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry"); +LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass"); +LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible"); +LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion"); +LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny"); +LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple"); +LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain"); +LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees"); +LLFastTimer::DeclareTimer FTM_RENDER_UI("UI"); +LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water"); +LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky"); +LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects"); +LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars"); +LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump"); +LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright"); +LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow"); +LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update"); +LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool"); +LLFastTimer::DeclareTimer FTM_POOLS("Pools"); +LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO"); +LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State"); +LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline"); +LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy"); + +static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables"); +static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort"); + //---------------------------------------- std::string gPoolNames[] = { @@ -973,7 +1000,7 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj) void LLPipeline::unlinkDrawable(LLDrawable *drawable) { - LLFastTimer t(LLFastTimer::FTM_PIPELINE); + LLFastTimer t(FTM_PIPELINE); assertInitialized(); @@ -1035,7 +1062,7 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::createObjects(F32 max_dtime) { - LLFastTimer ftm(LLFastTimer::FTM_GEO_UPDATE); + LLFastTimer ftm(FTM_GEO_UPDATE); LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS); LLTimer update_timer; @@ -1201,9 +1228,12 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) } } +static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree"); +static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move"); + void LLPipeline::updateMove() { - LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); + LLFastTimer t(FTM_UPDATE_MOVE); LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE); if (gSavedSettings.getBOOL("FreezeTime")) @@ -1249,7 +1279,7 @@ void LLPipeline::updateMove() //balance octrees { - LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE); + LLFastTimer ot(FTM_OCTREE_BALANCE); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -1354,10 +1384,11 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& return res; } +static LLFastTimer::DeclareTimer FTM_CULL("Object Culling"); void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip) { - LLFastTimer t(LLFastTimer::FTM_CULL); + LLFastTimer t(FTM_CULL); LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL); grabReferences(result); @@ -1572,7 +1603,7 @@ void LLPipeline::updateGeom(F32 max_dtime) LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM); LLPointer drawablep; - LLFastTimer t(LLFastTimer::FTM_GEO_UPDATE); + LLFastTimer t(FTM_GEO_UPDATE); assertInitialized(); @@ -1840,6 +1871,8 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f } } +static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order"); + void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { const U32 face_mask = (1 << LLPipeline::RENDER_TYPE_AVATAR) | @@ -1852,11 +1885,11 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) if (mRenderTypeMask & face_mask) { //clear faces from face pools - LLFastTimer t(LLFastTimer::FTM_RESET_DRAWORDER); + LLFastTimer t(FTM_RESET_DRAWORDER); gPipeline.resetDrawOrders(); } - LLFastTimer ftm(LLFastTimer::FTM_STATESORT); + LLFastTimer ftm(FTM_STATESORT); LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT); //LLVertexBuffer::unbind(); @@ -1912,7 +1945,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } { - LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE); + LLFastTimer ftm(FTM_STATESORT_DRAWABLE); for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { @@ -1925,7 +1958,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } { - LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); + LLFastTimer ftm(FTM_CLIENT_COPY); LLVertexBuffer::clientCopy(); } @@ -2188,7 +2221,7 @@ void renderSoundHighlights(LLDrawable* drawablep) void LLPipeline::postSort(LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT); - LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT); + LLFastTimer ftm(FTM_STATESORT_POSTSORT); assertInitialized(); @@ -2382,7 +2415,7 @@ void LLPipeline::postSort(LLCamera& camera) void render_hud_elements() { LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS); - LLFastTimer t(LLFastTimer::FTM_RENDER_UI); + LLFastTimer t(FTM_RENDER_UI); gPipeline.disableLights(); LLGLDisable fog(GL_FOG); @@ -2495,7 +2528,7 @@ void LLPipeline::renderHighlights() void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM); - LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); + LLFastTimer t(FTM_RENDER_GEOMETRY); assertInitialized(); @@ -2594,7 +2627,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } else { - LLFastTimer t(LLFastTimer::FTM_POOLS); + LLFastTimer t(FTM_POOLS); // HACK: don't calculate local lights if we're rendering the HUD! // Removing this check will cause bad flickering when there are @@ -2626,7 +2659,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0) { - LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + LLFastTimer t(FTM_POOLRENDER); gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); @@ -2760,9 +2793,9 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED); - LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); + LLFastTimer t(FTM_RENDER_GEOMETRY); - LLFastTimer t2(LLFastTimer::FTM_POOLS); + LLFastTimer t2(FTM_POOLS); LLGLEnable cull(GL_CULL_FACE); @@ -2804,7 +2837,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) { - LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + LLFastTimer t(FTM_POOLRENDER); gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); @@ -2862,7 +2895,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF); - LLFastTimer t(LLFastTimer::FTM_POOLS); + LLFastTimer t(FTM_POOLS); U32 cur_type = 0; LLGLEnable cull(GL_CULL_FACE); @@ -2895,7 +2928,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) { - LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + LLFastTimer t(FTM_POOLRENDER); gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); @@ -4979,6 +5012,7 @@ void LLPipeline::bindScreenToTexture() } +static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom"); void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM); @@ -5012,7 +5046,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.setColorMask(true, true); - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM); + LLFastTimer ftm(FTM_RENDER_BLOOM); gGL.color4f(1,1,1,1); LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -5087,7 +5121,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { { - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO); + LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); mGlow[2].bindTarget(); mGlow[2].clear(); } @@ -5159,7 +5193,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); { - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO); + LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); mGlow[i%2].bindTarget(); mGlow[i%2].clear(); } @@ -5201,7 +5235,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) if (LLRenderTarget::sUseFBO) { - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO); + LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } @@ -6095,6 +6129,10 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) return ret; } +static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows"); +static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow"); +static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow"); + void LLPipeline::generateSunShadow(LLCamera& camera) { @@ -6343,7 +6381,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadowCamera[j+4] = shadow_cam; } - LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); + LLFastTimer t(FTM_SHADOW_RENDER); stop_glerror(); @@ -6381,7 +6419,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) gDeferredShadowProgram.bind(); { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); + LLFastTimer ftm(FTM_SHADOW_SIMPLE); LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) @@ -6392,7 +6430,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) } { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); + LLFastTimer ftm(FTM_SHADOW_ALPHA); LLGLEnable test(GL_ALPHA_TEST); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fc02e7dd88..8f6867aa01 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -78,6 +78,27 @@ glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar); glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up); +extern LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY; +extern LLFastTimer::DeclareTimer FTM_RENDER_GRASS; +extern LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE; +extern LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION; +extern LLFastTimer::DeclareTimer FTM_RENDER_SHINY; +extern LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE; +extern LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN; +extern LLFastTimer::DeclareTimer FTM_RENDER_TREES; +extern LLFastTimer::DeclareTimer FTM_RENDER_UI; +extern LLFastTimer::DeclareTimer FTM_RENDER_WATER; +extern LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY; +extern LLFastTimer::DeclareTimer FTM_RENDER_ALPHA; +extern LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS; +extern LLFastTimer::DeclareTimer FTM_RENDER_BUMP; +extern LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT; +extern LLFastTimer::DeclareTimer FTM_RENDER_GLOW; +extern LLFastTimer::DeclareTimer FTM_STATESORT; +extern LLFastTimer::DeclareTimer FTM_PIPELINE; +extern LLFastTimer::DeclareTimer FTM_CLIENT_COPY; + + class LLPipeline { public: diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png index a4060e5e37..e27dbe2cad 100644 Binary files a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png index 9c2815ebba..82d044d817 100644 Binary files a/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png index 377b707529..7909d54f2b 100644 Binary files a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png differ diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png index a69a729bd4..6670667022 100644 Binary files a/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png and b/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png index fb59f2e61e..5dd0852a72 100644 Binary files a/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png and b/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Close_Press.png b/indra/newview/skins/default/textures/windows/Icon_Close_Press.png index 7177c803b0..ea547fca6f 100644 Binary files a/indra/newview/skins/default/textures/windows/Icon_Close_Press.png and b/indra/newview/skins/default/textures/windows/Icon_Close_Press.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png index cadd6bc8ce..4207ba68e5 100644 Binary files a/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png and b/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png b/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png index 08f8cfc3d4..2d09475783 100644 Binary files a/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png and b/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png index d790cf57ef..9a71d16a3f 100644 Binary files a/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png and b/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png b/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png index fdae4b75f6..3ab8c3666a 100644 Binary files a/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png and b/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png differ diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index eedc588449..633fff079b 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1,15 +1,14 @@ - - - - + + + Vis ikke dette igen - - - - + + Vælg altid dette - - + + + Luk + + + Din version af Second Life kan ikke vise den advarselsbesked den modtog. - -'[_NAME]' mangler fra notifications.xml. - - - - -Floater error: Kunne ikke finde følgende kontrol: +Fejl detaljer: Advarslen '[_NAME]' blev ikke fundet i notifications.xml. + + + + Floater error: Kunne ikke finde følgende kontrol: [CONTROLS] + + + + Der er i øjeblikket ingen tilgængelig guide. + + + + [MESSAGE] + + + [MESSAGE] + + + + Der opstod en fejl ved opdatering af Second Life. Hent venligst den nyeste version fra secondlife.com. - - - -Der er i øjeblikket ingen tilgængelig guide. - + + Netværksfejl: Kunne ikke oprette forbindelse. +'[DIAGNOSTIC]' +Check venligst din netværksforbindelse. + - - - -[MESSAGE] - - - -[MESSAGE] - - - - -Gem ændringer til nuværende tøj/krops del? - - - - -Der var problemer med upload af teksten til et script af følgende årsager: [REASON]. Prøv igen senere. - - - -Der var problemer med at uploade den kompileret script af følgende årsager: [REASON]. Prøv igen senere. - - - -Der var et problem med skrivning af animations data. Prøv igen senere. - - - -Der var problemer med at uploade billedet til auktionen af følgende årsager: [REASON] - - - -Ude af stand til at se indholdet af mere end ét element ad gangen. + + + Besked template [PATH] kunne ikke findes. + + + + Gem ændringer til nuværende tøj/krops del? + + + + Der var problemer med upload af teksten til et script af følgende årsager: [REASON]. Prøv igen senere. + + + Der var problemer med at uploade den kompileret script af følgende årsager: [REASON]. Prøv igen senere. + + + Der var et problem med skrivning af animations data. Prøv igen senere. + + + Der var problemer med at uploade billedet til auktionen af følgende årsager: [REASON] + + + Ude af stand til at se indholdet af mere end ét element ad gangen. Vælg kun en genstand, og prøv igen. - - - -Gem alle ændringer til tøj/krops dele? - - - - -At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse. + + + Gem alle ændringer til tøj/krops dele? + + + + At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse. Ønsker du at ændre rettigheder for [FIRST_NAME] [LAST_NAME]? - - - - -At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse. + + + + At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse. Ønsker du at ændre rettigheder for de valgte beboere? - - - - -Vil du tilbagekalde rettighederne for [FIRST_NAME] [LAST_NAME]? - - - - -Vil du tilbagekalde rettighederne for de valgte beboere? - - - - -Kunne ikke oprette gruppe. + + + + Vil du tilbagekalde rettighederne for [FIRST_NAME] [LAST_NAME]? + + + + Vil du tilbagekalde rettighederne for de valgte beboere? + + + + Kunne ikke oprette gruppe. [MESSAGE] - - - - -[NEEDS_APPLY_MESSAGE] + + + + [NEEDS_APPLY_MESSAGE] [WANT_APPLY_MESSAGE] - - - - -Du skal angive et emne for at sende en gruppe besked. - - - - -Du er ved at tilføje medlemmer til rollen som [ROLE_NAME]. + + + + Du skal angive et emne for at sende en gruppe besked. + + + + Du er ved at tilføje medlemmer til rollen som [ROLE_NAME]. Medlemmer ikke kan fjernes fra denne rolle. Medlemmerne skal fratræde sin rolle selv. Er du sikker på du vil fortsætte? - - - - -Du er ved at tilføje muligheden for '[ACTION_NAME]' til + + + + Du er ved at tilføje muligheden for '[ACTION_NAME]' til rollen '[ROLE_NAME]'. *ADVARSEL* Ethvert medlem i en rolle med denne evne kan tildele sig selv -- og et andet medlem - roller med flere beføjelser, end de har i øjeblikket, potentielt kan de ophøje sig selv til nær-Ejer magt. Være sikker på, at du ved, hvad du laver, før tildeling af denne evne. Add this Ability to '[ROLE_NAME]'? + + + + Media og musik kan kun ses og høres indenfor parcellen. Lyd og stemme valg muligheder kan begrænses til parcellen eller de kan høres af beboere udenfor parcellen, afhængigt af deres indholdsrating. Gå til 'Knowledge Base' for at lære hvordan disse valg opsættes. + + https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=5046 + - - - -Hvis du vælger "Vis i Søgning" Vises: + yestext="Gå til 'Knowledge Base'" + notext="Luk" /> + + + Søgeresultater er organiseret baseret på den fane du står på, din indholdsrating, den valgte kategori og andre faktorer. for yderligere detaljer se i 'Knowledge Base'. + + https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=4722 + + + + + Hvis du vælger "Vis i Søgning" Vises: - Din profil i søgeresultater - Et link til din profile i de offentlige gruppe sider - - - -Hvis en beboer har en hjemmeside adresse kan du: + + + Dinne standard rettigheder virker muligvis ikke i ældre regioner. + + + Hvis en beboer har en hjemmeside adresse kan du: * Klikke 'Load' for at side deres side her. * Klikke Load > 'I ekstern browser' for at se siden i din standard browser. * Klikke Load > 'Hjemme URL' for at returnere til denne beboers side hvis du har navigeret væk. Når du ser din egen profil, kan du skrive hvilken som helst adresse og klikke ok for at få den vist i din egen profil. Andre beboere kan besøge den adresse du har sat, når de besøger din profil. - - - -Tilmelding til denne gruppe koster L$[COST]. + + + Tilmelding til denne gruppe koster L$[COST]. Du har ikke nok L$ til denne tilmelding. - - - -E-mail dette billede med standard emne eller besked? - - - - -Der var et problem med at sende billedet på grund af følgende: [REASON] - - - -Ups! Noget var tomt. + + + E-mail dette billede med standard emne eller besked? + + + + Der var et problem med at sende billedet på grund af følgende: [REASON] + + + Ups! Noget var tomt. Du skal skrive både fornavn og efternavn på din figur. Du har brug for en konto for at logge ind i [SECOND_LIFE]. Vil du oprette en nu? - - - - -Vil du gerne genaktivere alle disse popups, som du tidligere har bedt om ikke at få vist? - - - - -Vil du deaktivere alle popups som kan undværes? - - - - -Det nye udseende vil vises efter du har genstartet [SECOND_LIFE]. - - - -
- - -
- - -
- - -
- - -Du har ikke tilladelse til at videreføre den valgte mappe. - - - -Ikke i stand til at købe land: + + + + Vil du gerne genaktivere alle disse popups, som du tidligere har bedt om ikke at få vist? + + + + Vil du deaktivere alle popups som kan undværes? + + + + Det nye udseende vil vises efter du har genstartet [SECOND_LIFE]. + + + +
+ + +
+ + +Der er problemer med at håndtere din teleport. Det kan være nødvendigt at logge ud og ind for at kunne skifte teleportere. +Hvis du bliver ved med at have problemet kan du checke teknisk support på: +www.secondlife.com/support + + +Problem registreret i forbindelse med skift til ny region. Det kan være nødvendigt at logge ud og ind for at kunne skifte regioner. +Hvis du bliver ved med at have problemet kan du checke teknisk support på: +www.secondlife.com/support + + +Beklager, teleport er blokeret lige nu. Prøv igen senere. +Hvis du stadig ikke kan teleporte, prøv venligst at logge ud og ligge ind for at løse dette problem. + + +Beklager, systemet kunne ikke finde landmærke destinationen. + + +Beklager, systemet kunne ikke fuldføre teleport forbindelse. +Prøv igen om lidt. + + +Beklager, du har ikke adgang til denne teleport destination. + + +Dine vedhæng er ikke ankommet endnu. Prøv at vente lidt endnu eller log ud og ind igen før du prøver at teleporte igen. + + +Tekniske problemer hindrer at din teleport kan gennemføres. +Prøv venligst igen om lidt eller vælg et mindre travlt område. + + +Beklager, men systemet kunne ikke fuldføre din teleport i rimelig tid. Prøv venligst igen om lidt. + + +Beklager, men systemet kunne ikke fuldføre skift til anden region i rimelig tid. Prøv venligst igen om lidt. + + +Ikke muligt at fine teleport destination. Destinationen kan være midlertidig utilgængelig eller findes ikke mere. +Prøv evt. igen om lidt. + + +Beholdningssystemet er ikke tilgængelig lige nu. + + + + Du har ikke tilladelse til at videreføre den valgte mappe. + + + Kunne ikke 'forstå' filen: [FILE] + + + Ikke i stand til at købe land: Kan ikke finde region som dette land er i. - - - -Du er blevet logget ud af [SECOND_LIFE]: + + + Vis ejere: +Farver på parceller viser ejer-type. + +Grøn = Dit land +Turkis = Din gruppes land +Rød = Ejet af andre +Gul = Til salg +Lilla = På auktion +Grå = Offentligt ejet + + + Du er blevet logget ud af [SECOND_LIFE]: [MESSAGE] Du kan stadig se eksiterende PB'er og chat ved at klikke'Se PB & Chat'. Ellers, klik 'Afslut' for at afslutte [SECOND_LIFE] nu. - - - - -Venner kan give tilladelse til at følge hinanden + + + + Venner kan give tilladelse til at følge hinanden på Verdenskortet eller modtage status opdateringer. Tilbyd venskab til [NAME]? - - - - -Venner kan give tilladelse til at følge hinanden + + + + Venner kan give tilladelse til at følge hinanden på Verdenskortet eller modtage status opdateringer. Tilbyd venskab til [NAME]? -
- -Vil du være min ven? - + + + Vil du være min ven? + +