aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui
diff options
context:
space:
mode:
authorJacek Antonelli2011-05-08 15:13:37 -0500
committerJacek Antonelli2011-05-08 15:50:49 -0500
commit7278f0254a3944bd2bcbf1e855fb0d90c3086a27 (patch)
tree5d7ecb81ebf1a07482f0a7d3d13acd7f18360c0b /linden/indra/llui
parentImprudence 1.3.1 released. (diff)
parentChanged version to Experimental 2011.04.19 (diff)
downloadmeta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.zip
meta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.tar.gz
meta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.tar.bz2
meta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.tar.xz
Merged Experimental branch (exp) back into main line (next).
Git thought many files (almost 100) had merge conflicts. But, after resolving the conflicts (which were mostly trivial), almost all the files turned out to be the same as in the exp branch. So, the conflicts are not listed here. Check the diff between commit 244ffe8 and this commit to see what really changed.
Diffstat (limited to 'linden/indra/llui')
-rw-r--r--linden/indra/llui/CMakeLists.txt15
-rw-r--r--linden/indra/llui/llbutton.cpp5
-rw-r--r--linden/indra/llui/llbutton.h3
-rw-r--r--linden/indra/llui/llcombobox.cpp32
-rw-r--r--linden/indra/llui/llcombobox.h5
-rw-r--r--linden/indra/llui/llfloater.cpp8
-rw-r--r--linden/indra/llui/llfocusmgr.cpp84
-rw-r--r--linden/indra/llui/llfocusmgr.h49
-rw-r--r--linden/indra/llui/llfunctorregistry.cpp1
-rw-r--r--linden/indra/llui/lliconctrl.cpp6
-rw-r--r--linden/indra/llui/lliconctrl.h2
-rw-r--r--linden/indra/llui/lllineeditor.cpp687
-rw-r--r--linden/indra/llui/lllineeditor.h69
-rw-r--r--linden/indra/llui/llmenugl.cpp248
-rw-r--r--linden/indra/llui/llmenugl.h117
-rw-r--r--linden/indra/llui/llmultisliderctrl.cpp3
-rw-r--r--linden/indra/llui/llnotifications.cpp6
-rw-r--r--linden/indra/llui/llpanel.cpp21
-rw-r--r--linden/indra/llui/llpanel.h3
-rw-r--r--linden/indra/llui/llresmgr.cpp6
-rw-r--r--linden/indra/llui/llresmgr.h3
-rw-r--r--linden/indra/llui/llscrollbar.cpp5
-rw-r--r--linden/indra/llui/llscrollbar.h1
-rw-r--r--linden/indra/llui/llscrollcontainer.cpp17
-rw-r--r--linden/indra/llui/llscrollcontainer.h1
-rw-r--r--linden/indra/llui/llscrolllistctrl.cpp83
-rw-r--r--linden/indra/llui/llscrolllistctrl.h18
-rw-r--r--linden/indra/llui/llsliderctrl.cpp2
-rw-r--r--linden/indra/llui/llspinctrl.cpp1
-rw-r--r--linden/indra/llui/llstyle.cpp8
-rw-r--r--linden/indra/llui/lltexteditor.cpp788
-rw-r--r--linden/indra/llui/lltexteditor.h89
-rw-r--r--linden/indra/llui/lltextparser.cpp48
-rw-r--r--linden/indra/llui/lltextparser.h7
-rw-r--r--linden/indra/llui/llui.cpp1
-rw-r--r--linden/indra/llui/lluictrl.cpp55
-rw-r--r--linden/indra/llui/lluictrl.h26
-rw-r--r--linden/indra/llui/lluixmltags.h192
-rw-r--r--linden/indra/llui/llview.cpp52
-rw-r--r--linden/indra/llui/llview.h16
40 files changed, 2365 insertions, 418 deletions
diff --git a/linden/indra/llui/CMakeLists.txt b/linden/indra/llui/CMakeLists.txt
index a0f80b4..e6b3b63 100644
--- a/linden/indra/llui/CMakeLists.txt
+++ b/linden/indra/llui/CMakeLists.txt
@@ -3,11 +3,9 @@
3project(llui) 3project(llui)
4 4
5include(00-Common) 5include(00-Common)
6include(LLAudio)
7include(LLCommon) 6include(LLCommon)
8include(LLImage) 7include(LLImage)
9include(LLMath) 8include(LLMath)
10include(LLMedia)
11include(LLMessage) 9include(LLMessage)
12include(LLRender) 10include(LLRender)
13include(LLWindow) 11include(LLWindow)
@@ -15,11 +13,9 @@ include(LLVFS)
15include(LLXML) 13include(LLXML)
16 14
17include_directories( 15include_directories(
18 ${LLAUDIO_INCLUDE_DIRS}
19 ${LLCOMMON_INCLUDE_DIRS} 16 ${LLCOMMON_INCLUDE_DIRS}
20 ${LLIMAGE_INCLUDE_DIRS} 17 ${LLIMAGE_INCLUDE_DIRS}
21 ${LLMATH_INCLUDE_DIRS} 18 ${LLMATH_INCLUDE_DIRS}
22 ${LLMEDIA_INCLUDE_DIRS}
23 ${LLMESSAGE_INCLUDE_DIRS} 19 ${LLMESSAGE_INCLUDE_DIRS}
24 ${LLRENDER_INCLUDE_DIRS} 20 ${LLRENDER_INCLUDE_DIRS}
25 ${LLWINDOW_INCLUDE_DIRS} 21 ${LLWINDOW_INCLUDE_DIRS}
@@ -141,3 +137,14 @@ set_source_files_properties(${llui_HEADER_FILES}
141list(APPEND llui_SOURCE_FILES ${llui_HEADER_FILES}) 137list(APPEND llui_SOURCE_FILES ${llui_HEADER_FILES})
142 138
143add_library (llui ${llui_SOURCE_FILES}) 139add_library (llui ${llui_SOURCE_FILES})
140# Libraries on which this library depends, needed for Linux builds
141# Sort by high-level to low-level
142target_link_libraries(llui
143 llrender
144 llwindow
145 llimage
146 llvfs # ugh, just for LLDir
147 llxml
148 llcommon # must be after llimage, llwindow, llrender
149 llmath
150 )
diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp
index 1a6c705..702e34e 100644
--- a/linden/indra/llui/llbutton.cpp
+++ b/linden/indra/llui/llbutton.cpp
@@ -840,6 +840,11 @@ void LLButton::setColor(const LLColor4& color)
840 setImageColor(color); 840 setImageColor(color);
841} 841}
842 842
843void LLButton::setAlpha(F32 alpha)
844{
845 mImageColor.setAlpha(alpha);
846 mDisabledImageColor.setAlpha(alpha * 0.5f);
847}
843 848
844void LLButton::setImageDisabled(LLPointer<LLUIImage> image) 849void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
845{ 850{
diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h
index 724b775..2174d95 100644
--- a/linden/indra/llui/llbutton.h
+++ b/linden/indra/llui/llbutton.h
@@ -136,7 +136,8 @@ public:
136 136
137 void setImageColor(const std::string& color_control); 137 void setImageColor(const std::string& color_control);
138 void setImageColor(const LLColor4& c); 138 void setImageColor(const LLColor4& c);
139 virtual void setColor(const LLColor4& c); 139 /*virtual*/ void setColor(const LLColor4& c);
140 /*virtual*/ void setAlpha(F32 alpha);
140 141
141 void setImages(const std::string &image_name, const std::string &selected_name); 142 void setImages(const std::string &image_name, const std::string &selected_name);
142 void setDisabledImages(const std::string &image_name, const std::string &selected_name); 143 void setDisabledImages(const std::string &image_name, const std::string &selected_name);
diff --git a/linden/indra/llui/llcombobox.cpp b/linden/indra/llui/llcombobox.cpp
index be34325..f3ef83e 100644
--- a/linden/indra/llui/llcombobox.cpp
+++ b/linden/indra/llui/llcombobox.cpp
@@ -43,6 +43,7 @@
43 43
44// newview includes 44// newview includes
45#include "llbutton.h" 45#include "llbutton.h"
46#include "llfont.h"
46#include "llkeyboard.h" 47#include "llkeyboard.h"
47#include "llscrolllistctrl.h" 48#include "llscrolllistctrl.h"
48#include "llwindow.h" 49#include "llwindow.h"
@@ -60,7 +61,7 @@ S32 MAX_COMBO_WIDTH = 500;
60 61
61static LLRegisterWidget<LLComboBox> r1("combo_box"); 62static LLRegisterWidget<LLComboBox> r1("combo_box");
62 63
63LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::string& label, 64LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::string& label, const LLFontGL* font,
64 void (*commit_callback)(LLUICtrl*,void*), 65 void (*commit_callback)(LLUICtrl*,void*),
65 void *callback_userdata 66 void *callback_userdata
66 ) 67 )
@@ -76,6 +77,15 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::
76 mTextEntryCallback( NULL ), 77 mTextEntryCallback( NULL ),
77 mLabel(label) 78 mLabel(label)
78{ 79{
80 if (font)
81 {
82 mGLFont = font;
83 }
84 else
85 {
86 mGLFont = LLFontGL::getFontSansSerifSmall();
87 }
88
79 // Always use text box 89 // Always use text box
80 // Text label button 90 // Text label button
81 mButton = new LLButton(mLabel, 91 mButton = new LLButton(mLabel,
@@ -89,14 +99,14 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::
89 mButton->setScaleImage(TRUE); 99 mButton->setScaleImage(TRUE);
90 100
91 mButton->setMouseDownCallback(onButtonDown); 101 mButton->setMouseDownCallback(onButtonDown);
92 mButton->setFont(LLFontGL::getFontSansSerifSmall()); 102 mButton->setFont(mGLFont);
93 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); 103 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
94 mButton->setHAlign( LLFontGL::LEFT ); 104 mButton->setHAlign( LLFontGL::LEFT );
95 mButton->setRightHPad(2); 105 mButton->setRightHPad(2);
96 addChild(mButton); 106 addChild(mButton);
97 107
98 // disallow multiple selection 108 // disallow multiple selection
99 mList = new LLScrollListCtrl(std::string("ComboBox"), LLRect(), 109 mList = new LLScrollListCtrl(std::string("ComboBox"), LLRect(), mGLFont,
100 &LLComboBox::onItemSelected, this, FALSE); 110 &LLComboBox::onItemSelected, this, FALSE);
101 mList->setVisible(FALSE); 111 mList->setVisible(FALSE);
102 mList->setBgWriteableColor( LLColor4(1,1,1,1) ); 112 mList->setBgWriteableColor( LLColor4(1,1,1,1) );
@@ -167,11 +177,14 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
167 S32 max_chars = 20; 177 S32 max_chars = 20;
168 node->getAttributeS32("max_chars", max_chars); 178 node->getAttributeS32("max_chars", max_chars);
169 179
180 LLFontGL* font = LLView::selectFont(node);
181
170 LLUICtrlCallback callback = NULL; 182 LLUICtrlCallback callback = NULL;
171 183
172 LLComboBox* combo_box = new LLComboBox(name, 184 LLComboBox* combo_box = new LLComboBox(name,
173 rect, 185 rect,
174 label, 186 label,
187 font,
175 callback, 188 callback,
176 NULL); 189 NULL);
177 combo_box->setAllowTextEntry(allow_text_entry, max_chars); 190 combo_box->setAllowTextEntry(allow_text_entry, max_chars);
@@ -540,7 +553,7 @@ void LLComboBox::updateLayout()
540 mTextEntry = new LLLineEditor(std::string("combo_text_entry"), 553 mTextEntry = new LLLineEditor(std::string("combo_text_entry"),
541 text_entry_rect, 554 text_entry_rect,
542 LLStringUtil::null, 555 LLStringUtil::null,
543 LLFontGL::getFontSansSerifSmall(), 556 mGLFont,
544 mMaxChars, 557 mMaxChars,
545 onTextCommit, 558 onTextCommit,
546 onTextEntry, 559 onTextEntry,
@@ -578,6 +591,13 @@ void LLComboBox::updateLayout()
578 } 591 }
579} 592}
580 593
594
595void LLComboBox::getAllData(std::vector<LLScrollListItem*>& item_list) const
596{
597 item_list = mList->getAllData();
598}
599
600
581void* LLComboBox::getCurrentUserdata() 601void* LLComboBox::getCurrentUserdata()
582{ 602{
583 LLScrollListItem* item = mList->getFirstSelected(); 603 LLScrollListItem* item = mList->getFirstSelected();
@@ -1153,7 +1173,7 @@ LLFlyoutButton::LLFlyoutButton(
1153 const std::string& label, 1173 const std::string& label,
1154 void (*commit_callback)(LLUICtrl*, void*) , 1174 void (*commit_callback)(LLUICtrl*, void*) ,
1155 void *callback_userdata) 1175 void *callback_userdata)
1156: LLComboBox(name, rect, LLStringUtil::null, commit_callback, callback_userdata), 1176: LLComboBox(name, rect, LLStringUtil::null, NULL, commit_callback, callback_userdata),
1157 mToggleState(FALSE), 1177 mToggleState(FALSE),
1158 mActionButton(NULL) 1178 mActionButton(NULL)
1159{ 1179{
@@ -1214,6 +1234,8 @@ LLXMLNodePtr LLFlyoutButton::getXML(bool save_children) const
1214 } 1234 }
1215 } 1235 }
1216 1236
1237 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
1238
1217 return node; 1239 return node;
1218} 1240}
1219 1241
diff --git a/linden/indra/llui/llcombobox.h b/linden/indra/llui/llcombobox.h
index 95ad17a..f92fe44 100644
--- a/linden/indra/llui/llcombobox.h
+++ b/linden/indra/llui/llcombobox.h
@@ -67,7 +67,8 @@ public:
67 LLComboBox( 67 LLComboBox(
68 const std::string& name, 68 const std::string& name,
69 const LLRect &rect, 69 const LLRect &rect,
70 const std::string& label, 70 const std::string& label,
71 const LLFontGL* font = NULL,
71 void (*commit_callback)(LLUICtrl*, void*) = NULL, 72 void (*commit_callback)(LLUICtrl*, void*) = NULL,
72 void *callback_userdata = NULL 73 void *callback_userdata = NULL
73 ); 74 );
@@ -168,6 +169,7 @@ public:
168 169
169 //======================================================================== 170 //========================================================================
170 171
172 void getAllData(std::vector<LLScrollListItem*>& item_list) const;
171 void* getCurrentUserdata(); 173 void* getCurrentUserdata();
172 174
173 void setPrearrangeCallback( void (*cb)(LLUICtrl*,void*) ) { mPrearrangeCallback = cb; } 175 void setPrearrangeCallback( void (*cb)(LLUICtrl*,void*) ) { mPrearrangeCallback = cb; }
@@ -190,6 +192,7 @@ protected:
190 EPreferredPosition mListPosition; 192 EPreferredPosition mListPosition;
191 LLPointer<LLUIImage> mArrowImage; 193 LLPointer<LLUIImage> mArrowImage;
192 std::string mLabel; 194 std::string mLabel;
195 const LLFontGL* mGLFont;
193 196
194private: 197private:
195 S32 mButtonPadding; 198 S32 mButtonPadding;
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp
index f6451a1..bb42ca3 100644
--- a/linden/indra/llui/llfloater.cpp
+++ b/linden/indra/llui/llfloater.cpp
@@ -1459,9 +1459,9 @@ void LLFloater::draw()
1459 { 1459 {
1460 if (hasFocus() && getDefaultButton()->getEnabled()) 1460 if (hasFocus() && getDefaultButton()->getEnabled())
1461 { 1461 {
1462 LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); 1462 LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
1463 // is this button a direct descendent and not a nested widget (e.g. checkbox)? 1463 // is this button a direct descendent and not a nested widget (e.g. checkbox)?
1464 BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && focus_ctrl->getParent() == this; 1464 BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && dynamic_cast<LLButton*>(focus_ctrl)->getParent() == this;
1465 // only enable default button when current focus is not a button 1465 // only enable default button when current focus is not a button
1466 getDefaultButton()->setBorderEnabled(!focus_is_child_button); 1466 getDefaultButton()->setBorderEnabled(!focus_is_child_button);
1467 } 1467 }
@@ -1481,7 +1481,7 @@ void LLFloater::draw()
1481 else 1481 else
1482 { 1482 {
1483 // draw children 1483 // draw children
1484 LLView* focused_child = gFocusMgr.getKeyboardFocus(); 1484 LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
1485 BOOL focused_child_visible = FALSE; 1485 BOOL focused_child_visible = FALSE;
1486 if (focused_child && focused_child->getParent() == this) 1486 if (focused_child && focused_child->getParent() == this)
1487 { 1487 {
@@ -2239,7 +2239,7 @@ BOOL LLFloaterView::allChildrenClosed()
2239 LLView* viewp = *it; 2239 LLView* viewp = *it;
2240 LLFloater* floaterp = (LLFloater*)viewp; 2240 LLFloater* floaterp = (LLFloater*)viewp;
2241 2241
2242 if (floaterp->getVisible() && !floaterp->isDead() && floaterp->canClose()) 2242 if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable())
2243 { 2243 {
2244 return false; 2244 return false;
2245 } 2245 }
diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp
index 661ffdd..96b01b9 100644
--- a/linden/indra/llui/llfocusmgr.cpp
+++ b/linden/indra/llui/llfocusmgr.cpp
@@ -38,6 +38,68 @@
38 38
39const F32 FOCUS_FADE_TIME = 0.3f; 39const F32 FOCUS_FADE_TIME = 0.3f;
40 40
41// NOTE: the LLFocusableElement implementation has been here from lluictrl.cpp.
42
43LLFocusableElement::LLFocusableElement()
44: mFocusLostCallback(NULL),
45 mFocusReceivedCallback(NULL),
46 mFocusChangedCallback(NULL),
47 mFocusCallbackUserData(NULL)
48{
49}
50
51// virtual
52BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent)
53{
54 return FALSE;
55}
56
57// virtual
58BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
59{
60 return FALSE;
61}
62
63// virtual
64LLFocusableElement::~LLFocusableElement()
65{
66}
67
68void LLFocusableElement::onFocusReceived()
69{
70 if( mFocusReceivedCallback )
71 {
72 mFocusReceivedCallback( this, mFocusCallbackUserData );
73 }
74 if( mFocusChangedCallback )
75 {
76 mFocusChangedCallback( this, mFocusCallbackUserData );
77 }
78}
79
80void LLFocusableElement::onFocusLost()
81{
82 if( mFocusLostCallback )
83 {
84 mFocusLostCallback( this, mFocusCallbackUserData );
85 }
86
87 if( mFocusChangedCallback )
88 {
89 mFocusChangedCallback( this, mFocusCallbackUserData );
90 }
91}
92
93BOOL LLFocusableElement::hasFocus() const
94{
95 return gFocusMgr.getKeyboardFocus() == this;
96}
97
98void LLFocusableElement::setFocus(BOOL b)
99{
100}
101
102
41LLFocusMgr gFocusMgr; 103LLFocusMgr gFocusMgr;
42 104
43LLFocusMgr::LLFocusMgr() 105LLFocusMgr::LLFocusMgr()
@@ -87,11 +149,13 @@ void LLFocusMgr::releaseFocusIfNeeded( const LLView* view )
87} 149}
88 150
89 151
90void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystrokes_only) 152void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)
91{ 153{
92 if (mLockedView && 154 if (mLockedView &&
93 (new_focus == NULL || 155 (new_focus == NULL ||
94 (new_focus != mLockedView && !new_focus->hasAncestor(mLockedView)))) 156 (new_focus != mLockedView
157 && dynamic_cast<LLView*>(new_focus)
158 && !dynamic_cast<LLView*>(new_focus)->hasAncestor(mLockedView))))
95 { 159 {
96 // don't allow focus to go to anything that is not the locked focus 160 // don't allow focus to go to anything that is not the locked focus
97 // or one of its descendants 161 // or one of its descendants
@@ -121,7 +185,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
121 mFocusTimer.reset(); 185 mFocusTimer.reset();
122 186
123 #ifdef _DEBUG 187 #ifdef _DEBUG
124 mKeyboardFocusName = new_focus ? new_focus->getName() : std::string("none"); 188 LLUICtrl* focus_ctrl = dynamic_cast<LLUICtrl*>(new_focus);
189 mKeyboardFocusName = focus_ctrl ? focus_ctrl->getName() : std::string("none");
125 #endif 190 #endif
126 191
127 // If we've got a default keyboard focus, and the caller is 192 // If we've got a default keyboard focus, and the caller is
@@ -131,8 +196,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
131 mDefaultKeyboardFocus->setFocus(TRUE); 196 mDefaultKeyboardFocus->setFocus(TRUE);
132 } 197 }
133 198
134 LLView* focus_subtree = mKeyboardFocus; 199 LLView* focus_subtree = dynamic_cast<LLView*>(mKeyboardFocus);
135 LLView* viewp = mKeyboardFocus; 200 LLView* viewp = dynamic_cast<LLView*>(mKeyboardFocus);
136 // find root-most focus root 201 // find root-most focus root
137 while(viewp) 202 while(viewp)
138 { 203 {
@@ -146,7 +211,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
146 211
147 if (focus_subtree) 212 if (focus_subtree)
148 { 213 {
149 mFocusHistory[focus_subtree->getHandle()] = mKeyboardFocus ? mKeyboardFocus->getHandle() : LLHandle<LLView>(); 214 LLView* focused_view = dynamic_cast<LLView*>(mKeyboardFocus);
215 mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle<LLView>();
150 } 216 }
151 } 217 }
152 218
@@ -160,7 +226,7 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
160// Returns TRUE is parent or any descedent of parent has keyboard focus. 226// Returns TRUE is parent or any descedent of parent has keyboard focus.
161BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const 227BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const
162{ 228{
163 LLView* focus_view = mKeyboardFocus; 229 LLView* focus_view = dynamic_cast<LLView*>(mKeyboardFocus);
164 while( focus_view ) 230 while( focus_view )
165 { 231 {
166 if( focus_view == parent ) 232 if( focus_view == parent )
@@ -190,7 +256,7 @@ BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const
190 return FALSE; 256 return FALSE;
191} 257}
192 258
193void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLView* focus ) 259void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus )
194{ 260{
195 // should be ok to unlock here, as you have to know the locked view 261 // should be ok to unlock here, as you have to know the locked view
196 // in order to unlock it 262 // in order to unlock it
@@ -313,7 +379,7 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view )
313 379
314void LLFocusMgr::lockFocus() 380void LLFocusMgr::lockFocus()
315{ 381{
316 mLockedView = mKeyboardFocus; 382 mLockedView = dynamic_cast<LLUICtrl*>(mKeyboardFocus);
317} 383}
318 384
319void LLFocusMgr::unlockFocus() 385void LLFocusMgr::unlockFocus()
diff --git a/linden/indra/llui/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h
index aaeb25a..88ede1a 100644
--- a/linden/indra/llui/llfocusmgr.h
+++ b/linden/indra/llui/llfocusmgr.h
@@ -37,10 +37,39 @@
37 37
38#include "llstring.h" 38#include "llstring.h"
39#include "llframetimer.h" 39#include "llframetimer.h"
40#include "llview.h" 40#include "llui.h"
41 41
42class LLUICtrl; 42class LLUICtrl;
43class LLMouseHandler; 43class LLMouseHandler;
44class LLView;
45
46class LLFocusableElement
47{
48 friend class LLFocusMgr; // allow access to focus change handlers
49public:
50 LLFocusableElement();
51 virtual ~LLFocusableElement();
52
53 virtual void setFocus( BOOL b );
54 virtual BOOL hasFocus() const;
55
56 void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; }
57 void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; }
58 void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; }
59
60 // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus.
61 virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
62 virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
63
64protected:
65 virtual void onFocusReceived();
66 virtual void onFocusLost();
67 void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata );
68 void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata );
69 void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata );
70 void* mFocusCallbackUserData;
71};
72
44 73
45class LLFocusMgr 74class LLFocusMgr
46{ 75{
@@ -55,11 +84,11 @@ public:
55 BOOL childHasMouseCapture( const LLView* parent ) const; 84 BOOL childHasMouseCapture( const LLView* parent ) const;
56 85
57 // Keyboard Focus 86 // Keyboard Focus
58 void setKeyboardFocus(LLUICtrl* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus. 87 void setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus.
59 LLUICtrl* getKeyboardFocus() const { return mKeyboardFocus; } 88 LLFocusableElement* getKeyboardFocus() const { return mKeyboardFocus; }
60 LLUICtrl* getLastKeyboardFocus() const { return mLastKeyboardFocus; } 89 LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; }
61 BOOL childHasKeyboardFocus( const LLView* parent ) const; 90 BOOL childHasKeyboardFocus( const LLView* parent ) const;
62 void removeKeyboardFocusWithoutCallback( const LLView* focus ); 91 void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus );
63 BOOL getKeystrokesOnly() { return mKeystrokesOnly; } 92 BOOL getKeystrokesOnly() { return mKeystrokesOnly; }
64 void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; } 93 void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; }
65 94
@@ -75,8 +104,8 @@ public:
75 104
76 // If setKeyboardFocus(NULL) is called, and there is a non-NULL default 105 // If setKeyboardFocus(NULL) is called, and there is a non-NULL default
77 // keyboard focus view, focus goes there. JC 106 // keyboard focus view, focus goes there. JC
78 void setDefaultKeyboardFocus(LLUICtrl* default_focus) { mDefaultKeyboardFocus = default_focus; } 107 void setDefaultKeyboardFocus(LLFocusableElement* default_focus) { mDefaultKeyboardFocus = default_focus; }
79 LLUICtrl* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; } 108 LLFocusableElement* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; }
80 109
81 110
82 // Top View 111 // Top View
@@ -98,9 +127,9 @@ private:
98 LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object 127 LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object
99 128
100 // Keyboard Focus 129 // Keyboard Focus
101 LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object 130 LLFocusableElement* mKeyboardFocus; // Keyboard events are preemptively routed to this object
102 LLUICtrl* mLastKeyboardFocus; // who last had focus 131 LLFocusableElement* mLastKeyboardFocus; // who last had focus
103 LLUICtrl* mDefaultKeyboardFocus; 132 LLFocusableElement* mDefaultKeyboardFocus;
104 BOOL mKeystrokesOnly; 133 BOOL mKeystrokesOnly;
105 134
106 // Top View 135 // Top View
diff --git a/linden/indra/llui/llfunctorregistry.cpp b/linden/indra/llui/llfunctorregistry.cpp
index 0c5b165..5f9644f 100644
--- a/linden/indra/llui/llfunctorregistry.cpp
+++ b/linden/indra/llui/llfunctorregistry.cpp
@@ -31,6 +31,7 @@
31 * $/LicenseInfo$ 31 * $/LicenseInfo$
32 **/ 32 **/
33 33
34#include "linden_common.h"
34#include "llfunctorregistry.h" 35#include "llfunctorregistry.h"
35 36
36// This is a default functor always resident in the system. 37// This is a default functor always resident in the system.
diff --git a/linden/indra/llui/lliconctrl.cpp b/linden/indra/llui/lliconctrl.cpp
index e73c8fe..0df960e 100644
--- a/linden/indra/llui/lliconctrl.cpp
+++ b/linden/indra/llui/lliconctrl.cpp
@@ -112,6 +112,12 @@ void LLIconCtrl::draw()
112 LLUICtrl::draw(); 112 LLUICtrl::draw();
113} 113}
114 114
115// virtual
116void LLIconCtrl::setAlpha(F32 alpha)
117{
118 mColor.setAlpha(alpha);
119}
120
115// virtual 121// virtual
116void LLIconCtrl::setValue(const LLSD& value ) 122void LLIconCtrl::setValue(const LLSD& value )
117{ 123{
diff --git a/linden/indra/llui/lliconctrl.h b/linden/indra/llui/lliconctrl.h
index 50778cf..2506fb2 100644
--- a/linden/indra/llui/lliconctrl.h
+++ b/linden/indra/llui/lliconctrl.h
@@ -65,6 +65,8 @@ public:
65 virtual void setValue(const LLSD& value ); 65 virtual void setValue(const LLSD& value );
66 virtual LLSD getValue() const; 66 virtual LLSD getValue() const;
67 67
68 /*virtual*/ void setAlpha(F32 alpha);
69
68 void setColor(const LLColor4& color) { mColor = color; } 70 void setColor(const LLColor4& color) { mColor = color; }
69 71
70 virtual LLXMLNodePtr getXML(bool save_children = true) const; 72 virtual LLXMLNodePtr getXML(bool save_children = true) const;
diff --git a/linden/indra/llui/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp
index 21f0800..453bb50 100644
--- a/linden/indra/llui/lllineeditor.cpp
+++ b/linden/indra/llui/lllineeditor.cpp
@@ -37,7 +37,6 @@
37#include "lllineeditor.h" 37#include "lllineeditor.h"
38 38
39#include "lltexteditor.h" 39#include "lltexteditor.h"
40#include "audioengine.h"
41#include "llmath.h" 40#include "llmath.h"
42#include "llfontgl.h" 41#include "llfontgl.h"
43#include "llgl.h" 42#include "llgl.h"
@@ -56,12 +55,24 @@
56#include "llui.h" 55#include "llui.h"
57#include "lluictrlfactory.h" 56#include "lluictrlfactory.h"
58#include "llclipboard.h" 57#include "llclipboard.h"
58#include "llmemberlistener.h"
59
60#include "../newview/lgghunspell_wrapper.h"
61#include "../newview/lltranslate.h"
62#include "../newview/llviewercontrol.h"
63#include "../newview/lggautocorrect.h"
64
59 65
60// 66//
61// Imported globals 67// Imported globals
62// 68//
63 69
64// 70//
71// Globals
72
73
74
75//
65// Constants 76// Constants
66// 77//
67 78
@@ -86,9 +97,41 @@ static LLRegisterWidget<LLLineEditor> r1("line_editor");
86 97
87/* static */ LLPointer<LLUIImage> LLLineEditor::sImage; 98/* static */ LLPointer<LLUIImage> LLLineEditor::sImage;
88 99
100typedef LLMemberListener<LLView> text_edit_listener_t;
101
89// 102//
90// Member functions 103// Member functions
91// 104//
105class LineChatTranslationReceiver : public LLTranslate::TranslationReceiver
106{
107public :
108 LineChatTranslationReceiver(const std::string &toLang, LLLineEditor* line, const S32 start, const S32 len):
109 LLTranslate::TranslationReceiver("", toLang),
110 m_line(line),
111 m_position(start),
112 m_origLength(len)
113 {
114 }
115
116 static boost::intrusive_ptr<LineChatTranslationReceiver> build(const std::string &toLang,LLLineEditor* line, const S32 start, const S32 len)
117 {
118 return boost::intrusive_ptr<LineChatTranslationReceiver>(new LineChatTranslationReceiver(toLang, line, start, len));
119 }
120
121protected:
122 void handleResponse(const std::string &translation, const std::string &detectedLanguage)
123 {
124 m_line->translationReplace(translation, m_position, m_origLength);
125 }
126 void handleFailure()
127 {
128 LLTranslate::TranslationReceiver::handleFailure();
129 }
130private:
131 LLLineEditor* m_line;
132 S32 m_position;
133 S32 m_origLength;
134};
92 135
93LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, 136LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
94 const std::string& default_text, const LLFontGL* font, 137 const std::string& default_text, const LLFontGL* font,
@@ -104,6 +147,7 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
104 : 147 :
105 LLUICtrl( name, rect, TRUE, commit_callback, userdata, FOLLOWS_TOP | FOLLOWS_LEFT ), 148 LLUICtrl( name, rect, TRUE, commit_callback, userdata, FOLLOWS_TOP | FOLLOWS_LEFT ),
106 mMaxLengthBytes(max_length_bytes), 149 mMaxLengthBytes(max_length_bytes),
150 mPopupMenuHandle(),
107 mCursorPos( 0 ), 151 mCursorPos( 0 ),
108 mScrollHPos( 0 ), 152 mScrollHPos( 0 ),
109 mTextPadLeft(0), 153 mTextPadLeft(0),
@@ -118,6 +162,7 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
118 mLastSelectionY(-1), 162 mLastSelectionY(-1),
119 mLastSelectionStart(-1), 163 mLastSelectionStart(-1),
120 mLastSelectionEnd(-1), 164 mLastSelectionEnd(-1),
165 mLastContextMenuX(-1),
121 mPrevalidateFunc( prevalidate_func ), 166 mPrevalidateFunc( prevalidate_func ),
122 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), 167 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ),
123 mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ), 168 mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ),
@@ -137,7 +182,9 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
137 mReadOnly(FALSE), 182 mReadOnly(FALSE),
138 mHaveHistory(FALSE), 183 mHaveHistory(FALSE),
139 mImage( sImage ), 184 mImage( sImage ),
140 mReplaceNewlinesWithSpaces( TRUE ) 185 mReplaceNewlinesWithSpaces( TRUE ),
186 mSpellCheckable( FALSE ),
187 mAllowTranslate(TRUE)
141{ 188{
142 llassert( max_length_bytes > 0 ); 189 llassert( max_length_bytes > 0 );
143 190
@@ -175,6 +222,19 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
175 sImage = LLUI::getUIImage("sm_rounded_corners_simple.tga"); 222 sImage = LLUI::getUIImage("sm_rounded_corners_simple.tga");
176 } 223 }
177 mImage = sImage; 224 mImage = sImage;
225
226
227 LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_rightclick_text.xml",this);
228 if (!menu)
229 {
230 menu = new LLMenuGL(LLStringUtil::null);
231 }
232
233 defineMenuCallbacks(menu);
234 mPopupMenuHandle = menu->getHandle();
235 menu->setBorderColor(gColors.getColor("MenuItemDisabledColor"));
236 menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
237
178} 238}
179 239
180 240
@@ -188,6 +248,7 @@ LLLineEditor::~LLLineEditor()
188 { 248 {
189 gEditMenuHandler = NULL; 249 gEditMenuHandler = NULL;
190 } 250 }
251 LLView::deleteViewByHandle(mPopupMenuHandle);
191} 252}
192 253
193 254
@@ -336,14 +397,23 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
336 setCursor(llmin((S32)mText.length(), getCursor())); 397 setCursor(llmin((S32)mText.length(), getCursor()));
337 398
338 // Set current history line to end of history. 399 // Set current history line to end of history.
339 mCurrentHistoryLine = mLineHistory.end() - 1; 400 // RC Fix, its really not safe to just take 1 of the end itterator, if end==begin
401 // that leaves an invalid state upseting the secure STL checks
402 if(mLineHistory.empty())
403 {
404 mCurrentHistoryLine = mLineHistory.begin();
405 }
406 else
407 {
408 mCurrentHistoryLine = mLineHistory.end() - 1;
409 }
340 410
341 mPrevText = mText; 411 mPrevText = mText;
342} 412}
343 413
344 414
345// Picks a new cursor position based on the actual screen size of text being drawn. 415// Picks a new cursor position based on the actual screen size of text being drawn.
346void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x ) 416S32 LLLineEditor::calculateCursorFromMouse( S32 local_mouse_x ) const
347{ 417{
348 const llwchar* wtext = mText.getWString().c_str(); 418 const llwchar* wtext = mText.getWString().c_str();
349 LLWString asterix_text; 419 LLWString asterix_text;
@@ -356,13 +426,17 @@ void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )
356 wtext = asterix_text.c_str(); 426 wtext = asterix_text.c_str();
357 } 427 }
358 428
359 S32 cursor_pos = 429 return mScrollHPos +
360 mScrollHPos +
361 mGLFont->charFromPixelOffset( 430 mGLFont->charFromPixelOffset(
362 wtext, mScrollHPos, 431 wtext, mScrollHPos,
363 (F32)(local_mouse_x - mMinHPixels), 432 (F32)(local_mouse_x - mMinHPixels),
364 (F32)(mMaxHPixels - mMinHPixels + 1)); // min-max range is inclusive 433 (F32)(mMaxHPixels - mMinHPixels + 1)); // min-max range is inclusive
365 setCursor(cursor_pos); 434
435}
436// Picks a new cursor position based on the actual screen size of text being drawn.
437void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )
438{
439 setCursor(calculateCursorFromMouse(local_mouse_x));
366} 440}
367 441
368void LLLineEditor::setCursor( S32 pos ) 442void LLLineEditor::setCursor( S32 pos )
@@ -417,6 +491,188 @@ void LLLineEditor::deselect()
417 mIsSelecting = FALSE; 491 mIsSelecting = FALSE;
418} 492}
419 493
494BOOL LLLineEditor::context_enable_cut(void* data)
495{
496 LLLineEditor* line = (LLLineEditor*)data;
497 return (line && line->canCut());
498}
499
500void LLLineEditor::context_cut(void* data)
501{
502 LLLineEditor* line = (LLLineEditor*)data;
503 if(line)line->cut();
504}
505
506BOOL LLLineEditor::context_enable_copy(void* data)
507{
508 LLLineEditor* line = (LLLineEditor*)data;
509 return (line &&line->canCopy());
510}
511
512void LLLineEditor::context_copy(void* data)
513{
514 LLLineEditor* line = (LLLineEditor*)data;
515 if(line)line->copy();
516}
517
518void LLLineEditor::spell_correct(void* data)
519{
520 SpellMenuBind* tempBind = (SpellMenuBind*)data;
521 LLLineEditor* line = tempBind->origin;
522 if(tempBind && line)
523 {
524 llinfos << ((LLMenuItemCallGL *)(tempBind->menuItem))->getName() << " : " << tempBind->origin->getName() << " : " << tempBind->word << llendl;
525 if(line)line->spellReplace(tempBind);
526
527 }
528}
529
530BOOL LLLineEditor::context_enable_translate(void* data)
531{
532 LLLineEditor* line = (LLLineEditor*)data;
533 return line && line->canTranslate();
534}
535
536void LLLineEditor::context_translate(void * data)
537{
538 LLLineEditor* line = (LLLineEditor*)data;
539 LLMenuGL* menu = line ? (LLMenuGL*)(line->mPopupMenuHandle.get()) : NULL;
540 LLMenuGL* translate_menu = menu ? menu->getChildMenuByName("Translation Options", TRUE) : NULL;
541 if (!translate_menu)
542 {
543 return;
544 }
545 const std::string to_lang = translate_menu->getHighlightedItem()->getName();
546
547 bool has_text = false;
548 S32 start, length;
549 if (line->hasSelection())
550 {
551 // translate selection
552 start = llmin(line->mSelectionStart, line->mSelectionEnd);
553 length = abs(line->mSelectionEnd - line->mSelectionStart);
554 has_text = length > 0;
555 }
556 else
557 {
558 // translate one word at click position
559 S32 at = line->calculateCursorFromMouse(line->mLastContextMenuX);
560 has_text = line->getWordBoundriesAt(at, &start, &length);
561 }
562
563 if (has_text)
564 {
565 std::string to_translate = wstring_to_utf8str(line->getWText().substr(start, length));
566 LLHTTPClient::ResponderPtr result = LineChatTranslationReceiver::build(to_lang, line, start, length);
567 LLTranslate::translateMessage(result,"", to_lang, to_translate);
568 }
569}
570
571void LLLineEditor::spell_show(void * data)
572{
573 SpellMenuBind* tempBind = (SpellMenuBind*)data;
574 LLLineEditor* line = tempBind->origin;
575
576 if (tempBind && line)
577 {
578 BOOL show = (tempBind->word == "Show Misspellings");
579 glggHunSpell->setSpellCheckHighlight(show);
580 }
581}
582
583void LLLineEditor::getMisspelledWordsPositions(std::vector<S32>& misspell_positions)
584{
585 misspell_positions.clear();
586 const LLWString& text = mText.getWString();
587
588 //llinfos << "end of box is at " << cursorloc << " and end of text is at " << text.length() << llendl;
589 S32 wordStart=0;
590 S32 wordEnd=mStartSpellHere;
591 while(wordEnd < mEndSpellHere)
592 {
593 //go through all the chars... XD
594 if( LLTextEditor::isPartOfWord( text[wordEnd] ) )
595
596 {
597 // Select word the cursor is over
598 while ((wordEnd > 0) && LLTextEditor::isPartOfWord(text[wordEnd-1]))
599 {
600 wordEnd--;
601 }
602 wordStart=wordEnd;
603 while ((wordEnd < (S32)text.length()) && LLTextEditor::isPartOfWord( text[wordEnd] ) )
604 {
605 wordEnd++;
606 }
607
608 //got a word? -- MC
609 if (wordStart != wordEnd)
610 {
611 std::string selectedWord(std::string(text.begin(),
612 text.end()).substr(wordStart,wordEnd-wordStart));
613
614 if(!selectedWord.empty() && !glggHunSpell->isSpelledRight(selectedWord))
615 {
616 //misspelled word here, and you have just right clicked on it!
617 //get the center of this word..
618 //S32 center = llround( (wordEnd-wordStart)/2 ) + wordStart;
619 //turn this cursor position into a pixel pos
620 //center = findPixelNearestPos(center-getCursor());
621
622 misspell_positions.push_back(wordStart);
623 misspell_positions.push_back(wordEnd);
624 }
625 }
626 }
627 wordEnd++;
628 }
629}
630
631void LLLineEditor::spell_add(void* data)
632{
633 SpellMenuBind* tempBind = (SpellMenuBind*)data;
634 if (tempBind)
635 {
636 glggHunSpell->addWordToCustomDictionary(tempBind->word);
637 tempBind->origin->mPrevSpelledText="";//make it update
638 }
639}
640
641BOOL LLLineEditor::context_enable_paste(void* data)
642{
643 LLLineEditor* line = (LLLineEditor*)data;
644 return (line && line->canPaste());
645}
646
647void LLLineEditor::context_paste(void* data)
648{
649 LLLineEditor* line = (LLLineEditor*)data;
650 if(line)line->paste();
651}
652
653BOOL LLLineEditor::context_enable_delete(void* data)
654{
655 LLLineEditor* line = (LLLineEditor*)data;
656 return (line && line->canDoDelete());
657}
658
659void LLLineEditor::context_delete(void* data)
660{
661 LLLineEditor* line = (LLLineEditor*)data;
662 if(line)line->doDelete();
663}
664
665BOOL LLLineEditor::context_enable_selectall(void* data)
666{
667 LLLineEditor* line = (LLLineEditor*)data;
668 return (line && line->canSelectAll());
669}
670
671void LLLineEditor::context_selectall(void* data)
672{
673 LLLineEditor* line = (LLLineEditor*)data;
674 if(line)line->selectAll();
675}
420 676
421void LLLineEditor::startSelection() 677void LLLineEditor::startSelection()
422{ 678{
@@ -508,6 +764,105 @@ BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
508 return TRUE; 764 return TRUE;
509} 765}
510 766
767
768BOOL LLLineEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
769{
770 setFocus(TRUE);
771
772 //setCursorAtLocalPos( x);
773 S32 wordStart = 0;
774 S32 wordLen = 0;
775 S32 pos = calculateCursorFromMouse(x);
776
777 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
778 if (menu)
779 {
780 if(menu->isOpen())
781 {
782 menu->setVisible(FALSE);
783 }
784 for (int i = 0;i<(int)suggestionMenuItems.size();i++)
785 {
786 SpellMenuBind * tempBind = suggestionMenuItems[i];
787 if (tempBind)
788 {
789 menu->remove((LLMenuItemCallGL *)tempBind->menuItem);
790 ((LLMenuItemCallGL *)tempBind->menuItem)->die();
791 //delete tempBind->menuItem;
792 //tempBind->menuItem = NULL;
793 delete tempBind;
794 }
795 }
796 suggestionMenuItems.clear();
797
798 // spell_check="true" in xui
799 menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable);
800 if (!mReadOnly && mSpellCheckable)
801 {
802 // search for word matches
803 bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen);
804 if (is_word_part)
805 {
806 const LLWString& text = mText.getWString();
807 std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen));
808
809 if (!glggHunSpell->isSpelledRight(selectedWord))
810 {
811 //misspelled word here, and you have just right clicked on it!
812 std::vector<std::string> suggs = glggHunSpell->getSuggestionList(selectedWord);
813
814 for (int i = 0; i<(int)suggs.size() ;i++)
815 {
816 SpellMenuBind * tempStruct = new SpellMenuBind;
817 tempStruct->origin = this;
818 tempStruct->word = suggs[i];
819 tempStruct->wordPositionEnd = wordStart + wordLen;
820 tempStruct->wordPositionStart=wordStart;
821 LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL(
822 tempStruct->word, spell_correct, NULL, tempStruct);
823 //new LLMenuItemCallGL("Select All", context_selectall, NULL, this));
824 tempStruct->menuItem = suggMenuItem;
825 suggestionMenuItems.push_back(tempStruct);
826 menu->append(suggMenuItem);
827 }
828 SpellMenuBind * tempStruct = new SpellMenuBind;
829 tempStruct->origin = this;
830 tempStruct->word = selectedWord;
831 tempStruct->wordPositionEnd = wordStart + wordLen;
832 tempStruct->wordPositionStart=wordStart;
833 LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL(
834 "Add Word", spell_add, NULL, tempStruct);
835 tempStruct->menuItem = suggMenuItem;
836 suggestionMenuItems.push_back(tempStruct);
837 menu->append(suggMenuItem);
838 }
839 }
840
841 SpellMenuBind * tempStruct = new SpellMenuBind;
842 tempStruct->origin = this;
843 if (glggHunSpell->getSpellCheckHighlight())
844 {
845 tempStruct->word = "Hide Misspellings";
846 }
847 else
848 {
849 tempStruct->word = "Show Misspellings";
850 }
851 LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL(
852 tempStruct->word, spell_show, NULL, tempStruct);
853 tempStruct->menuItem = suggMenuItem;
854 suggestionMenuItems.push_back(tempStruct);
855 menu->append(suggMenuItem);
856 }
857
858 mLastContextMenuX = x;
859 menu->buildDrawLabels();
860 menu->updateParent(LLMenuGL::sMenuContainer);
861 LLMenuGL::showPopup(this, menu, x, y);
862 }
863 return TRUE;
864}
865
511BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask) 866BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
512{ 867{
513 // Check first whether the "clear search" button wants to deal with this. 868 // Check first whether the "clear search" button wants to deal with this.
@@ -662,6 +1017,11 @@ BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask)
662 1017
663 return handled; 1018 return handled;
664} 1019}
1020BOOL LLLineEditor::handleHScrollWheel(S32 x, S32 y, S32 clicks)
1021{
1022 mScrollHPos = llclamp(mScrollHPos + clicks * 3, 0, mText.length());
1023 return TRUE;
1024}
665 1025
666 1026
667BOOL LLLineEditor::handleMouseUp(S32 x, S32 y, MASK mask) 1027BOOL LLLineEditor::handleMouseUp(S32 x, S32 y, MASK mask)
@@ -774,13 +1134,9 @@ void LLLineEditor::setSelection(S32 start, S32 end)
774{ 1134{
775 S32 len = mText.length(); 1135 S32 len = mText.length();
776 1136
777 mIsSelecting = TRUE; 1137 mSelectionStart = llclamp(start, 0, len);
778 1138 mSelectionEnd = llclamp(end, 0, len);
779 // JC, yes, this seems odd, but I think you have to presume a 1139 setCursor(end);
780 // selection dragged from the end towards the start.
781 mSelectionStart = llclamp(end, 0, len);
782 mSelectionEnd = llclamp(start, 0, len);
783 setCursor(start);
784} 1140}
785 1141
786void LLLineEditor::setDrawAsterixes(BOOL b) 1142void LLLineEditor::setDrawAsterixes(BOOL b)
@@ -817,6 +1173,26 @@ S32 LLLineEditor::nextWordPos(S32 cursorPos) const
817 return cursorPos; 1173 return cursorPos;
818} 1174}
819 1175
1176BOOL LLLineEditor::getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const
1177{
1178 const LLWString& wtext = mText.getWString();
1179 S32 pos = at;
1180 if (LLTextEditor::isPartOfWord(wtext[pos]))
1181 {
1182 while ( (pos > 0) && LLTextEditor::isPartOfWord(wtext[pos - 1]) )
1183 {
1184 pos--;
1185 }
1186 *word_begin = pos;
1187 while ( (pos < (S32)wtext.length()) && LLTextEditor::isPartOfWord(wtext[pos]) )
1188 {
1189 pos++;
1190 }
1191 *word_length = pos - *word_begin;
1192 return TRUE;
1193 }
1194 return FALSE;
1195}
820 1196
821BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask) 1197BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask)
822{ 1198{
@@ -912,7 +1288,7 @@ void LLLineEditor::deleteSelection()
912 if( !mReadOnly && hasSelection() ) 1288 if( !mReadOnly && hasSelection() )
913 { 1289 {
914 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 1290 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
915 S32 selection_length = abs( mSelectionStart - mSelectionEnd ); 1291 S32 selection_length = llabs( mSelectionStart - mSelectionEnd );
916 1292
917 mText.erase(left_pos, selection_length); 1293 mText.erase(left_pos, selection_length);
918 deselect(); 1294 deselect();
@@ -925,6 +1301,67 @@ BOOL LLLineEditor::canCut() const
925 return !mReadOnly && !mDrawAsterixes && hasSelection(); 1301 return !mReadOnly && !mDrawAsterixes && hasSelection();
926} 1302}
927 1303
1304// method to define the associated callbacks
1305void LLLineEditor::defineMenuCallbacks(LLMenuGL* menu) {
1306
1307 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
1308 "Cut Text",
1309 this,
1310 (void*)context_enable_cut);
1311 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
1312 "Cut Text",
1313 this,
1314 (void*)context_cut);
1315
1316 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
1317 "Copy Text",
1318 this,
1319 (void*)context_enable_copy);
1320 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
1321 "Copy Text",
1322 this,
1323 (void*)context_copy);
1324
1325 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
1326 "Paste Text",
1327 this,
1328 (void*)context_enable_paste);
1329 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
1330 "Paste Text",
1331 this,
1332 (void*)context_paste);
1333
1334 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
1335 "Delete Text",
1336 this,
1337 (void*)context_enable_delete);
1338 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
1339 "Delete Text",
1340 this,
1341 (void*)context_delete);
1342
1343 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
1344 "Select All Text",
1345 this,
1346 (void*)context_enable_selectall);
1347 menu->setCtrlResponse(1+LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
1348 "Select All Text",
1349 this,
1350 (void*)context_selectall);
1351
1352 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
1353 "Translate Text",
1354 this,
1355 (void*)context_enable_translate);
1356 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_TRANSLATE,
1357 "Translate Text",
1358 this,
1359 (void*)context_translate);
1360
1361
1362
1363}
1364
928// cut selection to clipboard 1365// cut selection to clipboard
929void LLLineEditor::cut() 1366void LLLineEditor::cut()
930{ 1367{
@@ -935,7 +1372,7 @@ void LLLineEditor::cut()
935 1372
936 1373
937 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 1374 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
938 S32 length = abs( mSelectionStart - mSelectionEnd ); 1375 S32 length = llabs( mSelectionStart - mSelectionEnd );
939 gClipboard.copyFromSubstring( mText.getWString(), left_pos, length ); 1376 gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
940 deleteSelection(); 1377 deleteSelection();
941 1378
@@ -966,11 +1403,69 @@ void LLLineEditor::copy()
966 if( canCopy() ) 1403 if( canCopy() )
967 { 1404 {
968 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 1405 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
969 S32 length = abs( mSelectionStart - mSelectionEnd ); 1406 S32 length = llabs( mSelectionStart - mSelectionEnd );
970 gClipboard.copyFromSubstring( mText.getWString(), left_pos, length ); 1407 gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
971 } 1408 }
972} 1409}
973 1410
1411void LLLineEditor::spellReplace(SpellMenuBind* spellData)
1412{
1413 mText.erase(spellData->wordPositionStart,
1414 spellData->wordPositionEnd - spellData->wordPositionStart);
1415 insert(spellData->word,spellData->wordPositionStart);
1416 mCursorPos+=spellData->word.length() - (spellData->wordPositionEnd-spellData->wordPositionStart);
1417
1418
1419}
1420
1421void LLLineEditor::translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length)
1422{
1423 //*TODO: should probably check if the content was modified since the http query
1424 // was made, so we don't insert text in the wrong place.
1425 BOOL replace = gSavedSettings.getBOOL("EmeraldTranslateReplace");
1426 std::string text = replace ? translation : " (" + translation + ")";
1427 S32 pos = replace ? orig_start : orig_start + orig_length;
1428 if (replace)
1429 {
1430 mText.erase(orig_start, orig_length);
1431 }
1432 insert(text, pos);
1433
1434 S32 text_wlen = utf8str_to_wstring(text).length();
1435 if (hasSelection())
1436 {
1437 setSelection(pos, pos + text_wlen);
1438 }
1439 setCursor(pos + text_wlen);
1440}
1441
1442BOOL LLLineEditor::canTranslate() const
1443{
1444 // if allow_translate="true" in xui, and if other factors permit, we allow it
1445 S32 pos = calculateCursorFromMouse(mLastContextMenuX);
1446 const LLWString& wtext = getWText();
1447 bool is_word_part = (pos > -1) && LLTextEditor::isPartOfWord(wtext[pos]);
1448 return (mAllowTranslate && !mReadOnly && (is_word_part || hasSelection()));
1449}
1450
1451void LLLineEditor::insert(std::string what, S32 wher)
1452{
1453 LLLineEditorRollback rollback(this);
1454 LLWString clean_string(utf8str_to_wstring(what));
1455 LLWStringUtil::replaceTabsWithSpaces(clean_string, 4);
1456 mText.insert(wher, clean_string);
1457 //see if we should move over the cursor acordingly
1458 // Validate new string and rollback the if needed.
1459 BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
1460 if( need_to_rollback )
1461 {
1462 rollback.doRollback( this );
1463 reportBadKeystroke();
1464 }
1465 else if( mKeystrokeCallback )
1466 mKeystrokeCallback( this, mCallbackUserData );
1467}
1468
974BOOL LLLineEditor::canPaste() const 1469BOOL LLLineEditor::canPaste() const
975{ 1470{
976 return !mReadOnly && gClipboard.canPasteString(); 1471 return !mReadOnly && gClipboard.canPasteString();
@@ -993,17 +1488,25 @@ void LLLineEditor::pasteHelper(bool is_primary)
993{ 1488{
994 bool can_paste_it; 1489 bool can_paste_it;
995 if (is_primary) 1490 if (is_primary)
1491 {
996 can_paste_it = canPastePrimary(); 1492 can_paste_it = canPastePrimary();
1493 }
997 else 1494 else
1495 {
998 can_paste_it = canPaste(); 1496 can_paste_it = canPaste();
1497 }
999 1498
1000 if (can_paste_it) 1499 if (can_paste_it)
1001 { 1500 {
1002 LLWString paste; 1501 LLWString paste;
1003 if (is_primary) 1502 if (is_primary)
1503 {
1004 paste = gClipboard.getPastePrimaryWString(); 1504 paste = gClipboard.getPastePrimaryWString();
1505 }
1005 else 1506 else
1507 {
1006 paste = gClipboard.getPasteWString(); 1508 paste = gClipboard.getPasteWString();
1509 }
1007 1510
1008 if (!paste.empty()) 1511 if (!paste.empty())
1009 { 1512 {
@@ -1018,7 +1521,7 @@ void LLLineEditor::pasteHelper(bool is_primary)
1018 1521
1019 // Clean up string (replace tabs and returns and remove characters that our fonts don't support.) 1522 // Clean up string (replace tabs and returns and remove characters that our fonts don't support.)
1020 LLWString clean_string(paste); 1523 LLWString clean_string(paste);
1021 LLWStringUtil::replaceTabsWithSpaces(clean_string, 1); 1524 LLWStringUtil::replaceTabsWithSpaces(clean_string, 4);
1022 //clean_string = wstring_detabify(paste, 1); 1525 //clean_string = wstring_detabify(paste, 1);
1023 LLWStringUtil::replaceChar(clean_string, '\n', mReplaceNewlinesWithSpaces ? ' ' : 182); // 182 == paragraph character 1526 LLWStringUtil::replaceChar(clean_string, '\n', mReplaceNewlinesWithSpaces ? ' ' : 182); // 182 == paragraph character
1024 1527
@@ -1074,7 +1577,7 @@ void LLLineEditor::copyPrimary()
1074 if( canCopy() ) 1577 if( canCopy() )
1075 { 1578 {
1076 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 1579 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
1077 S32 length = abs( mSelectionStart - mSelectionEnd ); 1580 S32 length = llabs( mSelectionStart - mSelectionEnd );
1078 gClipboard.copyFromPrimarySubstring( mText.getWString(), left_pos, length ); 1581 gClipboard.copyFromPrimarySubstring( mText.getWString(), left_pos, length );
1079 } 1582 }
1080} 1583}
@@ -1322,6 +1825,14 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )
1322 BOOL handled = FALSE; 1825 BOOL handled = FALSE;
1323 BOOL selection_modified = FALSE; 1826 BOOL selection_modified = FALSE;
1324 1827
1828 // SL-51858: Key presses are not being passed to the Popup menu.
1829 // A proper fix is non-trivial so instead just close the menu.
1830 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
1831 if (menu && menu->isOpen())
1832 {
1833 LLMenuGL::sMenuContainer->hideMenus();
1834 }
1835
1325 if ( gFocusMgr.getKeyboardFocus() == this ) 1836 if ( gFocusMgr.getKeyboardFocus() == this )
1326 { 1837 {
1327 LLLineEditorRollback rollback( this ); 1838 LLLineEditorRollback rollback( this );
@@ -1396,6 +1907,13 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
1396 1907
1397 if ( (gFocusMgr.getKeyboardFocus() == this) && getVisible() && !mReadOnly) 1908 if ( (gFocusMgr.getKeyboardFocus() == this) && getVisible() && !mReadOnly)
1398 { 1909 {
1910 // SL-51858: Key presses are not being passed to the Popup menu.
1911 // A proper fix is non-trivial so instead just close the menu.
1912 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
1913 if (menu && menu->isOpen())
1914 {
1915 LLMenuGL::sMenuContainer->hideMenus();
1916 }
1399 handled = TRUE; 1917 handled = TRUE;
1400 1918
1401 LLLineEditorRollback rollback( this ); 1919 LLLineEditorRollback rollback( this );
@@ -1472,9 +1990,106 @@ void LLLineEditor::doDelete()
1472 } 1990 }
1473} 1991}
1474 1992
1993void LLLineEditor::autoCorrectText()
1994{
1995 static BOOL *doAnything = rebind_llcontrol<BOOL>("EmeraldEnableAutoCorrect", &gSavedSettings, true);
1996 if (!mReadOnly && *doAnything && isSpellDirty())
1997 {
1998 S32 wordStart = 0;
1999 S32 wordEnd = mCursorPos-1;
2000 //llinfos <<"Checking Word, Cursor is at "<<mCursorPos<<" and text is "<<mText.getString().c_str()<<llendl;
2001 if (wordEnd < 1)
2002 {
2003 return;
2004 }
2005 const LLWString& text = mText.getWString();
2006 if (text.size() < 1 || LLTextEditor::isPartOfWord(text[wordEnd]))
2007 {
2008 return;//we only check on word breaks
2009 }
2010
2011 wordEnd--;
2012 if (LLTextEditor::isPartOfWord(text[wordEnd]))
2013 {
2014 while ((wordEnd > 0) && (' '!=text[wordEnd-1]))
2015 {
2016 wordEnd--;
2017 }
2018 wordStart = wordEnd;
2019 while ((wordEnd < (S32)text.length()) && (' '!=text[wordEnd] ) )
2020 {
2021 wordEnd++;
2022 }
2023 std::string lastTypedWord(std::string(text.begin(),
2024 text.end()).substr(wordStart, wordEnd-wordStart));
2025 //llinfos << " The last typed word has been chosen, it is "<<lastTypedWord.c_str()<<llendl;
2026
2027 std::string correctedWord(LGGAutoCorrect::getInstance()->replaceWord(lastTypedWord));
2028 if(correctedWord != lastTypedWord)
2029 {
2030 int dif = correctedWord.length()-lastTypedWord.length();
2031 std::string regText(mText);
2032 //int wordStart = regText.find(lastTypedWord);
2033 regText.replace(wordStart,lastTypedWord.length(),correctedWord);
2034 mText=regText;
2035 mCursorPos+=dif;
2036 }
2037 }
2038 }
2039}
2040
2041void LLLineEditor::drawMisspelled(const LLRect& background)
2042{
2043 if (!mReadOnly && mSpellCheckable)
2044 {
2045 S32 newStartSpellHere = mScrollHPos;
2046 S32 cursorloc = calculateCursorFromMouse(mMaxHPixels);
2047 S32 newStopSpellHere = (((S32)mText.length())>cursorloc) ? cursorloc : (S32)mText.length();
2048
2049 F32 elapsed = mSpellTimer.getElapsedTimeF32();
2050 if (S32(elapsed / 1) & 1)
2051 {
2052 if (isSpellDirty() || (newStartSpellHere != mStartSpellHere) || ( newStopSpellHere != mEndSpellHere))
2053 {
2054 mStartSpellHere = newStartSpellHere;
2055 mEndSpellHere = newStopSpellHere;
2056 resetSpellDirty();
2057 getMisspelledWordsPositions(mMisspellLocations);
2058 }
2059 }
2060
2061 if (!mMisspellLocations.empty() && glggHunSpell->getSpellCheckHighlight())
2062 {
2063 for (int i =0; i<(int)mMisspellLocations.size(); i++)
2064 {
2065 S32 wstart =findPixelNearestPos( mMisspellLocations[i]-getCursor());
2066 S32 wend = findPixelNearestPos(mMisspellLocations[++i]-getCursor());
2067 S32 maxw = getRect().getWidth();
2068
2069 if (wend > maxw)
2070 {
2071 wend = maxw;
2072 }
2073 if (wstart > maxw)
2074 {
2075 wstart = maxw;
2076 }
2077 gGL.color4ub(255,0,0,200);
2078 //3 line zig zags..
2079 while (wstart < wend)
2080 {
2081 gl_line_2d(wstart, background.mBottom-1, wstart+3, background.mBottom+2);
2082 gl_line_2d(wstart+3, background.mBottom+2, wstart+6, background.mBottom-1);
2083 wstart+=6;
2084 }
2085 }
2086 }
2087 }
2088}
1475 2089
1476void LLLineEditor::draw() 2090void LLLineEditor::draw()
1477{ 2091{
2092 autoCorrectText();
1478 S32 text_len = mText.length(); 2093 S32 text_len = mText.length();
1479 2094
1480 std::string saved_text; 2095 std::string saved_text;
@@ -1661,6 +2276,9 @@ void LLLineEditor::draw()
1661 mBorder->setVisible(FALSE); // no more programmatic art. 2276 mBorder->setVisible(FALSE); // no more programmatic art.
1662#endif 2277#endif
1663 2278
2279 drawMisspelled(background);
2280 resetSpellDirty();
2281
1664 // If we're editing... 2282 // If we're editing...
1665 if( gFocusMgr.getKeyboardFocus() == this) 2283 if( gFocusMgr.getKeyboardFocus() == this)
1666 { 2284 {
@@ -2122,7 +2740,6 @@ BOOL LLLineEditor::prevalidatePrintableNotPipe(const LLWString &str)
2122 return rv; 2740 return rv;
2123} 2741}
2124 2742
2125
2126// static 2743// static
2127BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str) 2744BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str)
2128{ 2745{
@@ -2147,6 +2764,25 @@ BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str)
2147} 2764}
2148 2765
2149// static 2766// static
2767BOOL LLLineEditor::prevalidatePrintableSpace(const LLWString &str)
2768{
2769 BOOL rv = TRUE;
2770 S32 len = str.length();
2771 if(len == 0) return rv;
2772 while(len--)
2773 {
2774 if( !(LLStringOps::isAlnum((char)str[len]) ||
2775 LLStringOps::isPunct((char)str[len]) ||
2776 ' ' == str[len]) )
2777 {
2778 rv = FALSE;
2779 break;
2780 }
2781 }
2782 return rv;
2783}
2784
2785// static
2150BOOL LLLineEditor::prevalidateASCII(const LLWString &str) 2786BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
2151{ 2787{
2152 BOOL rv = TRUE; 2788 BOOL rv = TRUE;
@@ -2166,6 +2802,7 @@ BOOL LLLineEditor::evaluateFloat()
2166{ 2802{
2167 bool success = false; 2803 bool success = false;
2168 std::string expr = getText(); 2804 std::string expr = getText();
2805 LLStringUtil::toUpper(expr);
2169 2806
2170 // user deleted the contents, nothing to evaluate -- MC 2807 // user deleted the contents, nothing to evaluate -- MC
2171 if (expr.empty()) 2808 if (expr.empty())
@@ -2339,6 +2976,16 @@ LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
2339 { 2976 {
2340 line_editor->setCommitOnFocusLost(commit_on_focus_lost); 2977 line_editor->setCommitOnFocusLost(commit_on_focus_lost);
2341 } 2978 }
2979 BOOL spell_checking = FALSE;
2980 if (node->getAttributeBOOL("spell_check", spell_checking))
2981 {
2982 line_editor->setSpellCheckable(spell_checking);
2983 }
2984 BOOL allow_translate = TRUE;
2985 if (node->getAttributeBOOL("allow_translate", allow_translate))
2986 {
2987 line_editor->setAllowTranslate(allow_translate);
2988 }
2342 2989
2343 line_editor->setColorParameters(node); 2990 line_editor->setColorParameters(node);
2344 2991
diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h
index fc1b75f..b3e21ce 100644
--- a/linden/indra/llui/lllineeditor.h
+++ b/linden/indra/llui/lllineeditor.h
@@ -55,6 +55,7 @@
55class LLFontGL; 55class LLFontGL;
56class LLLineEditorRollback; 56class LLLineEditorRollback;
57class LLButton; 57class LLButton;
58class LLMenuGL;
58 59
59typedef BOOL (*LLLinePrevalidateFunc)(const LLWString &wstr); 60typedef BOOL (*LLLinePrevalidateFunc)(const LLWString &wstr);
60 61
@@ -78,6 +79,7 @@ public:
78 LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE, 79 LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE,
79 S32 border_thickness = 1); 80 S32 border_thickness = 1);
80 81
82
81 virtual ~LLLineEditor(); 83 virtual ~LLLineEditor();
82 84
83 virtual LLXMLNodePtr getXML(bool save_children = true) const; 85 virtual LLXMLNodePtr getXML(bool save_children = true) const;
@@ -89,17 +91,36 @@ public:
89 /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); 91 /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
90 /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); 92 /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
91 /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); 93 /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
94 /*virtual*/ BOOL handleHScrollWheel(S32 x, S32 y, S32 clicks);
92 /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask); 95 /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask);
93 /*virtual*/ BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask); 96 /*virtual*/ BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
97 /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
94 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask ); 98 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
95 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); 99 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
96 /*virtual*/ void onMouseCaptureLost(); 100 /*virtual*/ void onMouseCaptureLost();
97 101
98 // LLEditMenuHandler overrides 102 struct SpellMenuBind
103 {
104 LLLineEditor* origin;
105 void * menuItem;
106 std::string word;
107 S32 wordPositionStart;
108 S32 wordPositionEnd;
109 };
110
111 virtual void spellReplace(SpellMenuBind* spellData);
112 virtual void translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length);
113 virtual BOOL canTranslate() const;
114 virtual void insert(std::string what,S32 wher);
115
116 // LLEditMenuHandler overrides and menu set up methods.
117 void defineMenuCallbacks(LLMenuGL* menu);
99 virtual void cut(); 118 virtual void cut();
100 virtual BOOL canCut() const; 119 virtual BOOL canCut() const;
120
101 virtual void copy(); 121 virtual void copy();
102 virtual BOOL canCopy() const; 122 virtual BOOL canCopy() const;
123
103 virtual void paste(); 124 virtual void paste();
104 virtual BOOL canPaste() const; 125 virtual BOOL canPaste() const;
105 126
@@ -117,8 +138,28 @@ public:
117 virtual void deselect(); 138 virtual void deselect();
118 virtual BOOL canDeselect() const; 139 virtual BOOL canDeselect() const;
119 140
141 static BOOL context_enable_cut(void* data);
142 static void context_cut(void* data);
143 static BOOL context_enable_copy(void* data);
144 static void context_copy(void* data);
145 static BOOL context_enable_paste(void* data);
146 static void context_paste(void* data);
147 static BOOL context_enable_delete(void* data);
148 static void context_delete(void* data);
149 static BOOL context_enable_selectall(void* data);
150 static void context_selectall(void* data);
151 static BOOL context_enable_translate(void * data);
152 static void context_translate(void * data);
153 static void spell_correct(void* data);
154 static void spell_show(void* data);
155 static void spell_add(void* data);
156
157 void getMisspelledWordsPositions(std::vector<S32>& misspell_positions);
158
120 // view overrides 159 // view overrides
121 virtual void draw(); 160 virtual void draw();
161 void autoCorrectText();
162 void drawMisspelled(const LLRect& background);
122 virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE); 163 virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE);
123 virtual void onFocusReceived(); 164 virtual void onFocusReceived();
124 virtual void onFocusLost(); 165 virtual void onFocusLost();
@@ -133,6 +174,8 @@ public:
133 virtual void onCommit(); 174 virtual void onCommit();
134 virtual BOOL isDirty() const { return mText.getString() != mPrevText; } // Returns TRUE if user changed value at all 175 virtual BOOL isDirty() const { return mText.getString() != mPrevText; } // Returns TRUE if user changed value at all
135 virtual void resetDirty() { mPrevText = mText.getString(); } // Clear dirty state 176 virtual void resetDirty() { mPrevText = mText.getString(); } // Clear dirty state
177 virtual BOOL isSpellDirty() const { return mText.getString() != mPrevSpelledText; } // Returns TRUE if user changed value at all
178 virtual void resetSpellDirty() { mPrevSpelledText = mText.getString(); } // Clear dirty state
136 179
137 // assumes UTF8 text 180 // assumes UTF8 text
138 virtual void setValue(const LLSD& value ) { setText(value.asString()); } 181 virtual void setValue(const LLSD& value ) { setText(value.asString()); }
@@ -168,6 +211,8 @@ public:
168 void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; } 211 void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; }
169 void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; } 212 void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; }
170 void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; } 213 void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; }
214 void setSpellCheckable(BOOL b) { mSpellCheckable = b; }
215 void setAllowTranslate(BOOL b) { mAllowTranslate = b; }
171 216
172 const LLColor4& getFgColor() const { return mFgColor; } 217 const LLColor4& getFgColor() const { return mFgColor; }
173 const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor; } 218 const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor; }
@@ -184,6 +229,7 @@ public:
184 // get the cursor position of the beginning/end of the prev/next word in the text 229 // get the cursor position of the beginning/end of the prev/next word in the text
185 S32 prevWordPos(S32 cursorPos) const; 230 S32 prevWordPos(S32 cursorPos) const;
186 S32 nextWordPos(S32 cursorPos) const; 231 S32 nextWordPos(S32 cursorPos) const;
232 BOOL getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const;
187 233
188 BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); } 234 BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); }
189 void startSelection(); 235 void startSelection();
@@ -210,10 +256,11 @@ public:
210 static BOOL prevalidateAlphaNumSpace(const LLWString &str ); 256 static BOOL prevalidateAlphaNumSpace(const LLWString &str );
211 static BOOL prevalidatePrintableNotPipe(const LLWString &str); 257 static BOOL prevalidatePrintableNotPipe(const LLWString &str);
212 static BOOL prevalidatePrintableNoSpace(const LLWString &str); 258 static BOOL prevalidatePrintableNoSpace(const LLWString &str);
259 static BOOL prevalidatePrintableSpace(const LLWString &str);
213 static BOOL prevalidateASCII(const LLWString &str); 260 static BOOL prevalidateASCII(const LLWString &str);
214 261
215 static BOOL postvalidateFloat(const std::string &str); 262 static BOOL postvalidateFloat(const std::string &str);
216 263
217 BOOL evaluateFloat(); 264 BOOL evaluateFloat();
218 265
219 // line history support: 266 // line history support:
@@ -225,11 +272,12 @@ public:
225private: 272private:
226 // private helper methods 273 // private helper methods
227 274
228 void pasteHelper(bool is_primary); 275 void pasteHelper(bool is_primary);
229 276
230 void removeChar(); 277 void removeChar();
231 void addChar(const llwchar c); 278 void addChar(const llwchar c);
232 void setCursorAtLocalPos(S32 local_mouse_x); 279 void setCursorAtLocalPos(S32 local_mouse_x);
280 S32 calculateCursorFromMouse(S32 local_mouse_x) const;
233 S32 findPixelNearestPos(S32 cursor_offset = 0) const; 281 S32 findPixelNearestPos(S32 cursor_offset = 0) const;
234 void reportBadKeystroke(); 282 void reportBadKeystroke();
235 BOOL handleSpecialKey(KEY key, MASK mask); 283 BOOL handleSpecialKey(KEY key, MASK mask);
@@ -253,9 +301,20 @@ private:
253 virtual S32 getPreeditFontSize() const; 301 virtual S32 getPreeditFontSize() const;
254 302
255protected: 303protected:
304 LLHandle<LLView> mPopupMenuHandle;
256 LLUIString mText; // The string being edited. 305 LLUIString mText; // The string being edited.
257 std::string mPrevText; // Saved string for 'ESC' revert 306 std::string mPrevText; // Saved string for 'ESC' revert
258 LLUIString mLabel; // text label that is visible when no user text provided 307 LLUIString mLabel; // text label that is visible when no user text provided
308 std::string mPrevSpelledText; // saved string so we know whether to respell or not
309 std::vector<S32> mMisspellLocations; // where all the mispelled words are
310 S32 mStartSpellHere; // the position of the first char on the screen, stored so we know when to update
311 S32 mEndSpellHere; // the location of the last char on the screen
312 BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field
313 LLFrameTimer mSpellTimer;
314 //to keep track of what we have to remove before showing menu
315 std::vector<SpellMenuBind* > suggestionMenuItems;
316 S32 mLastContextMenuX;
317 BOOL mAllowTranslate; // set in xui as "allow_translate".
259 318
260 // line history support: 319 // line history support:
261 BOOL mHaveHistory; // flag for enabled line history 320 BOOL mHaveHistory; // flag for enabled line history
@@ -364,6 +423,8 @@ private:
364 BOOL mIsSelecting; 423 BOOL mIsSelecting;
365 S32 mSelectionStart; 424 S32 mSelectionStart;
366 S32 mSelectionEnd; 425 S32 mSelectionEnd;
426
427
367 }; // end class LLLineEditorRollback 428 }; // end class LLLineEditorRollback
368 429
369}; // end class LLLineEditor 430}; // end class LLLineEditor
@@ -410,4 +471,6 @@ private:
410 471
411}; 472};
412 473
474
475
413#endif // LL_LINEEDITOR_ 476#endif // LL_LINEEDITOR_
diff --git a/linden/indra/llui/llmenugl.cpp b/linden/indra/llui/llmenugl.cpp
index b70f98b..d5e1186 100644
--- a/linden/indra/llui/llmenugl.cpp
+++ b/linden/indra/llui/llmenugl.cpp
@@ -101,8 +101,8 @@ const U32 SEPARATOR_HEIGHT_PIXELS = 8;
101const S32 TEAROFF_SEPARATOR_HEIGHT_PIXELS = 10; 101const S32 TEAROFF_SEPARATOR_HEIGHT_PIXELS = 10;
102const S32 MENU_ITEM_PADDING = 4; 102const S32 MENU_ITEM_PADDING = 4;
103 103
104const std::string BOOLEAN_TRUE_PREFIX( "X" ); 104const std::string BOOLEAN_TRUE_PREFIX( "\xe2\x9c\x93" ); // U+2714 -- MC
105const std::string BRANCH_SUFFIX( ">" ); 105const std::string BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE
106const std::string ARROW_UP ("^^^^^^^"); 106const std::string ARROW_UP ("^^^^^^^");
107const std::string ARROW_DOWN("vvvvvvv"); 107const std::string ARROW_DOWN("vvvvvvv");
108 108
@@ -149,6 +149,18 @@ LLMenuItemGL::LLMenuItemGL( const std::string& name, const std::string& label, K
149 setLabel( label ); 149 setLabel( label );
150} 150}
151 151
152LLMenuItemGL::~LLMenuItemGL() {
153
154 // Delete all the entries in the mFutureCallbackRequests vector
155 for(std::vector<LLCallbackInformation*>::iterator iter= mFutureCallbackRequests.begin();
156 iter!=mFutureCallbackRequests.end();
157 ++iter) {
158 delete (*iter);
159 }
160
161}
162
163
152// virtual 164// virtual
153LLXMLNodePtr LLMenuItemGL::getXML(bool save_children) const 165LLXMLNodePtr LLMenuItemGL::getXML(bool save_children) const
154{ 166{
@@ -517,6 +529,18 @@ BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit&
517 return TRUE; 529 return TRUE;
518} 530}
519 531
532
533void LLMenuItemGL::addCallbackType(U8 theType,
534 const std::string& name,
535 const std::string& userdata) {
536
537 // Add the new callback information to the list of callbacks that are being tracked.
538 mFutureCallbackRequests.push_back(new LLCallbackInformation(theType,name,userdata));
539
540}
541
542
543
520//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 544//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
521// Class LLMenuItemSeparatorGL 545// Class LLMenuItemSeparatorGL
522// 546//
@@ -541,6 +565,12 @@ public:
541 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 565 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
542 566
543 virtual U32 getNominalHeight( void ) const { return SEPARATOR_HEIGHT_PIXELS; } 567 virtual U32 getNominalHeight( void ) const { return SEPARATOR_HEIGHT_PIXELS; }
568
569 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
570 const std::string& name,
571 void* user_data,
572 void *callback_fcn) { return FALSE; } ;
573
544}; 574};
545 575
546LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const std::string &name ) : 576LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const std::string &name ) :
@@ -726,6 +756,11 @@ public:
726 } 756 }
727 virtual void doIt( void ) {} 757 virtual void doIt( void ) {}
728 virtual void draw( void ) {} 758 virtual void draw( void ) {}
759 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
760 const std::string& name,
761 void* user_data,
762 void *callback_fcn) { return FALSE; } ;
763
729}; 764};
730 765
731 766
@@ -805,6 +840,8 @@ LLMenuItemCallGL::LLMenuItemCallGL(const std::string& name,
805 if(!enabled) setEnabled(FALSE); 840 if(!enabled) setEnabled(FALSE);
806} 841}
807 842
843
844
808void LLMenuItemCallGL::setEnabledControl(std::string enabled_control, LLView *context) 845void LLMenuItemCallGL::setEnabledControl(std::string enabled_control, LLView *context)
809{ 846{
810 // Register new listener 847 // Register new listener
@@ -921,6 +958,53 @@ BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask )
921 return LLMenuItemGL::handleAcceleratorKey(key, mask); 958 return LLMenuItemGL::handleAcceleratorKey(key, mask);
922} 959}
923 960
961
962
963// Method to add a callback function for the given type and name.
964BOOL LLMenuItemCallGL::setCtrlResponse(U8 llMenuItemCallType,
965 const std::string& name,
966 void* user_data,
967 void *callback_fcn) {
968
969 // Loop through all of the menu items and check to see which ones
970 // match the name and callback type given.
971 BOOL result = FALSE;
972 std::vector<LLCallbackInformation*>::iterator item_iter;
973 for (item_iter = mFutureCallbackRequests.begin();
974 item_iter != mFutureCallbackRequests.end();
975 ++item_iter)
976 {
977 if( ((*item_iter)->getTypeOfCallback()==llMenuItemCallType) &&
978 ((*item_iter)->getCallbackName()==name)) {
979
980 // Found a match. Set the user data and then determine what type it is.
981 setUserData(user_data);
982
983 if(llMenuItemCallType == LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK)
984 {
985 setMenuCallback((menu_callback)callback_fcn,user_data);
986 }
987
988 else if (llMenuItemCallType == LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE)
989 {
990 setEnabledCallback((enabled_callback)callback_fcn);
991 }
992
993 else if (llMenuItemCallType == LLCallbackInformation::LL_MENU_ITEM_CALL_GL_TRANSLATE) {
994 setName((*item_iter)->getCallbackUserData());
995 setMenuCallback((menu_callback)callback_fcn,user_data);
996 }
997
998 }
999 }
1000
1001
1002 return result;
1003
1004}
1005
1006
1007
924///============================================================================ 1008///============================================================================
925/// Class LLMenuItemCheckGL 1009/// Class LLMenuItemCheckGL
926///============================================================================ 1010///============================================================================
@@ -1379,6 +1463,17 @@ void LLMenuItemBranchGL::openMenu()
1379} 1463}
1380 1464
1381 1465
1466BOOL LLMenuItemBranchGL::setCtrlResponse(U8 llMenuItemCallType,
1467 const std::string& name,
1468 void* user_data,
1469 void *callback_fcn) {
1470
1471 // Get the menu branch and set the callback functions on all its children.
1472 return(getBranch()->setCtrlResponse(llMenuItemCallType,name,user_data,callback_fcn));
1473
1474}
1475
1476
1382//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1477//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1383// Class LLMenuItemBranchDownGL 1478// Class LLMenuItemBranchDownGL
1384// 1479//
@@ -1982,13 +2077,31 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
1982 2077
1983 LLSimpleListener* callback = parent->getListenerByName(callback_name); 2078 LLSimpleListener* callback = parent->getListenerByName(callback_name);
1984 2079
1985 if (!callback) 2080 if (callback)
1986 { 2081 {
1987 lldebugs << "Ignoring \"on_click\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; 2082 new_item->addListener(callback, "on_click", callback_data);
1988 continue; 2083 }
2084 else {
2085
2086 // A callback for this item has not yet been
2087 // specified. Add it to the list of options
2088 // that do not yet have callbacks.
2089 if (call_child->hasAttribute("translate"))
2090 {
2091 new_item->addCallbackType
2092 (LLCallbackInformation::LL_MENU_ITEM_CALL_GL_TRANSLATE,
2093 item_name,
2094 callback_data);
2095 }
2096
2097 else
2098 {
2099 new_item->addCallbackType
2100 (LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
2101 item_name,
2102 callback_data);
2103 }
1989 } 2104 }
1990
1991 new_item->addListener(callback, "on_click", callback_data);
1992 } 2105 }
1993 if (call_child->hasName("on_enable")) 2106 if (call_child->hasName("on_enable"))
1994 { 2107 {
@@ -2016,13 +2129,22 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
2016 2129
2017 LLSimpleListener* callback = parent->getListenerByName(callback_name); 2130 LLSimpleListener* callback = parent->getListenerByName(callback_name);
2018 2131
2019 if (!callback) 2132 if (callback)
2020 { 2133 {
2021 lldebugs << "Ignoring \"on_enable\" \"" << item_name << "\" because \"" << callback_name << "\" is not registered" << llendl; 2134 new_item->addListener(callback, "on_build", userdata);
2022 continue; 2135 } else {
2136
2137 // A callback for this item has not yet been
2138 // specified. Add it to the list of options
2139 // that do not yet have callbacks.
2140
2141 new_item->addCallbackType
2142 (LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
2143 item_name,
2144 callback_data);
2023 } 2145 }
2024 2146
2025 new_item->addListener(callback, "on_build", userdata); 2147
2026 } 2148 }
2027 else if (call_child->hasAttribute("control")) 2149 else if (call_child->hasAttribute("control"))
2028 { 2150 {
@@ -2188,7 +2310,7 @@ LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
2188 LLColor4 color(0,0,0,1); 2310 LLColor4 color(0,0,0,1);
2189 if (opaque && LLUICtrlFactory::getAttributeColor(node,"color", color)) 2311 if (opaque && LLUICtrlFactory::getAttributeColor(node,"color", color))
2190 { 2312 {
2191 menu->setBackgroundColor(color); 2313 menu->setBackgroundColor(color);
2192 } 2314 }
2193 2315
2194 BOOL create_jump_keys = FALSE; 2316 BOOL create_jump_keys = FALSE;
@@ -2582,6 +2704,31 @@ BOOL LLMenuGL::appendMenu( LLMenuGL* menu )
2582 return success; 2704 return success;
2583} 2705}
2584 2706
2707// Remove a menu item from this menu.
2708BOOL LLMenuGL::remove( LLMenuItemGL* item )
2709{
2710 if (mSpilloverMenu)
2711 {
2712 cleanupSpilloverBranch();
2713 }
2714
2715 item_list_t::iterator found_iter = std::find(mItems.begin(), mItems.end(), item);
2716 if (found_iter != mItems.end())
2717 {
2718 mItems.erase(found_iter);
2719 }
2720
2721 removeChild( item );
2722
2723 // We keep it around in case someone is pointing at it.
2724 // The caller can delete it if it's safe.
2725 // Note that getMenu() will still not work since its parent isn't a menu.
2726 sMenuContainer->addChild( item );
2727
2728 arrange();
2729 return TRUE;
2730}
2731
2585void LLMenuGL::setEnabledSubMenus(BOOL enable) 2732void LLMenuGL::setEnabledSubMenus(BOOL enable)
2586{ 2733{
2587 setEnabled(enable); 2734 setEnabled(enable);
@@ -2952,7 +3099,8 @@ void LLMenuGL::draw( void )
2952 3099
2953 if( mBgVisible ) 3100 if( mBgVisible )
2954 { 3101 {
2955 gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor ); 3102 gl_rect_2d( -1, getRect().getHeight()+2, getRect().getWidth()+2, -2, mBorderColor,FALSE);
3103 gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor );
2956 } 3104 }
2957 LLView::draw(); 3105 LLView::draw();
2958} 3106}
@@ -3008,6 +3156,41 @@ LLMenuGL* LLMenuGL::getChildMenuByName(const std::string& name, BOOL recurse) co
3008 return NULL; 3156 return NULL;
3009} 3157}
3010 3158
3159
3160void LLMenuGL::setBackgroundColor( const LLColor4& color ) {
3161
3162 mBackgroundColor = color;
3163 item_list_t::iterator item_iter;
3164 for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
3165 {
3166 if((*item_iter)->getType()=="menu")
3167 {
3168 LLMenuItemBranchGL *menuBranchItem = (LLMenuItemBranchGL*)(*item_iter);
3169 menuBranchItem->getBranch()->setBackgroundColor(color);
3170 }
3171 }
3172
3173
3174}
3175
3176
3177void LLMenuGL::setBorderColor( const LLColor4& color ) {
3178
3179 mBorderColor = color;
3180 item_list_t::iterator item_iter;
3181 for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
3182 {
3183 if((*item_iter)->getType()=="menu")
3184 {
3185 LLMenuItemBranchGL *menuBranchItem = (LLMenuItemBranchGL*)(*item_iter);
3186 menuBranchItem->getBranch()->setBorderColor(color);
3187 }
3188 }
3189
3190
3191}
3192
3193
3011BOOL LLMenuGL::clearHoverItem() 3194BOOL LLMenuGL::clearHoverItem()
3012{ 3195{
3013 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) 3196 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
@@ -3073,6 +3256,26 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
3073 menu->getParent()->sendChildToFront(menu); 3256 menu->getParent()->sendChildToFront(menu);
3074} 3257}
3075 3258
3259
3260BOOL LLMenuGL::setCtrlResponse(U8 llMenuItemCallType,
3261 const std::string& name,
3262 void* user_data,
3263 void *callback_fcn)
3264{
3265
3266 // Go through all of the children on this menu and set the callback function.
3267 BOOL result = FALSE;
3268 item_list_t::iterator item_iter;
3269 for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
3270 {
3271 result |= (*item_iter)->setCtrlResponse(llMenuItemCallType,name,user_data,callback_fcn);
3272 }
3273
3274 return result;
3275}
3276
3277
3278
3076//----------------------------------------------------------------------------- 3279//-----------------------------------------------------------------------------
3077// class LLPieMenuBranch 3280// class LLPieMenuBranch
3078// A branch to another pie menu 3281// A branch to another pie menu
@@ -3092,6 +3295,12 @@ public:
3092 3295
3093 LLPieMenu* getBranch() { return mBranch; } 3296 LLPieMenu* getBranch() { return mBranch; }
3094 3297
3298 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
3299 const std::string& name,
3300 void* user_data,
3301 void *callback_fcn) { return FALSE; } ;
3302
3303
3095protected: 3304protected:
3096 LLPieMenu* mBranch; 3305 LLPieMenu* mBranch;
3097}; 3306};
@@ -4556,3 +4765,16 @@ void LLTearOffMenu::onClose(bool app_quitting)
4556 destroy(); 4765 destroy();
4557} 4766}
4558 4767
4768
4769///============================================================================
4770/// Class LLCallbackInformation
4771///============================================================================
4772
4773LLCallbackInformation::LLCallbackInformation(U8 theType,
4774 const std::string& theName,
4775 const std::string& userData)
4776 : callbackName(theName),
4777 callbackUserData(userData)
4778{
4779 setTypeOfCallback(theType);
4780}
diff --git a/linden/indra/llui/llmenugl.h b/linden/indra/llui/llmenugl.h
index 26fc294..9a9d1b0 100644
--- a/linden/indra/llui/llmenugl.h
+++ b/linden/indra/llui/llmenugl.h
@@ -70,6 +70,57 @@ typedef BOOL (*check_callback)(void*);
70// contents. Put the contents of the label in the provided parameter. 70// contents. Put the contents of the label in the provided parameter.
71typedef void (*label_callback)(std::string&,void*); 71typedef void (*label_callback)(std::string&,void*);
72 72
73
74
75//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76// Class LLCallbackInformation
77//
78// The LLCallbackInformation class is used to keep track of callback
79// information for menus that might be requested at a future time.
80//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81
82class LLCallbackInformation
83{
84
85public :
86
87 // Constants used for keeping track of what type of callback is required.
88 static const U8 LL_MENU_ITEM_CALL_GL_NONE = 0;
89 static const U8 LL_MENU_ITEM_CALL_GL_ON_CLICK = 1;
90 static const U8 LL_MENU_ITEM_CALL_GL_ON_ENABLE = 2;
91 static const U8 LL_MENU_ITEM_CALL_GL_TRANSLATE = 3;
92
93
94 LLCallbackInformation(U8 theType=LLCallbackInformation::LL_MENU_ITEM_CALL_GL_NONE,
95 const std::string& theName = LLStringUtil::null,
96 const std::string& userData = LLStringUtil::null);
97 ~LLCallbackInformation() {};
98
99 void setTypeOfCallback(U8 theType) {typeOfCallback = theType; }
100 void setCallbackName(const std::string& name) {callbackName = name; }
101 void setCallbackUserData(const std::string& userdata) {callbackUserData = userdata; }
102
103 U8 getTypeOfCallback() {return(typeOfCallback); }
104 const std::string& getCallbackName() {return(callbackName); }
105 const std::string& getCallbackUserData() {return(callbackUserData); }
106
107 BOOL isTypeMatch(U8 type) { return(type == typeOfCallback);}
108 BOOL isNameMatch(const std::string& name) { return(name == callbackName);}
109
110protected:
111
112private:
113
114 U8 typeOfCallback;
115 std::string callbackName;
116 std::string callbackUserData;
117
118};
119
120
121
122
123
73//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 124//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74// Class LLMenuItemGL 125// Class LLMenuItemGL
75// 126//
@@ -79,6 +130,7 @@ typedef void (*label_callback)(std::string&,void*);
79class LLMenuItemGL : public LLView 130class LLMenuItemGL : public LLView
80{ 131{
81public: 132public:
133
82 // static functions to control the global color scheme. 134 // static functions to control the global color scheme.
83 static void setEnabledColor( const LLColor4& color ) { sEnabledColor = color; } 135 static void setEnabledColor( const LLColor4& color ) { sEnabledColor = color; }
84 static const LLColor4& getEnabledColor() { return sEnabledColor; } 136 static const LLColor4& getEnabledColor() { return sEnabledColor; }
@@ -90,7 +142,7 @@ public:
90 static const LLColor4& getHighlightFGColor() { return sHighlightForeground; } 142 static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }
91 143
92 LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE ); 144 LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE );
93 virtual ~LLMenuItemGL() {}; 145 virtual ~LLMenuItemGL();
94 146
95 virtual void setValue(const LLSD& value) { setLabel(value.asString()); } 147 virtual void setValue(const LLSD& value) { setLabel(value.asString()); }
96 148
@@ -174,6 +226,14 @@ public:
174 void setDrawTextDisabled(BOOL disabled) { mDrawTextDisabled = disabled; } 226 void setDrawTextDisabled(BOOL disabled) { mDrawTextDisabled = disabled; }
175 BOOL getDrawTextDisabled() const { return mDrawTextDisabled; } 227 BOOL getDrawTextDisabled() const { return mDrawTextDisabled; }
176 228
229 // functionality for adding callbacks after the menu is constucted
230 void addCallbackType(U8 theType,const std::string& name,const std::string& userdata);
231
232 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
233 const std::string& name,
234 void* user_data,
235 void *callback_fcn) = 0;
236
177protected: 237protected:
178 void setHover(BOOL hover) { mGotHover = hover; } 238 void setHover(BOOL hover) { mGotHover = hover; }
179 239
@@ -194,6 +254,11 @@ protected:
194 LLUIString mDrawBranchLabel; 254 LLUIString mDrawBranchLabel;
195 255
196 BOOL mHighlight; 256 BOOL mHighlight;
257
258 // variables used for tracking callback types that will be
259 // requested after the widget is in place.
260 std::vector<LLCallbackInformation*> mFutureCallbackRequests;
261
197private: 262private:
198 static LLColor4 sEnabledColor; 263 static LLColor4 sEnabledColor;
199 static LLColor4 sDisabledColor; 264 static LLColor4 sDisabledColor;
@@ -214,6 +279,7 @@ private:
214 BOOL mDrawTextDisabled; 279 BOOL mDrawTextDisabled;
215 280
216 KEY mJumpKey; 281 KEY mJumpKey;
282
217}; 283};
218 284
219 285
@@ -262,6 +328,7 @@ public:
262 KEY key = KEY_NONE, MASK mask = MASK_NONE, 328 KEY key = KEY_NONE, MASK mask = MASK_NONE,
263 BOOL enabled = TRUE, 329 BOOL enabled = TRUE,
264 on_disabled_callback on_disabled_c = NULL); 330 on_disabled_callback on_disabled_c = NULL);
331
265 virtual LLXMLNodePtr getXML(bool save_children = true) const; 332 virtual LLXMLNodePtr getXML(bool save_children = true) const;
266 333
267 virtual std::string getType() const { return "call"; } 334 virtual std::string getType() const { return "call"; }
@@ -288,6 +355,13 @@ public:
288 355
289 //virtual void draw(); 356 //virtual void draw();
290 357
358 // Functionality for tracking callback types for setting after widget is in place.
359 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
360 const std::string& name,
361 void* user_data,
362 void *callback_fcn);
363
364
291 365
292private: 366private:
293 menu_callback mCallback; 367 menu_callback mCallback;
@@ -382,6 +456,12 @@ public:
382 // LLView Functionality 456 // LLView Functionality
383 //virtual void draw( void ); 457 //virtual void draw( void );
384 458
459 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
460 const std::string& name,
461 void* user_data,
462 void *callback_fcn) { return FALSE; } ;
463
464
385private: 465private:
386 BOOL* mToggle; 466 BOOL* mToggle;
387}; 467};
@@ -434,14 +514,19 @@ public:
434 514
435 // background colors 515 // background colors
436 static void setDefaultBackgroundColor( const LLColor4& color ) { sDefaultBackgroundColor = color; } 516 static void setDefaultBackgroundColor( const LLColor4& color ) { sDefaultBackgroundColor = color; }
437 void setBackgroundColor( const LLColor4& color ) { mBackgroundColor = color; } 517 void setBackgroundColor( const LLColor4& color );
518 void setBorderColor( const LLColor4& color );
438 const LLColor4& getBackgroundColor() const { return mBackgroundColor; } 519 const LLColor4& getBackgroundColor() const { return mBackgroundColor; }
520 const LLColor4& getBorderColor() const { return mBorderColor; }
439 void setBackgroundVisible( BOOL b ) { mBgVisible = b; } 521 void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
440 void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>()); 522 void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>());
441 523
442 // Add the menu item to this menu. 524 // Add the menu item to this menu.
443 virtual BOOL append( LLMenuItemGL* item ); 525 virtual BOOL append( LLMenuItemGL* item );
444 526
527 // Remove a menu item from this menu.
528 virtual BOOL remove( LLMenuItemGL* item );
529
445 // *NOTE:Mani - appendNoArrange() should be removed when merging to skinning/viewer2.0 530 // *NOTE:Mani - appendNoArrange() should be removed when merging to skinning/viewer2.0
446 // Its added as a fix to a viewer 1.23 bug that has already been address by skinning work. 531 // Its added as a fix to a viewer 1.23 bug that has already been address by skinning work.
447 virtual BOOL appendNoArrange( LLMenuItemGL* item ); 532 virtual BOOL appendNoArrange( LLMenuItemGL* item );
@@ -522,6 +607,8 @@ public:
522 static BOOL getKeyboardMode() { return sKeyboardMode; } 607 static BOOL getKeyboardMode() { return sKeyboardMode; }
523 608
524 static class LLMenuHolderGL* sMenuContainer; 609 static class LLMenuHolderGL* sMenuContainer;
610
611 BOOL setCtrlResponse(U8 llMenuItemCallType,const std::string& name,void* user_data,void *callback_fcn);
525 612
526protected: 613protected:
527 void createSpilloverBranch(); 614 void createSpilloverBranch();
@@ -544,6 +631,7 @@ private:
544 static BOOL sKeyboardMode; 631 static BOOL sKeyboardMode;
545 632
546 LLColor4 mBackgroundColor; 633 LLColor4 mBackgroundColor;
634 LLColor4 mBorderColor;
547 BOOL mBgVisible; 635 BOOL mBgVisible;
548 LLMenuItemGL* mParentMenuItem; 636 LLMenuItemGL* mParentMenuItem;
549 LLUIString mLabel; 637 LLUIString mLabel;
@@ -620,6 +708,12 @@ public:
620 708
621 virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; 709 virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
622 710
711 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
712 const std::string& name,
713 void* user_data,
714 void *callback_fcn);
715
716
623private: 717private:
624 LLHandle<LLView> mBranch; 718 LLHandle<LLView> mBranch;
625}; // end class LLMenuItemBranchGL 719}; // end class LLMenuItemBranchGL
@@ -665,6 +759,12 @@ public:
665 void show(S32 x, S32 y, BOOL mouse_down); 759 void show(S32 x, S32 y, BOOL mouse_down);
666 void hide(BOOL item_selected); 760 void hide(BOOL item_selected);
667 761
762 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
763 const std::string& name,
764 void* user_data,
765 void *callback_fcn) { return FALSE; } ;
766
767
668private: 768private:
669 LLMenuItemGL *pieItemFromXY(S32 x, S32 y); 769 LLMenuItemGL *pieItemFromXY(S32 x, S32 y);
670 S32 pieItemIndexFromXY(S32 x, S32 y); 770 S32 pieItemIndexFromXY(S32 x, S32 y);
@@ -726,6 +826,12 @@ public:
726 826
727 void resetMenuTrigger() { mAltKeyTrigger = FALSE; } 827 void resetMenuTrigger() { mAltKeyTrigger = FALSE; }
728 828
829 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
830 const std::string& name,
831 void* user_data,
832 void *callback_fcn) { return FALSE; } ;
833
834
729private: 835private:
730 void checkMenuTrigger(); 836 void checkMenuTrigger();
731 837
@@ -811,6 +917,12 @@ public:
811 virtual void draw(void); 917 virtual void draw(void);
812 virtual U32 getNominalHeight() const; 918 virtual U32 getNominalHeight() const;
813 919
920 virtual BOOL setCtrlResponse(U8 llMenuItemCallType,
921 const std::string& name,
922 void* user_data,
923 void *callback_fcn) { return FALSE; } ;
924
925
814private: 926private:
815 LLHandle<LLFloater> mParentHandle; 927 LLHandle<LLFloater> mParentHandle;
816}; 928};
@@ -829,4 +941,5 @@ private:
829 LLEditMenuHandlerMgr() {}; 941 LLEditMenuHandlerMgr() {};
830}; 942};
831 943
944
832#endif // LL_LLMENUGL_H 945#endif // LL_LLMENUGL_H
diff --git a/linden/indra/llui/llmultisliderctrl.cpp b/linden/indra/llui/llmultisliderctrl.cpp
index b76c2f6..f9ec6d5 100644
--- a/linden/indra/llui/llmultisliderctrl.cpp
+++ b/linden/indra/llui/llmultisliderctrl.cpp
@@ -34,9 +34,6 @@
34 34
35#include "llmultisliderctrl.h" 35#include "llmultisliderctrl.h"
36 36
37#include "audioengine.h"
38#include "sound_ids.h"
39
40#include "llmath.h" 37#include "llmath.h"
41#include "llfontgl.h" 38#include "llfontgl.h"
42#include "llgl.h" 39#include "llgl.h"
diff --git a/linden/indra/llui/llnotifications.cpp b/linden/indra/llui/llnotifications.cpp
index 2459110..77f2ff7 100644
--- a/linden/indra/llui/llnotifications.cpp
+++ b/linden/indra/llui/llnotifications.cpp
@@ -40,7 +40,7 @@
40#include <algorithm> 40#include <algorithm>
41#include <boost/regex.hpp> 41#include <boost/regex.hpp>
42 42
43#include "../newview/hippoGridManager.h" 43#include "../newview/hippogridmanager.h"
44 44
45 45
46const std::string NOTIFICATION_PERSIST_VERSION = "0.93"; 46const std::string NOTIFICATION_PERSIST_VERSION = "0.93";
@@ -1190,13 +1190,13 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
1190 if (found != replacements.end()) 1190 if (found != replacements.end())
1191 { 1191 {
1192 replacement = found->second; 1192 replacement = found->second;
1193 //llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl; 1193 //llinfos << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << llendl;
1194 1194
1195 it->second->setValue(replacement); 1195 it->second->setValue(replacement);
1196 } 1196 }
1197 else 1197 else
1198 { 1198 {
1199 llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl; 1199 llwarns << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << llendl;
1200 } 1200 }
1201 } 1201 }
1202 } 1202 }
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp
index 709342b..07e78ed 100644
--- a/linden/indra/llui/llpanel.cpp
+++ b/linden/indra/llui/llpanel.cpp
@@ -203,6 +203,12 @@ void LLPanel::draw()
203 LLView::draw(); 203 LLView::draw();
204} 204}
205 205
206/*virtual*/
207void LLPanel::setAlpha(F32 alpha)
208{
209 mBgColorOpaque.setAlpha(alpha);
210}
211
206void LLPanel::updateDefaultBtn() 212void LLPanel::updateDefaultBtn()
207{ 213{
208 // This method does not call LLView::draw() so callers will need 214 // This method does not call LLView::draw() so callers will need
@@ -213,8 +219,7 @@ void LLPanel::updateDefaultBtn()
213 { 219 {
214 if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled()) 220 if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
215 { 221 {
216 LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); 222 LLButton* buttonp = dynamic_cast<LLButton*>(gFocusMgr.getKeyboardFocus());
217 LLButton* buttonp = dynamic_cast<LLButton*>(focus_ctrl);
218 BOOL focus_is_child_button = buttonp && buttonp->getCommitOnReturn(); 223 BOOL focus_is_child_button = buttonp && buttonp->getCommitOnReturn();
219 // only enable default button when current focus is not a return-capturing button 224 // only enable default button when current focus is not a return-capturing button
220 mDefaultBtn->setBorderEnabled(!focus_is_child_button); 225 mDefaultBtn->setBorderEnabled(!focus_is_child_button);
@@ -276,7 +281,7 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
276{ 281{
277 BOOL handled = FALSE; 282 BOOL handled = FALSE;
278 283
279 LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); 284 LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
280 285
281 // handle user hitting ESC to defocus 286 // handle user hitting ESC to defocus
282 if (key == KEY_ESCAPE) 287 if (key == KEY_ESCAPE)
@@ -800,6 +805,14 @@ void LLPanel::childSetColor(const std::string& id, const LLColor4& color)
800 child->setColor(color); 805 child->setColor(color);
801 } 806 }
802} 807}
808void LLPanel::childSetAlpha(const std::string& id, F32 alpha)
809{
810 LLUICtrl* child = getChild<LLUICtrl>(id, true);
811 if (child)
812 {
813 child->setAlpha(alpha);
814 }
815}
803 816
804LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const 817LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const
805{ 818{
@@ -1158,7 +1171,7 @@ void LLLayoutStack::draw()
1158 1171
1159 LLLocalClipRect clip(clip_rect); 1172 LLLocalClipRect clip(clip_rect);
1160 // only force drawing invisible children if visible amount is non-zero 1173 // only force drawing invisible children if visible amount is non-zero
1161 drawChild(panelp, 0, 0, !clip_rect.isNull()); 1174 drawChild(panelp, 0, 0, !clip_rect.isEmpty());
1162 } 1175 }
1163} 1176}
1164 1177
diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h
index 756d02e..378b357 100644
--- a/linden/indra/llui/llpanel.h
+++ b/linden/indra/llui/llpanel.h
@@ -82,6 +82,8 @@ public:
82 82
83 // From LLFocusableElement 83 // From LLFocusableElement
84 /*virtual*/ void setFocus( BOOL b ); 84 /*virtual*/ void setFocus( BOOL b );
85 virtual void setAlpha(F32 alpha);
86
85 87
86 // New virtuals 88 // New virtuals
87 virtual void refresh(); // called in setFocus() 89 virtual void refresh(); // called in setFocus()
@@ -174,6 +176,7 @@ public:
174 void childSetUserData(const std::string& id, void* userdata); 176 void childSetUserData(const std::string& id, void* userdata);
175 177
176 void childSetColor(const std::string& id, const LLColor4& color); 178 void childSetColor(const std::string& id, const LLColor4& color);
179 void childSetAlpha(const std::string& id, F32 alpha);
177 180
178 LLCtrlSelectionInterface* childGetSelectionInterface(const std::string& id) const; 181 LLCtrlSelectionInterface* childGetSelectionInterface(const std::string& id) const;
179 LLCtrlListInterface* childGetListInterface(const std::string& id) const; 182 LLCtrlListInterface* childGetListInterface(const std::string& id) const;
diff --git a/linden/indra/llui/llresmgr.cpp b/linden/indra/llui/llresmgr.cpp
index 32d3d1f..22610ca 100644
--- a/linden/indra/llui/llresmgr.cpp
+++ b/linden/indra/llui/llresmgr.cpp
@@ -58,7 +58,8 @@ LLResMgr::LLResMgr()
58 mUSAFonts[ LLFONT_OCRA ] = LLFontGL::getFontMonospace(); 58 mUSAFonts[ LLFONT_OCRA ] = LLFontGL::getFontMonospace();
59 mUSAFonts[ LLFONT_SANSSERIF ] = LLFontGL::getFontSansSerif(); 59 mUSAFonts[ LLFONT_SANSSERIF ] = LLFontGL::getFontSansSerif();
60 mUSAFonts[ LLFONT_SANSSERIF_SMALL ] = LLFontGL::getFontSansSerifSmall(); 60 mUSAFonts[ LLFONT_SANSSERIF_SMALL ] = LLFontGL::getFontSansSerifSmall();
61 mUSAFonts[ LLFONT_SANSSERIF_BIG ] = LLFontGL::getFontSansSerifBig(); 61 mUSAFonts[ LLFONT_SANSSERIF_BIGGER ]= LLFontGL::getFontSansSerifBigger();
62 mUSAFonts[ LLFONT_SANSSERIF_LARGE ] = LLFontGL::getFontSansSerifLarge();
62 mUSAFonts[ LLFONT_SMALL ] = LLFontGL::getFontMonospace(); 63 mUSAFonts[ LLFONT_SMALL ] = LLFontGL::getFontMonospace();
63/* 64/*
64 // USA Strings 65 // USA Strings
@@ -421,7 +422,8 @@ const std::string LLFONT_ID_NAMES[] =
421 std::string("OCRA"), 422 std::string("OCRA"),
422 std::string("SANSSERIF"), 423 std::string("SANSSERIF"),
423 std::string("SANSSERIF_SMALL"), 424 std::string("SANSSERIF_SMALL"),
424 std::string("SANSSERIF_BIG"), 425 std::string("SANSSERIF_BIGGER"),
426 std::string("SANSSERIF_LARGE"),
425 std::string("SMALL"), 427 std::string("SMALL"),
426}; 428};
427 429
diff --git a/linden/indra/llui/llresmgr.h b/linden/indra/llui/llresmgr.h
index d54505c..3008244 100644
--- a/linden/indra/llui/llresmgr.h
+++ b/linden/indra/llui/llresmgr.h
@@ -51,7 +51,8 @@ enum LLFONT_ID
51 LLFONT_OCRA, 51 LLFONT_OCRA,
52 LLFONT_SANSSERIF, 52 LLFONT_SANSSERIF,
53 LLFONT_SANSSERIF_SMALL, 53 LLFONT_SANSSERIF_SMALL,
54 LLFONT_SANSSERIF_BIG, 54 LLFONT_SANSSERIF_BIGGER,
55 LLFONT_SANSSERIF_LARGE,
55 LLFONT_SMALL, 56 LLFONT_SMALL,
56 LLFONT_COUNT // Number of values in this enum. Keep at end. 57 LLFONT_COUNT // Number of values in this enum. Keep at end.
57}; 58};
diff --git a/linden/indra/llui/llscrollbar.cpp b/linden/indra/llui/llscrollbar.cpp
index 65086d8..11e6239 100644
--- a/linden/indra/llui/llscrollbar.cpp
+++ b/linden/indra/llui/llscrollbar.cpp
@@ -426,6 +426,11 @@ BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
426 changeLine( clicks * mStepSize, TRUE ); 426 changeLine( clicks * mStepSize, TRUE );
427 return TRUE; 427 return TRUE;
428} 428}
429BOOL LLScrollbar::handleHScrollWheel(S32 x, S32 y, S32 clicks)
430{
431 changeLine( clicks * mStepSize, TRUE );
432 return TRUE;
433}
429 434
430BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, 435BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
431 EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string &tooltip_msg) 436 EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string &tooltip_msg)
diff --git a/linden/indra/llui/llscrollbar.h b/linden/indra/llui/llscrollbar.h
index 0bbf866..6969662 100644
--- a/linden/indra/llui/llscrollbar.h
+++ b/linden/indra/llui/llscrollbar.h
@@ -69,6 +69,7 @@ public:
69 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); 69 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
70 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 70 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
71 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 71 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
72 virtual BOOL handleHScrollWheel(S32 x, S32 y, S32 clicks);
72 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, 73 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
73 EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string &tooltip_msg); 74 EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string &tooltip_msg);
74 75
diff --git a/linden/indra/llui/llscrollcontainer.cpp b/linden/indra/llui/llscrollcontainer.cpp
index 6f037e2..8737a70 100644
--- a/linden/indra/llui/llscrollcontainer.cpp
+++ b/linden/indra/llui/llscrollcontainer.cpp
@@ -239,6 +239,23 @@ BOOL LLScrollableContainerView::handleScrollWheel( S32 x, S32 y, S32 clicks )
239 return TRUE; 239 return TRUE;
240} 240}
241 241
242BOOL LLScrollableContainerView::handleHScrollWheel( S32 x, S32 y, S32 clicks )
243{
244 for( S32 i = SCROLLBAR_COUNT - 1; i >= 0; i++ )
245 {
246 // Note: tries horizontal and then vertical
247
248 // Pretend the mouse is over the scrollbar
249 if( mScrollbar[i]->handleScrollWheel( 0, 0, clicks ) )
250 {
251 return TRUE;
252 }
253 }
254
255 // Eat scroll wheel event (to avoid scrolling nested containers?)
256 return TRUE;
257}
258
242BOOL LLScrollableContainerView::needsToScroll(S32 x, S32 y, LLScrollableContainerView::SCROLL_ORIENTATION axis) const 259BOOL LLScrollableContainerView::needsToScroll(S32 x, S32 y, LLScrollableContainerView::SCROLL_ORIENTATION axis) const
243{ 260{
244 if(mScrollbar[axis]->getVisible()) 261 if(mScrollbar[axis]->getVisible())
diff --git a/linden/indra/llui/llscrollcontainer.h b/linden/indra/llui/llscrollcontainer.h
index 70fc908..c18a0db 100644
--- a/linden/indra/llui/llscrollcontainer.h
+++ b/linden/indra/llui/llscrollcontainer.h
@@ -91,6 +91,7 @@ public:
91 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); 91 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
92 virtual BOOL handleKeyHere(KEY key, MASK mask); 92 virtual BOOL handleKeyHere(KEY key, MASK mask);
93 virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); 93 virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
94 virtual BOOL handleHScrollWheel( S32 x, S32 y, S32 clicks );
94 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, 95 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
95 EDragAndDropType cargo_type, 96 EDragAndDropType cargo_type,
96 void* cargo_data, 97 void* cargo_data,
diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp
index 3c2293f..1b93abf 100644
--- a/linden/indra/llui/llscrolllistctrl.cpp
+++ b/linden/indra/llui/llscrolllistctrl.cpp
@@ -103,6 +103,10 @@ struct SortScrollListItem
103LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width) 103LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width)
104 : LLScrollListCell(width), 104 : LLScrollListCell(width),
105 mIcon(icon), 105 mIcon(icon),
106 // <edit>
107 mCallback(NULL),
108 mUserData(NULL),
109 // </edit>
106 mColor(LLColor4::white) 110 mColor(LLColor4::white)
107{ 111{
108} 112}
@@ -145,6 +149,19 @@ void LLScrollListIcon::setValue(const LLSD& value)
145 } 149 }
146} 150}
147 151
152// <edit>
153void LLScrollListIcon::setClickCallback(BOOL (*callback)(void*), void* user_data)
154{
155 mCallback = callback;
156 mUserData = user_data;
157}
158
159BOOL LLScrollListIcon::handleClick()
160{
161 if(mCallback) return mCallback(mUserData);
162 return FALSE;
163}
164// </edit>
148 165
149void LLScrollListIcon::setColor(const LLColor4& color) 166void LLScrollListIcon::setColor(const LLColor4& color)
150{ 167{
@@ -553,7 +570,7 @@ void LLScrollListItemSeparator::draw(const LLRect& rect, const LLColor4& fg_colo
553// LLScrollListCtrl 570// LLScrollListCtrl
554//--------------------------------------------------------------------------- 571//---------------------------------------------------------------------------
555 572
556LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, 573LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, const LLFontGL* font,
557 void (*commit_callback)(LLUICtrl* ctrl, void* userdata), 574 void (*commit_callback)(LLUICtrl* ctrl, void* userdata),
558 void* callback_user_data, 575 void* callback_user_data,
559 BOOL allow_multiple_selection, 576 BOOL allow_multiple_selection,
@@ -588,6 +605,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
588 mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ), 605 mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ),
589 mBorderThickness( 2 ), 606 mBorderThickness( 2 ),
590 mOnDoubleClickCallback( NULL ), 607 mOnDoubleClickCallback( NULL ),
608 mOnRightMouseDownCallback( NULL ),
591 mOnMaximumSelectCallback( NULL ), 609 mOnMaximumSelectCallback( NULL ),
592 mOnSortChangedCallback( NULL ), 610 mOnSortChangedCallback( NULL ),
593 mHighlightedItem(-1), 611 mHighlightedItem(-1),
@@ -601,6 +619,15 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
601 mOriginalSelection(-1), 619 mOriginalSelection(-1),
602 mDrewSelected(FALSE) 620 mDrewSelected(FALSE)
603{ 621{
622 if (font)
623 {
624 mGLFont = font;
625 }
626 else
627 {
628 mGLFont = LLFontGL::getFontSansSerifSmall();
629 }
630
604 mItemListRect.setOriginAndSize( 631 mItemListRect.setOriginAndSize(
605 mBorderThickness, 632 mBorderThickness,
606 mBorderThickness, 633 mBorderThickness,
@@ -969,14 +996,14 @@ void LLScrollListCtrl::calcColumnWidths()
969 column->setWidth(new_width); 996 column->setWidth(new_width);
970 997
971 // update max content width for this column, by looking at all items 998 // update max content width for this column, by looking at all items
972 column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; 999 column->mMaxContentWidth = column->mHeader ? mGLFont->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
973 item_list::iterator iter; 1000 item_list::iterator iter;
974 for (iter = mItemList.begin(); iter != mItemList.end(); iter++) 1001 for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
975 { 1002 {
976 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); 1003 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
977 if (!cellp) continue; 1004 if (!cellp) continue;
978 1005
979 column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); 1006 column->mMaxContentWidth = llmax(mGLFont->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
980 } 1007 }
981 1008
982 max_item_width += column->mMaxContentWidth; 1009 max_item_width += column->mMaxContentWidth;
@@ -1624,7 +1651,7 @@ LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_te
1624 if (getItemCount() < mMaxItemCount) 1651 if (getItemCount() < mMaxItemCount)
1625 { 1652 {
1626 item = new LLScrollListItem( enabled, NULL, id ); 1653 item = new LLScrollListItem( enabled, NULL, id );
1627 item->addColumn(item_text, LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL), column_width); 1654 item->addColumn(item_text, mGLFont, column_width);
1628 addItem( item, pos ); 1655 addItem( item, pos );
1629 } 1656 }
1630 return item; 1657 return item;
@@ -2065,6 +2092,27 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
2065 return TRUE; 2092 return TRUE;
2066} 2093}
2067 2094
2095BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
2096{
2097 //BOOL handled = FALSE;
2098 BOOL handled = handleClick(x, y, mask);
2099
2100 if (!handled)
2101 {
2102 // Offer the click to the children, even if we aren't enabled
2103 // so the scroll bars will work.
2104 if (NULL == LLView::childrenHandleRightMouseDown(x, y, mask))
2105 {
2106 if( mCanSelect && mOnRightMouseDownCallback )
2107 {
2108 mOnRightMouseDownCallback( x, y, mCallbackUserData );
2109 }
2110 }
2111 }
2112
2113 return TRUE;
2114}
2115
2068BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) 2116BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask)
2069{ 2117{
2070 // which row was clicked on? 2118 // which row was clicked on?
@@ -2861,6 +2909,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2861 LLScrollListCtrl* scroll_list = new LLScrollListCtrl( 2909 LLScrollListCtrl* scroll_list = new LLScrollListCtrl(
2862 name, 2910 name,
2863 rect, 2911 rect,
2912 NULL,
2864 callback, 2913 callback,
2865 NULL, 2914 NULL,
2866 multi_select, 2915 multi_select,
@@ -3335,7 +3384,11 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
3335 const LLFontGL *font = LLResMgr::getInstance()->getRes(fontname); 3384 const LLFontGL *font = LLResMgr::getInstance()->getRes(fontname);
3336 if (!font) 3385 if (!font)
3337 { 3386 {
3338 font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); 3387 font = mGLFont;
3388 if (!font)
3389 {
3390 font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
3391 }
3339 } 3392 }
3340 U8 font_style = LLFontGL::getStyleFromString(fontstyle); 3393 U8 font_style = LLFontGL::getStyleFromString(fontstyle);
3341 3394
@@ -3407,7 +3460,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
3407 if (new_item->getColumn(column_idx) == NULL) 3460 if (new_item->getColumn(column_idx) == NULL)
3408 { 3461 {
3409 LLScrollListColumn* column_ptr = &column_it->second; 3462 LLScrollListColumn* column_ptr = &column_it->second;
3410 new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->getWidth(), LLFontGL::NORMAL)); 3463 new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, mGLFont, column_ptr->getWidth(), LLFontGL::NORMAL));
3411 } 3464 }
3412 } 3465 }
3413 3466
@@ -3427,7 +3480,7 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E
3427 3480
3428 LLScrollListItem *new_item = new LLScrollListItem(entry_id); 3481 LLScrollListItem *new_item = new LLScrollListItem(entry_id);
3429 3482
3430 const LLFontGL *font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); 3483 const LLFontGL *font = mGLFont;
3431 3484
3432 new_item->addColumn(value, font, getRect().getWidth()); 3485 new_item->addColumn(value, font, getRect().getWidth());
3433 3486
@@ -3614,6 +3667,22 @@ BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask)
3614 return TRUE; 3667 return TRUE;
3615} 3668}
3616 3669
3670BOOL LLColumnHeader::handleRightMouseDown(S32 x, S32 y, MASK mask)
3671{
3672 if (canResize() && mResizeBar->getRect().pointInRect(x, y))
3673 {
3674 // reshape column to max content width
3675 LLRect column_rect = getRect();
3676 column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth;
3677 userSetShape(column_rect);
3678 }
3679 else
3680 {
3681 onClick(this);
3682 }
3683 return TRUE;
3684}
3685
3617void LLColumnHeader::setImage(const std::string &image_name) 3686void LLColumnHeader::setImage(const std::string &image_name)
3618{ 3687{
3619 if (mButton) 3688 if (mButton)
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h
index 516e4f1..1b7105f 100644
--- a/linden/indra/llui/llscrolllistctrl.h
+++ b/linden/indra/llui/llscrolllistctrl.h
@@ -163,10 +163,18 @@ public:
163 virtual void setColor(const LLColor4&); 163 virtual void setColor(const LLColor4&);
164 virtual BOOL isText()const { return FALSE; } 164 virtual BOOL isText()const { return FALSE; }
165 virtual void setValue(const LLSD& value); 165 virtual void setValue(const LLSD& value);
166 // <edit>
167 void setClickCallback(BOOL (*callback)(void*), void* user_data);
168 virtual BOOL handleClick();
169 // </edit>
166 170
167private: 171private:
168 LLUIImagePtr mIcon; 172 LLUIImagePtr mIcon;
169 LLColor4 mColor; 173 LLColor4 mColor;
174 // <edit>
175 BOOL (*mCallback)(void*);
176 void* mUserData;
177 // </edit>
170}; 178};
171 179
172/* 180/*
@@ -233,6 +241,7 @@ public:
233 241
234 /*virtual*/ void draw(); 242 /*virtual*/ void draw();
235 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); 243 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
244 /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
236 245
237 /*virtual*/ void showList(); 246 /*virtual*/ void showList();
238 /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding); 247 /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding);
@@ -344,6 +353,7 @@ public:
344 LLScrollListCtrl( 353 LLScrollListCtrl(
345 const std::string& name, 354 const std::string& name,
346 const LLRect& rect, 355 const LLRect& rect,
356 const LLFontGL* font,
347 void (*commit_callback)(LLUICtrl*, void*), 357 void (*commit_callback)(LLUICtrl*, void*),
348 void* callback_userdata, 358 void* callback_userdata,
349 BOOL allow_multiple_selection, 359 BOOL allow_multiple_selection,
@@ -423,6 +433,7 @@ public:
423 433
424 void highlightNthItem( S32 index ); 434 void highlightNthItem( S32 index );
425 void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; } 435 void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; }
436 void setRightMouseDownCallback( void (*cb)(S32 x, S32 y, void*) ) { mOnRightMouseDownCallback = cb; }
426 void setMaximumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; } 437 void setMaximumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; }
427 void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; } 438 void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; }
428 439
@@ -493,6 +504,9 @@ public:
493 504
494 virtual S32 getScrollPos() const; 505 virtual S32 getScrollPos() const;
495 virtual void setScrollPos( S32 pos ); 506 virtual void setScrollPos( S32 pos );
507 // <edit>
508 S32 getPageLines() { return mPageLines; }
509 // </edit>
496 S32 getSearchColumn(); 510 S32 getSearchColumn();
497 void setSearchColumn(S32 column) { mSearchColumn = column; } 511 void setSearchColumn(S32 column) { mSearchColumn = column; }
498 S32 getColumnIndexFromOffset(S32 x); 512 S32 getColumnIndexFromOffset(S32 x);
@@ -506,6 +520,7 @@ public:
506 /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); 520 /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
507 /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); 521 /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
508 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); 522 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
523 /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
509 /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); 524 /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
510 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); 525 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
511 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); 526 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
@@ -649,6 +664,7 @@ private:
649 664
650 S32 mBorderThickness; 665 S32 mBorderThickness;
651 void (*mOnDoubleClickCallback)(void* userdata); 666 void (*mOnDoubleClickCallback)(void* userdata);
667 void (*mOnRightMouseDownCallback)(S32 x, S32 y, void* userdata);
652 void (*mOnMaximumSelectCallback)(void* userdata ); 668 void (*mOnMaximumSelectCallback)(void* userdata );
653 void (*mOnSortChangedCallback)(void* userdata); 669 void (*mOnSortChangedCallback)(void* userdata);
654 670
@@ -679,6 +695,8 @@ private:
679 695
680 // HACK: Did we draw one selected item this frame? 696 // HACK: Did we draw one selected item this frame?
681 BOOL mDrewSelected; 697 BOOL mDrewSelected;
698
699 const LLFontGL* mGLFont;
682}; // end class LLScrollListCtrl 700}; // end class LLScrollListCtrl
683 701
684 702
diff --git a/linden/indra/llui/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp
index 8a13ed4..51d43fb 100644
--- a/linden/indra/llui/llsliderctrl.cpp
+++ b/linden/indra/llui/llsliderctrl.cpp
@@ -34,8 +34,6 @@
34 34
35#include "llsliderctrl.h" 35#include "llsliderctrl.h"
36 36
37#include "audioengine.h"
38
39#include "llmath.h" 37#include "llmath.h"
40#include "llfontgl.h" 38#include "llfontgl.h"
41#include "llgl.h" 39#include "llgl.h"
diff --git a/linden/indra/llui/llspinctrl.cpp b/linden/indra/llui/llspinctrl.cpp
index 7eccaca..e66b20e 100644
--- a/linden/indra/llui/llspinctrl.cpp
+++ b/linden/indra/llui/llspinctrl.cpp
@@ -45,7 +45,6 @@
45#include "lltextbox.h" 45#include "lltextbox.h"
46#include "llkeyboard.h" 46#include "llkeyboard.h"
47#include "llmath.h" 47#include "llmath.h"
48#include "audioengine.h"
49#include "llcontrol.h" 48#include "llcontrol.h"
50#include "llfocusmgr.h" 49#include "llfocusmgr.h"
51#include "llresmgr.h" 50#include "llresmgr.h"
diff --git a/linden/indra/llui/llstyle.cpp b/linden/indra/llui/llstyle.cpp
index a716cbb..61a025e 100644
--- a/linden/indra/llui/llstyle.cpp
+++ b/linden/indra/llui/llstyle.cpp
@@ -128,9 +128,13 @@ void LLStyle::setFontName(const std::string& fontname)
128 { 128 {
129 mFontID = LLFONT_SMALL; 129 mFontID = LLFONT_SMALL;
130 } 130 }
131 else if ((fontname_lc == "sansserifbig")) 131 else if ((fontname_lc == "sansserifbigger"))
132 { 132 {
133 mFontID = LLFONT_SANSSERIF_BIG; 133 mFontID = LLFONT_SANSSERIF_BIGGER;
134 }
135 else if ((fontname_lc == "sansserifhuge"))
136 {
137 mFontID = LLFONT_SANSSERIF_LARGE;
134 } 138 }
135 else if (fontname_lc == "small") 139 else if (fontname_lc == "small")
136 { 140 {
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index 2d46943..5bddcbc 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -36,7 +36,6 @@
36 36
37#include "lltexteditor.h" 37#include "lltexteditor.h"
38 38
39#include "llerror.h"
40#include "llfontgl.h" 39#include "llfontgl.h"
41#include "llrender.h" 40#include "llrender.h"
42#include "llui.h" 41#include "llui.h"
@@ -46,7 +45,6 @@
46#include "lltimer.h" 45#include "lltimer.h"
47#include "llmath.h" 46#include "llmath.h"
48 47
49#include "audioengine.h"
50#include "llclipboard.h" 48#include "llclipboard.h"
51#include "llscrollbar.h" 49#include "llscrollbar.h"
52#include "llstl.h" 50#include "llstl.h"
@@ -59,8 +57,15 @@
59#include "llimagegl.h" 57#include "llimagegl.h"
60#include "llwindow.h" 58#include "llwindow.h"
61#include "lltextparser.h" 59#include "lltextparser.h"
60#include "lldir.h"
62#include <queue> 61#include <queue>
63#include <stdexcept> 62
63#include "llmenugl.h"
64#include <boost/regex.hpp>
65#include "../newview/lgghunspell_wrapper.h"
66#include "../newview/lltranslate.h"
67#include "../newview/llviewercontrol.h"
68#include "../newview/lggautocorrect.h"
64 69
65// 70//
66// Globals 71// Globals
@@ -96,7 +101,38 @@ LLColor4 LLTextEditor::mLinkColor = LLColor4::blue;
96void (* LLTextEditor::mURLcallback)(const std::string&) = NULL; 101void (* LLTextEditor::mURLcallback)(const std::string&) = NULL;
97bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; 102bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
98bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL; 103bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
104///////////////////////////////////////////////////////////////////
105
106class TextChatTranslationReceiver : public LLTranslate::TranslationReceiver
107{
108public :
109 TextChatTranslationReceiver(const std::string &toLang, LLTextEditor* line, const S32 start, const S32 len):
110 LLTranslate::TranslationReceiver("", toLang),
111 m_line(line),
112 m_position(start),
113 m_origLength(len)
114 {
115 }
99 116
117 static boost::intrusive_ptr<TextChatTranslationReceiver> build(const std::string &toLang,LLTextEditor* line, const S32 start, const S32 len)
118 {
119 return boost::intrusive_ptr<TextChatTranslationReceiver>(new TextChatTranslationReceiver(toLang, line, start, len));
120 }
121
122protected:
123 void handleResponse(const std::string &translation, const std::string &detectedLanguage)
124 {
125 m_line->translationReplace(translation, m_position, m_origLength);
126 }
127 void handleFailure()
128 {
129 LLTranslate::TranslationReceiver::handleFailure();
130 }
131private:
132 LLTextEditor* m_line;
133 S32 m_position;
134 S32 m_origLength;
135};
100 136
101/////////////////////////////////////////////////////////////////// 137///////////////////////////////////////////////////////////////////
102 138
@@ -257,6 +293,7 @@ LLTextEditor::LLTextEditor(
257 LLUICtrl( name, rect, TRUE, NULL, NULL, FOLLOWS_TOP | FOLLOWS_LEFT ), 293 LLUICtrl( name, rect, TRUE, NULL, NULL, FOLLOWS_TOP | FOLLOWS_LEFT ),
258 mTextIsUpToDate(TRUE), 294 mTextIsUpToDate(TRUE),
259 mMaxTextByteLength( max_length ), 295 mMaxTextByteLength( max_length ),
296 mPopupMenuHandle(),
260 mBaseDocIsPristine(TRUE), 297 mBaseDocIsPristine(TRUE),
261 mPristineCmd( NULL ), 298 mPristineCmd( NULL ),
262 mLastCmd( NULL ), 299 mLastCmd( NULL ),
@@ -289,8 +326,12 @@ LLTextEditor::LLTextEditor(
289 mMouseDownY(0), 326 mMouseDownY(0),
290 mLastSelectionX(-1), 327 mLastSelectionX(-1),
291 mLastSelectionY(-1), 328 mLastSelectionY(-1),
329 mLastContextMenuX(-1),
330 mLastContextMenuY(-1),
292 mReflowNeeded(FALSE), 331 mReflowNeeded(FALSE),
293 mScrollNeeded(FALSE) 332 mScrollNeeded(FALSE),
333 mSpellCheckable(FALSE),
334 mAllowTranslate(TRUE)
294{ 335{
295 mSourceID.generate(); 336 mSourceID.generate();
296 337
@@ -342,8 +383,21 @@ LLTextEditor::LLTextEditor(
342 383
343 mParseHTML=FALSE; 384 mParseHTML=FALSE;
344 mHTML.clear(); 385 mHTML.clear();
345}
346 386
387 // make the popup menu available
388
389 LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_rightclick_text.xml",this);
390 if (!menu)
391 {
392 menu = new LLMenuGL(LLStringUtil::null);
393 }
394
395 defineMenuCallbacks(menu);
396 mPopupMenuHandle = menu->getHandle();
397 menu->setBorderColor(gColors.getColor("MenuItemDisabledColor"));
398 menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
399
400}
347 401
348LLTextEditor::~LLTextEditor() 402LLTextEditor::~LLTextEditor()
349{ 403{
@@ -360,8 +414,247 @@ LLTextEditor::~LLTextEditor()
360 std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); 414 std::for_each(mSegments.begin(), mSegments.end(), DeletePointer());
361 415
362 std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); 416 std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
417 LLView::deleteViewByHandle(mPopupMenuHandle);
418}
419
420BOOL LLTextEditor::context_enable_cut(void* data)
421{
422 LLTextEditor* line = (LLTextEditor*)data;
423 return (line && line->canCut());
424}
425
426void LLTextEditor::context_cut(void* data)
427{
428 LLTextEditor* line = (LLTextEditor*)data;
429 if(line)line->cut();
430}
431
432BOOL LLTextEditor::context_enable_copy(void* data)
433{
434 LLTextEditor* line = (LLTextEditor*)data;
435 return (line && line->canCopy());
436}
437
438void LLTextEditor::context_copy(void* data)
439{
440 LLTextEditor* line = (LLTextEditor*)data;
441 if(line)line->copy();
442}
443
444BOOL LLTextEditor::context_enable_translate(void * data)
445{
446 LLTextEditor* editor = (LLTextEditor*)data;
447 return editor && editor->canTranslate();
448}
449
450void LLTextEditor::context_translate(void * data)
451{
452 LLTextEditor* line = (LLTextEditor*)data;
453 LLMenuGL* menu = line ? (LLMenuGL*)(line->mPopupMenuHandle.get()) : NULL;
454 LLMenuGL* translate_menu = menu ? menu->getChildMenuByName("Translation Options", TRUE) : NULL;
455 if (!translate_menu)
456 {
457 return;
458 }
459 const std::string to_lang = translate_menu->getHighlightedItem()->getName();
460
461 bool has_text = false;
462 S32 start, length;
463 if (line->hasSelection())
464 {
465 // translate selection
466 start = llmin(line->mSelectionStart, line->mSelectionEnd);
467 length = abs(line->mSelectionEnd - line->mSelectionStart);
468 has_text = length > 0;
469 }
470 else
471 {
472 // translate one word as click position
473 S32 at = line->getCursorPosFromLocalCoord(line->mLastContextMenuX, line->mLastContextMenuY, TRUE);
474 has_text = line->getWordBoundriesAt(at, &start, &length);
475 }
476
477 if (has_text)
478 {
479 const std::string to_translate = wstring_to_utf8str(line->getWText().substr(start, length));
480 LLHTTPClient::ResponderPtr result = TextChatTranslationReceiver::build(to_lang, line, start, length);
481 LLTranslate::translateMessage(result,"", to_lang, to_translate);
482 }
483}
484
485void LLTextEditor::spell_correct(void* data)
486{
487 SpellMenuBind* tempBind = (SpellMenuBind*)data;
488 LLTextEditor* line = tempBind->origin;
489 if(tempBind && line)
490 {
491 llinfos << tempBind->menuItem->getName() << " : " << tempBind->origin->getName() << " : " << tempBind->word << llendl;
492 if(line)line->spellReplace(tempBind);
493
494 }
495}
496void LLTextEditor::spell_show(void * data)
497{
498 SpellMenuBind* tempBind = (SpellMenuBind*)data;
499 LLTextEditor* line = tempBind->origin;
500
501 if (tempBind && line)
502 {
503 BOOL show = (tempBind->word == "Show Misspellings");
504 glggHunSpell->setSpellCheckHighlight(show);
505 }
506}
507
508void LLTextEditor::getMisspelledWordsPositions(std::vector<S32>& misspell_positions)
509{
510 resetSpellDirty();
511 misspell_positions.clear();
512 LLWString& text = mWText;
513 S32 wordStart=0;
514 S32 wordEnd=spellStart;//start at the scroll start
515 while(wordEnd < spellEnd)
516 {
517 //go through all the chars... XD
518 if( LLTextEditor::isPartOfWord( text[wordEnd] ) )
519 {
520 // Select word the cursor is over
521 while ((wordEnd > 0) && LLTextEditor::isPartOfWord(text[wordEnd-1]))
522 {
523 wordEnd--;
524 }
525 wordStart=wordEnd;
526 while ((wordEnd < (S32)text.length()) && LLTextEditor::isPartOfWord( text[wordEnd] ) )
527 {
528 wordEnd++;
529 }
530
531 //got a word? -- MC
532 if (wordStart != wordEnd)
533 {
534 std::string regText(text.begin(),text.end());
535 std::string selectedWord(regText.substr(wordStart,wordEnd-wordStart));
536
537 if(!selectedWord.empty() && !glggHunSpell->isSpelledRight(selectedWord))
538 {
539 //misspelled word here, and you have just right clicked on it
540
541 misspell_positions.push_back(wordStart);
542 misspell_positions.push_back(wordEnd);
543 }
544 }
545 }
546 wordEnd++;
547 }
548}
549
550void LLTextEditor::spell_add(void* data)
551{
552 SpellMenuBind* tempBind = (SpellMenuBind*)data;
553 if(tempBind)
554 {
555 glggHunSpell->addWordToCustomDictionary(tempBind->word);
556 tempBind->origin->mPrevSpelledText.erase();//make it update
557 }
558}
559
560BOOL LLTextEditor::context_enable_paste(void* data)
561{
562 LLTextEditor* line = (LLTextEditor*)data;
563 return(line && line->canPaste());
564}
565
566void LLTextEditor::context_paste(void* data)
567{
568 LLTextEditor* line = (LLTextEditor*)data;
569 if(line)line->paste();
570}
571
572BOOL LLTextEditor::context_enable_delete(void* data)
573{
574 LLTextEditor* line = (LLTextEditor*)data;
575 return (line && line->canDoDelete());
576}
577
578void LLTextEditor::context_delete(void* data)
579{
580 LLTextEditor* line = (LLTextEditor*)data;
581 if(line)line->doDelete();
582}
583
584BOOL LLTextEditor::context_enable_selectall(void* data)
585{
586 LLTextEditor* line = (LLTextEditor*)data;
587 return (line && line->canSelectAll());
588}
589
590void LLTextEditor::context_selectall(void* data)
591{
592 LLTextEditor* line = (LLTextEditor*)data;
593 if(line)line->selectAll();
594}
595
596// method to define the associated callbacks
597void LLTextEditor::defineMenuCallbacks(LLMenuGL* menu) {
598
599 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
600 "Cut Text",
601 this,
602 (void*)context_enable_cut);
603 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
604 "Cut Text",
605 this,
606 (void*)context_cut);
607
608 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
609 "Copy Text",
610 this,
611 (void*)context_enable_copy);
612 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
613 "Copy Text",
614 this,
615 (void*)context_copy);
616
617 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
618 "Paste Text",
619 this,
620 (void*)context_enable_paste);
621 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
622 "Paste Text",
623 this,
624 (void*)context_paste);
625
626 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
627 "Delete Text",
628 this,
629 (void*)context_enable_delete);
630 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
631 "Delete Text",
632 this,
633 (void*)context_delete);
634
635 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
636 "Select All Text",
637 this,
638 (void*)context_enable_selectall);
639 menu->setCtrlResponse(1+LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_CLICK,
640 "Select All Text",
641 this,
642 (void*)context_selectall);
643
644 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_ON_ENABLE,
645 "Translate Text",
646 this,
647 (void*)context_enable_translate);
648 menu->setCtrlResponse(LLCallbackInformation::LL_MENU_ITEM_CALL_GL_TRANSLATE,
649 "Translate Text",
650 this,
651 (void*)context_translate);
652
653
654
363} 655}
364 656
657
365void LLTextEditor::setTrackColor( const LLColor4& color ) 658void LLTextEditor::setTrackColor( const LLColor4& color )
366{ 659{
367 mScrollbar->setTrackColor(color); 660 mScrollbar->setTrackColor(color);
@@ -738,6 +1031,26 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
738 return cursorPos; 1031 return cursorPos;
739} 1032}
740 1033
1034BOOL LLTextEditor::getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const
1035{
1036 S32 pos = at;
1037 if (isPartOfWord(mWText[pos]))
1038 {
1039 while ( (pos > 0) && isPartOfWord(mWText[pos - 1]) )
1040 {
1041 pos--;
1042 }
1043 *word_begin = pos;
1044 while ( (pos < getLength()) && isPartOfWord(mWText[pos]) )
1045 {
1046 pos++;
1047 }
1048 *word_length = pos - *word_begin;
1049 return TRUE;
1050 }
1051 return FALSE;
1052}
1053
741S32 LLTextEditor::getLineStart( S32 line ) const 1054S32 LLTextEditor::getLineStart( S32 line ) const
742{ 1055{
743 S32 num_lines = getLineCount(); 1056 S32 num_lines = getLineCount();
@@ -1142,6 +1455,14 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
1142{ 1455{
1143 BOOL handled = FALSE; 1456 BOOL handled = FALSE;
1144 1457
1458 // SL-51858: Key presses are not being passed to the Popup menu.
1459 // A proper fix is non-trivial so instead just close the menu.
1460 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
1461 if (menu && menu->isOpen())
1462 {
1463 LLMenuGL::sMenuContainer->hideMenus();
1464 }
1465
1145 // Let scrollbar have first dibs 1466 // Let scrollbar have first dibs
1146 handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; 1467 handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
1147 1468
@@ -1216,6 +1537,99 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
1216 1537
1217 return handled; 1538 return handled;
1218} 1539}
1540BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
1541{
1542 setFocus(TRUE);
1543
1544 //setCursorAtLocalPos( x, y, TRUE );
1545 S32 wordStart = 0;
1546 S32 wordLen = 0;
1547 S32 pos = getCursorPosFromLocalCoord(x,y,TRUE);
1548
1549 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
1550 if (menu)
1551 {
1552 for(int i = 0;i<(int)suggestionMenuItems.size();i++)
1553 {
1554 SpellMenuBind * tempBind = suggestionMenuItems[i];
1555 if(tempBind)
1556 {
1557 menu->remove(tempBind->menuItem);
1558 tempBind->menuItem->die();
1559 //delete tempBind->menuItem;
1560 //tempBind->menuItem = NULL;
1561 delete tempBind;
1562 }
1563 }
1564 suggestionMenuItems.clear();
1565
1566 // spell_check="true" in xui
1567 menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable);
1568 if (!mReadOnly && mSpellCheckable)
1569 {
1570 bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordLen);
1571 if (is_word_part)
1572 {
1573 const LLWString &text = mWText;
1574 std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordLen));
1575
1576 if (!glggHunSpell->isSpelledRight(selectedWord))
1577 {
1578 //misspelled word here, and you have just right clicked on it!
1579 std::vector<std::string> suggs = glggHunSpell->getSuggestionList(selectedWord);
1580
1581 for (int i = 0; i<(int)suggs.size(); i++)
1582 {
1583 SpellMenuBind * tempStruct = new SpellMenuBind;
1584 tempStruct->origin = this;
1585 tempStruct->word = suggs[i];
1586 tempStruct->wordPositionEnd = wordStart + wordLen;
1587 tempStruct->wordPositionStart=wordStart;
1588 tempStruct->wordY=y;
1589 LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL(
1590 tempStruct->word, spell_correct, NULL, tempStruct);
1591 tempStruct->menuItem = suggMenuItem;
1592 suggestionMenuItems.push_back(tempStruct);
1593 menu->append(suggMenuItem);
1594 }
1595 SpellMenuBind * tempStruct = new SpellMenuBind;
1596 tempStruct->origin = this;
1597 tempStruct->word = selectedWord;
1598 tempStruct->wordPositionEnd = wordStart + wordLen;
1599 tempStruct->wordPositionStart=wordStart;
1600 tempStruct->wordY=y;
1601 LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL(
1602 "Add Word", spell_add, NULL, tempStruct);
1603 tempStruct->menuItem = suggMenuItem;
1604 suggestionMenuItems.push_back(tempStruct);
1605 menu->append(suggMenuItem);
1606 }
1607 }
1608
1609 SpellMenuBind * tempStruct = new SpellMenuBind;
1610 tempStruct->origin = this;
1611 if (glggHunSpell->getSpellCheckHighlight())
1612 {
1613 tempStruct->word = "Hide Misspellings";
1614 }
1615 else
1616 {
1617 tempStruct->word = "Show Misspellings";
1618 }
1619 LLMenuItemCallGL * suggMenuItem = new LLMenuItemCallGL(
1620 tempStruct->word, spell_show, NULL, tempStruct);
1621 tempStruct->menuItem = suggMenuItem;
1622 suggestionMenuItems.push_back(tempStruct);
1623 menu->append(suggMenuItem);
1624 }
1625 mLastContextMenuX = x;
1626 mLastContextMenuY = y;
1627 menu->buildDrawLabels();
1628 menu->updateParent(LLMenuGL::sMenuContainer);
1629 LLMenuGL::showPopup(this, menu, x, y);
1630 }
1631 return TRUE;
1632}
1219 1633
1220 1634
1221BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) 1635BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
@@ -1350,11 +1764,6 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
1350 1764
1351 setCursorAtLocalPos( x, y, TRUE ); 1765 setCursorAtLocalPos( x, y, TRUE );
1352 endSelection(); 1766 endSelection();
1353
1354 updateScrollFromCursor();
1355
1356 // take selection to primary clipboard
1357 updatePrimary();
1358 } 1767 }
1359 1768
1360 if( !hasSelection() ) 1769 if( !hasSelection() )
@@ -1432,7 +1841,6 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
1432 1841
1433 handled = TRUE; 1842 handled = TRUE;
1434 } 1843 }
1435
1436 return handled; 1844 return handled;
1437} 1845}
1438 1846
@@ -1913,6 +2321,45 @@ BOOL LLTextEditor::canPaste() const
1913 return !mReadOnly && gClipboard.canPasteString(); 2321 return !mReadOnly && gClipboard.canPasteString();
1914} 2322}
1915 2323
2324void LLTextEditor::spellReplace(SpellMenuBind* spellData)
2325{
2326 remove( spellData->wordPositionStart,
2327 spellData->wordPositionEnd - spellData->wordPositionStart, TRUE );
2328 LLWString clean_string = utf8str_to_wstring(spellData->word);
2329 insert(spellData->wordPositionStart, clean_string, FALSE);
2330 mCursorPos+=clean_string.length() - (spellData->wordPositionEnd-spellData->wordPositionStart);
2331 needsReflow();
2332}
2333
2334void LLTextEditor::translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length)
2335{
2336 //*TODO: should probably check if the content was modified since the http query
2337 // was made, so we don't insert text in the wrong place.
2338 BOOL replace = gSavedSettings.getBOOL("EmeraldTranslateReplace");
2339 LLWString wtext = utf8str_to_wstring(replace ? translation : " (" + translation + ")");
2340 S32 pos = replace ? orig_start : orig_start + orig_length;
2341 if (replace)
2342 {
2343 remove(orig_start, orig_length, FALSE);
2344 }
2345 S32 inserted = insert(pos, wtext, FALSE);
2346 if (hasSelection())
2347 {
2348 mSelectionStart = llclamp(pos, 0, getLength());
2349 mSelectionEnd = llclamp(pos + inserted, mSelectionStart, getLength());
2350 }
2351 setCursorPos(pos + inserted);
2352 needsReflow();
2353}
2354
2355BOOL LLTextEditor::canTranslate() const
2356{
2357 // if allow_translate="true" in xui, and if other factors permit, we allow it
2358 S32 pos = getCursorPosFromLocalCoord(mLastContextMenuX, mLastContextMenuY, TRUE);
2359 bool is_word_part = (pos > -1) && isPartOfWord(mWText[pos]);
2360 return (mAllowTranslate && !mReadOnly && (is_word_part || hasSelection()));
2361}
2362
1916// paste from clipboard 2363// paste from clipboard
1917void LLTextEditor::paste() 2364void LLTextEditor::paste()
1918{ 2365{
@@ -1932,25 +2379,35 @@ void LLTextEditor::pasteHelper(bool is_primary)
1932{ 2379{
1933 bool can_paste_it; 2380 bool can_paste_it;
1934 if (is_primary) 2381 if (is_primary)
2382 {
1935 can_paste_it = canPastePrimary(); 2383 can_paste_it = canPastePrimary();
2384 }
1936 else 2385 else
2386 {
1937 can_paste_it = canPaste(); 2387 can_paste_it = canPaste();
2388 }
1938 2389
1939 if (!can_paste_it) 2390 if (!can_paste_it)
1940 { 2391 {
1941 return; 2392 return;
1942 } 2393 }
2394
1943 LLUUID source_id; 2395 LLUUID source_id;
1944 LLWString paste; 2396 LLWString paste;
1945 if (is_primary) 2397 if (is_primary)
2398 {
1946 paste = gClipboard.getPastePrimaryWString(&source_id); 2399 paste = gClipboard.getPastePrimaryWString(&source_id);
2400 }
1947 else 2401 else
2402 {
1948 paste = gClipboard.getPasteWString(&source_id); 2403 paste = gClipboard.getPasteWString(&source_id);
2404 }
1949 2405
1950 if (paste.empty()) 2406 if (paste.empty())
1951 { 2407 {
1952 return; 2408 return;
1953 } 2409 }
2410
1954 // Delete any selected characters (the paste replaces them) 2411 // Delete any selected characters (the paste replaces them)
1955 if( (!is_primary) && hasSelection() ) 2412 if( (!is_primary) && hasSelection() )
1956 { 2413 {
@@ -1995,7 +2452,7 @@ void LLTextEditor::copyPrimary()
1995 return; 2452 return;
1996 } 2453 }
1997 S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); 2454 S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
1998 S32 length = abs( mSelectionStart - mSelectionEnd ); 2455 S32 length = llabs( mSelectionStart - mSelectionEnd );
1999 gClipboard.copyFromPrimarySubstring(mWText, left_pos, length, mSourceID); 2456 gClipboard.copyFromPrimarySubstring(mWText, left_pos, length, mSourceID);
2000} 2457}
2001 2458
@@ -2262,6 +2719,13 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
2262 BOOL selection_modified = FALSE; 2719 BOOL selection_modified = FALSE;
2263 BOOL return_key_hit = FALSE; 2720 BOOL return_key_hit = FALSE;
2264 BOOL text_may_have_changed = TRUE; 2721 BOOL text_may_have_changed = TRUE;
2722 // SL-51858: Key presses are not being passed to the Popup menu.
2723 // A proper fix is non-trivial so instead just close the menu.
2724 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
2725 if (menu && menu->isOpen())
2726 {
2727 LLMenuGL::sMenuContainer->hideMenus();
2728 }
2265 2729
2266 if ( gFocusMgr.getKeyboardFocus() == this ) 2730 if ( gFocusMgr.getKeyboardFocus() == this )
2267 { 2731 {
@@ -2306,6 +2770,14 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
2306 } 2770 }
2307 } 2771 }
2308 2772
2773 // SL-51858: Key presses are not being passed to the Popup menu.
2774 // A proper fix is non-trivial so instead just close the menu.
2775 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
2776 if (menu && menu->isOpen())
2777 {
2778 LLMenuGL::sMenuContainer->hideMenus();
2779 }
2780
2309 // Handle most keys only if the text editor is writeable. 2781 // Handle most keys only if the text editor is writeable.
2310 if( !mReadOnly ) 2782 if( !mReadOnly )
2311 { 2783 {
@@ -2740,10 +3212,155 @@ void LLTextEditor::drawSelectionBackground()
2740 } 3212 }
2741} 3213}
2742 3214
3215void LLTextEditor::autoCorrectText()
3216{
3217 static BOOL *doAnything = rebind_llcontrol<BOOL>("EmeraldEnableAutoCorrect", &gSavedSettings, true);
3218 if (!mReadOnly && *doAnything && isSpellDirty())
3219 {
3220 S32 wordStart = 0;
3221 S32 wordEnd = mCursorPos-1;
3222 if (wordEnd < 1)
3223 {
3224 return;
3225 }
3226 LLWString& text = mWText;
3227 if (text.size() < 1 || LLTextEditor::isPartOfWord(text[wordEnd]))
3228 {
3229 return;//we only check on word breaks
3230 }
3231
3232 wordEnd--;
3233 if (LLTextEditor::isPartOfWord(text[wordEnd]))
3234 {
3235 while ((wordEnd > 0) && (text[wordEnd-1]!=' '))
3236 {
3237 wordEnd--;
3238 }
3239 wordStart = wordEnd;
3240 while ((wordEnd < (S32)text.length()) && (' '!= text[wordEnd] ) )
3241 {
3242 wordEnd++;
3243 }
3244 std::string lastTypedWord(std::string(text.begin(),
3245 text.end()).substr(wordStart, wordEnd-wordStart));
3246
3247 std::string regText(text.begin(), text.end());
3248
3249 std::string correctedWord(LGGAutoCorrect::getInstance()->replaceWord(lastTypedWord));
3250 if (correctedWord != lastTypedWord)
3251 {
3252 int dif = correctedWord.length() - lastTypedWord.length();
3253 regText.replace(wordStart, lastTypedWord.length(), correctedWord);
3254 mWText = utf8str_to_wstring(regText);
3255 mCursorPos += dif;
3256 needsReflow();
3257 }
3258 }
3259 }
3260}
3261
3262void LLTextEditor::drawMisspelled()
3263{
3264 if (!mReadOnly && mSpellCheckable)
3265 {
3266 if(
3267 ( ((getLength()<400)||(false)) &&( (S32(mSpellTimer.getElapsedTimeF32() / 1) & 1) ))
3268 ||
3269 (S32(mKeystrokeTimer.getElapsedTimeF32() / 1) & 1)
3270 )
3271 {
3272 S32 newSpellStart = getLineStart(mScrollbar->getDocPos());//start at the scroll start
3273 S32 newSpellEnd = getLineStart(mScrollbar->getDocPos() + 1 + mScrollbar->getDocSize()-mScrollbar->getDocPosMax());//end at the end o.o
3274
3275 if (mScrollbar->getDocPos() == mScrollbar->getDocPosMax())
3276 {
3277 newSpellEnd = (S32)mWText.length();
3278 }
3279 if (isSpellDirty() || (newSpellEnd!=spellEnd || newSpellStart!=spellStart))
3280 {
3281 spellEnd = newSpellEnd;
3282 spellStart = newSpellStart;
3283 getMisspelledWordsPositions(mMisspellLocations);
3284 }
3285 }
3286 //draw
3287 if (!mMisspellLocations.empty() && glggHunSpell->getSpellCheckHighlight())
3288 {
3289 for (int i = 0; i<(int)mMisspellLocations.size() ;i++)
3290 {
3291 S32 wstart = mMisspellLocations[i];
3292 S32 wend = mMisspellLocations[++i];
3293 //start curor code mod
3294 const LLWString &text = mWText;
3295 const S32 text_len = getLength();
3296 // Skip through the lines we aren't drawing.
3297 S32 search_pos = mScrollbar->getDocPos();
3298 S32 num_lines = getLineCount();
3299 if (search_pos >= num_lines)
3300 {
3301 return;
3302 }
3303 S32 line_start = getLineStart(search_pos);
3304 F32 line_height = mGLFont->getLineHeight();
3305 F32 text_y = (F32)(mTextRect.mTop) - line_height;
3306
3307 F32 word_left = 0.f;
3308 F32 word_right = 0.f;
3309 F32 word_bottom = 0.f;
3310 BOOL word_visible = FALSE;
3311
3312 S32 line_end = 0;
3313 // Determine if the cursor is visible and if so what its coordinates are.
3314 while( (mTextRect.mBottom <= llround(text_y)) && (search_pos < num_lines))
3315 {
3316 line_end = text_len + 1;
3317 S32 next_line = -1;
3318
3319 if ((search_pos + 1) < num_lines)
3320 {
3321 next_line = getLineStart(search_pos + 1);
3322 line_end = next_line - 1;
3323 }
3324 const llwchar* line = text.c_str() + line_start;
3325 // Find the cursor and selection bounds
3326 if( line_start <= wstart && wend <= line_end )
3327 {
3328 word_visible = TRUE;
3329 word_left = (F32)mTextRect.mLeft + mGLFont->getWidthF32(line, 0, wstart - line_start, mAllowEmbeddedItems )-1.f;
3330 word_right = (F32)mTextRect.mLeft + mGLFont->getWidthF32(line, 0, wend - line_start, mAllowEmbeddedItems )+1.f;
3331 word_bottom = text_y;
3332 break;
3333 }
3334 // move down one line
3335 text_y -= line_height;
3336 line_start = next_line;
3337 search_pos++;
3338 }
3339 if (mShowLineNumbers)
3340 {
3341 word_left += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
3342 word_right += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
3343 }
3344 // Draw the cursor
3345 if (word_visible)
3346 {
3347 //end cursor code mod
3348 gGL.color4ub(255,0,0,200);
3349 while (word_left<word_right)
3350 {
3351 gl_line_2d(word_left,word_bottom-2, word_left+3,word_bottom+1);
3352 gl_line_2d(word_left+3,word_bottom+1, word_left+6,word_bottom-2);
3353 word_left += 6;
3354 }
3355 }
3356 }
3357 }
3358 }
3359}
3360
2743void LLTextEditor::drawCursor() 3361void LLTextEditor::drawCursor()
2744{ 3362{
2745 if( gFocusMgr.getKeyboardFocus() == this 3363 if (!mReadOnly && gFocusMgr.getKeyboardFocus() == this && gShowTextEditCursor)
2746 && gShowTextEditCursor && !mReadOnly)
2747 { 3364 {
2748 const LLWString &text = mWText; 3365 const LLWString &text = mWText;
2749 const S32 text_len = getLength(); 3366 const S32 text_len = getLength();
@@ -3205,6 +3822,8 @@ void LLTextEditor::draw()
3205 mReflowNeeded = FALSE; 3822 mReflowNeeded = FALSE;
3206 } 3823 }
3207 3824
3825 autoCorrectText();
3826
3208 // then update scroll position, as cursor may have moved 3827 // then update scroll position, as cursor may have moved
3209 if (mScrollNeeded) 3828 if (mScrollNeeded)
3210 { 3829 {
@@ -3222,7 +3841,8 @@ void LLTextEditor::draw()
3222 drawPreeditMarker(); 3841 drawPreeditMarker();
3223 drawText(); 3842 drawText();
3224 drawCursor(); 3843 drawCursor();
3225 3844 drawMisspelled();
3845 resetSpellDirty();
3226 unbindEmbeddedChars(mGLFont); 3846 unbindEmbeddedChars(mGLFont);
3227 3847
3228 //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret 3848 //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
@@ -3250,6 +3870,8 @@ void LLTextEditor::onTabInto()
3250void LLTextEditor::clear() 3870void LLTextEditor::clear()
3251{ 3871{
3252 setText(LLStringUtil::null); 3872 setText(LLStringUtil::null);
3873 std::for_each(mSegments.begin(), mSegments.end(), DeletePointer());
3874 mSegments.clear();
3253} 3875}
3254 3876
3255// Start or stop the editor from accepting text-editing keystrokes 3877// Start or stop the editor from accepting text-editing keystrokes
@@ -3598,13 +4220,13 @@ void LLTextEditor::autoIndent()
3598} 4220}
3599 4221
3600// Inserts new text at the cursor position 4222// Inserts new text at the cursor position
3601void LLTextEditor::insertText(const std::string &new_text) 4223void LLTextEditor::insertText(const std::string &new_text,BOOL deleteCurrentSelection)
3602{ 4224{
3603 BOOL enabled = getEnabled(); 4225 BOOL enabled = getEnabled();
3604 setEnabled( TRUE ); 4226 setEnabled( TRUE );
3605 4227
3606 // Delete any selected characters (the insertion replaces them) 4228 // Delete any selected characters (the insertion replaces them)
3607 if( hasSelection() ) 4229 if( hasSelection() && (deleteCurrentSelection))
3608 { 4230 {
3609 deleteSelection(TRUE); 4231 deleteSelection(TRUE);
3610 } 4232 }
@@ -3624,7 +4246,10 @@ void LLTextEditor::appendColoredText(const std::string &new_text,
3624 const std::string& font_name) 4246 const std::string& font_name)
3625{ 4247{
3626 LLColor4 lcolor=color; 4248 LLColor4 lcolor=color;
3627 if (mParseHighlights) 4249 // If LindenUserDir is empty then we didn't login yet.
4250 // In that case we can't instantiate LLTextParser, which
4251 // is initialized per user.
4252 if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty())
3628 { 4253 {
3629 LLTextParser* highlight = LLTextParser::getInstance(); 4254 LLTextParser* highlight = LLTextParser::getInstance();
3630 highlight->parseFullLineHighlights(new_text, &lcolor); 4255 highlight->parseFullLineHighlights(new_text, &lcolor);
@@ -3638,9 +4263,9 @@ void LLTextEditor::appendColoredText(const std::string &new_text,
3638} 4263}
3639 4264
3640void LLTextEditor::appendStyledText(const std::string &new_text, 4265void LLTextEditor::appendStyledText(const std::string &new_text,
3641 bool allow_undo, 4266 bool allow_undo,
3642 bool prepend_newline, 4267 bool prepend_newline,
3643 const LLStyleSP stylep) 4268 LLStyleSP stylep)
3644{ 4269{
3645 S32 part = (S32)LLTextParser::WHOLE; 4270 S32 part = (S32)LLTextParser::WHOLE;
3646 if(mParseHTML) 4271 if(mParseHTML)
@@ -3648,9 +4273,9 @@ void LLTextEditor::appendStyledText(const std::string &new_text,
3648 4273
3649 S32 start=0,end=0; 4274 S32 start=0,end=0;
3650 std::string text = new_text; 4275 std::string text = new_text;
3651 while ( findHTML(text, &start, &end) ) 4276 std::string url;
4277 while ( findHTML(text, &start, &end, url) )
3652 { 4278 {
3653
3654 LLStyleSP html(new LLStyle); 4279 LLStyleSP html(new LLStyle);
3655 html->setVisible(true); 4280 html->setVisible(true);
3656 html->setColor(mLinkColor); 4281 html->setColor(mLinkColor);
@@ -3675,9 +4300,9 @@ void LLTextEditor::appendStyledText(const std::string &new_text,
3675 appendHighlightedText(subtext,allow_undo, prepend_newline, part, stylep); 4300 appendHighlightedText(subtext,allow_undo, prepend_newline, part, stylep);
3676 } 4301 }
3677 4302
3678 html->setLinkHREF(text.substr(start,end-start)); 4303 html->setLinkHREF(url);
3679 appendText(text.substr(start, end-start),allow_undo, prepend_newline, html); 4304 appendText(text.substr(start, end-start),allow_undo, prepend_newline, html);
3680 if (end < (S32)text.length()) 4305 if (end < (S32)text.length())
3681 { 4306 {
3682 text = text.substr(end,text.length() - end); 4307 text = text.substr(end,text.length() - end);
3683 end=0; 4308 end=0;
@@ -3688,6 +4313,7 @@ void LLTextEditor::appendStyledText(const std::string &new_text,
3688 break; 4313 break;
3689 } 4314 }
3690 } 4315 }
4316
3691 if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END; 4317 if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END;
3692 if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, stylep); 4318 if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, stylep);
3693 } 4319 }
@@ -3703,7 +4329,10 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text,
3703 S32 highlight_part, 4329 S32 highlight_part,
3704 LLStyleSP stylep) 4330 LLStyleSP stylep)
3705{ 4331{
3706 if (mParseHighlights) 4332 // If LindenUserDir is empty then we didn't login yet.
4333 // In that case we can't instantiate LLTextParser, which
4334 // is initialized per user.
4335 if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty())
3707 { 4336 {
3708 LLTextParser* highlight = LLTextParser::getInstance(); 4337 LLTextParser* highlight = LLTextParser::getInstance();
3709 4338
@@ -3784,6 +4413,10 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool
3784 { 4413 {
3785 mSelectionStart = selection_start; 4414 mSelectionStart = selection_start;
3786 mSelectionEnd = selection_end; 4415 mSelectionEnd = selection_end;
4416
4417
4418
4419
3787 mIsSelecting = was_selecting; 4420 mIsSelecting = was_selecting;
3788 setCursorPos(cursor_pos); 4421 setCursorPos(cursor_pos);
3789 } 4422 }
@@ -3952,6 +4585,15 @@ void LLTextEditor::loadKeywords(const std::string& filename,
3952 } 4585 }
3953} 4586}
3954 4587
4588void LLTextEditor::addToken(LLKeywordToken::TOKEN_TYPE type,
4589 const std::string& key,
4590 const LLColor3& color,
4591 const std::string& tool_tip,
4592 const std::string& delimiter)
4593{
4594 mKeywords.addToken(type,key,color,tool_tip);
4595}
4596
3955void LLTextEditor::updateSegments() 4597void LLTextEditor::updateSegments()
3956{ 4598{
3957 if (mKeywords.isLoaded()) 4599 if (mKeywords.isLoaded())
@@ -4385,6 +5027,10 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node)
4385 5027
4386 node->getAttributeBOOL("track_bottom", mTrackBottom); 5028 node->getAttributeBOOL("track_bottom", mTrackBottom);
4387 5029
5030 node->getAttributeBOOL("spell_check", mSpellCheckable);
5031
5032 node->getAttributeBOOL("allow_translate", mAllowTranslate);
5033
4388 LLColor4 color; 5034 LLColor4 color;
4389 if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color)) 5035 if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color))
4390 { 5036 {
@@ -4417,11 +5063,9 @@ S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse)
4417 std::string openers=" \t\n('\"[{<>"; 5063 std::string openers=" \t\n('\"[{<>";
4418 std::string closers=" \t\n)'\"]}><;"; 5064 std::string closers=" \t\n)'\"]}><;";
4419 5065
4420 S32 index = 0;
4421
4422 if (reverse) 5066 if (reverse)
4423 { 5067 {
4424 for (index=pos; index >= 0; index--) 5068 for (int index=pos; index >= 0; index--)
4425 { 5069 {
4426 char c = line[index]; 5070 char c = line[index];
4427 S32 m2 = openers.find(c); 5071 S32 m2 = openers.find(c);
@@ -4430,13 +5074,13 @@ S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse)
4430 return index+1; 5074 return index+1;
4431 } 5075 }
4432 } 5076 }
4433 index = 0; // Can't be before first charater 5077 return 0; // index is -1, don't want to return that.
4434 } 5078 }
4435 else 5079 else
4436 { 5080 {
4437 // adjust the search slightly, to allow matching parenthesis inside the URL 5081 // adjust the search slightly, to allow matching parenthesis inside the URL
4438 S32 paren_count = 0; 5082 S32 paren_count = 0;
4439 for (index=pos; index<(S32)line.length(); index++) 5083 for (int index=pos; index<(S32)line.length(); index++)
4440 { 5084 {
4441 char c = line[index]; 5085 char c = line[index];
4442 5086
@@ -4464,12 +5108,11 @@ S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse)
4464 } 5108 }
4465 } 5109 }
4466 } 5110 }
5111 return line.length();
4467 } 5112 }
4468
4469 return index;
4470} 5113}
4471 5114
4472BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const 5115BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end, std::string& url) const
4473{ 5116{
4474 5117
4475 S32 m1,m2,m3; 5118 S32 m1,m2,m3;
@@ -4481,34 +5124,21 @@ BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const
4481 { 5124 {
4482 *begin = findHTMLToken(line, m1, TRUE); 5125 *begin = findHTMLToken(line, m1, TRUE);
4483 *end = findHTMLToken(line, m1, FALSE); 5126 *end = findHTMLToken(line, m1, FALSE);
4484
4485 // Can't start before the first char
4486 if(*begin < 0)
4487 {
4488 //*begin = 0;
4489 }
4490 5127
4491 //Load_url only handles http and https so don't hilite ftp, smb, etc. 5128 //Load_url only handles http and https so don't hilite ftp, smb, etc.
4492 try 5129 m2 = line.substr(*begin,(m1 - *begin)).find("http");
5130 m3 = line.substr(*begin,(m1 - *begin)).find("secondlife");
5131
5132 std::string badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\";
5133
5134 if (m2 >= 0 || m3>=0)
4493 { 5135 {
4494 m2 = line.substr(*begin,(m1 - *begin)).find("http"); 5136 S32 bn = badneighbors.find(line.substr(m1+3,1));
4495 m3 = line.substr(*begin,(m1 - *begin)).find("secondlife"); 5137
4496 5138 if (bn < 0)
4497 std::string badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\"; 5139 {
4498 5140 matched = TRUE;
4499 if (m2 >= 0 || m3>=0)
4500 {
4501 S32 bn = badneighbors.find(line.substr(m1+3,1));
4502
4503 if (bn < 0)
4504 {
4505 matched = TRUE;
4506 }
4507 } 5141 }
4508 }
4509 catch ( std::out_of_range outOfRange )
4510 {
4511 LL_WARNS("TextEditor") << "got std::out_of_range exception \"" << line << "\"" << LL_ENDL;
4512 } 5142 }
4513 } 5143 }
4514/* matches things like secondlife.com (no http://) needs a whitelist to really be effective. 5144/* matches things like secondlife.com (no http://) needs a whitelist to really be effective.
@@ -4541,34 +5171,35 @@ BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const
4541 { 5171 {
4542 S32 strpos, strpos2; 5172 S32 strpos, strpos2;
4543 5173
5174 // Is this try here still needed considering the changes to LLTextEditor::findHTMLToken? - MC
4544 try 5175 try
4545 { 5176 {
4546 std::string url = line.substr(*begin,*end - *begin); 5177 url = line.substr(*begin,*end - *begin);
4547 std::string slurlID = "slurl.com/secondlife/"; 5178 std::string slurlID = "slurl.com/secondlife/";
4548 strpos = url.find(slurlID); 5179 strpos = url.find(slurlID);
4549 5180
4550 if (strpos < 0) 5181 if (strpos < 0)
4551 { 5182 {
4552 slurlID="maps.secondlife.com/secondlife/"; 5183 slurlID="maps.secondlife.com/secondlife/";
4553 strpos = url.find(slurlID); 5184 strpos = url.find(slurlID);
4554 } 5185 }
4555 5186
4556 if (strpos < 0) 5187 if (strpos < 0)
4557 { 5188 {
4558 slurlID="secondlife://"; 5189 slurlID="secondlife://";
4559 strpos = url.find(slurlID); 5190 strpos = url.find(slurlID);
4560 } 5191 }
4561 5192
4562 if (strpos < 0) 5193 if (strpos < 0)
4563 { 5194 {
4564 slurlID="sl://"; 5195 slurlID="sl://";
4565 strpos = url.find(slurlID); 5196 strpos = url.find(slurlID);
4566 } 5197 }
4567 5198
4568 if (strpos >= 0) 5199 if (strpos >= 0)
4569 { 5200 {
4570 strpos+=slurlID.length(); 5201 strpos+=slurlID.length();
4571 5202
4572 while ( ( strpos2=url.find("/",strpos) ) == -1 ) 5203 while ( ( strpos2=url.find("/",strpos) ) == -1 )
4573 { 5204 {
4574 if ((*end+2) >= (S32)line.length() || line.substr(*end,1) != " " ) 5205 if ((*end+2) >= (S32)line.length() || line.substr(*end,1) != " " )
@@ -4576,19 +5207,18 @@ BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const
4576 matched=FALSE; 5207 matched=FALSE;
4577 break; 5208 break;
4578 } 5209 }
4579 5210
4580 strpos = (*end + 1) - *begin; 5211 strpos = (*end + 1) - *begin;
4581 5212
4582 *end = findHTMLToken(line,(*begin + strpos),FALSE); 5213 *end = findHTMLToken(line,(*begin + strpos),FALSE);
4583 url = line.substr(*begin,*end - *begin); 5214 url = line.substr(*begin,*end - *begin);
4584 } 5215 }
4585 } 5216 }
4586
4587 } 5217 }
4588 5218
4589 catch ( std::out_of_range outOfRange ) 5219 catch ( std::out_of_range outOfRange )
4590 { 5220 {
4591 LL_WARNS("TextEditor") << "got std::out_of_range exception \"" << line << "\"" << LL_ENDL; 5221 llwarns << "got std::out_of_range exception \"" << line << "\"" << llendl;
4592 } 5222 }
4593 } 5223 }
4594 5224
diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h
index f26bf3b..759cd69 100644
--- a/linden/indra/llui/lltexteditor.h
+++ b/linden/indra/llui/lltexteditor.h
@@ -45,6 +45,7 @@
45#include "lldarray.h" 45#include "lldarray.h"
46 46
47#include "llpreeditor.h" 47#include "llpreeditor.h"
48#include "llmenugl.h"
48 49
49class LLFontGL; 50class LLFontGL;
50class LLScrollbar; 51class LLScrollbar;
@@ -84,6 +85,7 @@ public:
84 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 85 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
85 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 86 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
86 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask ); 87 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
88 virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
87 virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask); 89 virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
88 90
89 virtual BOOL handleKeyHere(KEY key, MASK mask ); 91 virtual BOOL handleKeyHere(KEY key, MASK mask );
@@ -108,23 +110,40 @@ public:
108 virtual void setFocus( BOOL b ); 110 virtual void setFocus( BOOL b );
109 virtual BOOL acceptsTextInput() const; 111 virtual BOOL acceptsTextInput() const;
110 virtual BOOL isDirty() const { return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) ); } 112 virtual BOOL isDirty() const { return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) ); }
113 BOOL isSpellDirty() const { return mWText != mPrevSpelledText; } // Returns TRUE if user changed value at all
114 void resetSpellDirty() { mPrevSpelledText = mWText; } // Clear dirty state
111 115
116 struct SpellMenuBind
117 {
118 LLTextEditor* origin;
119 LLMenuItemCallGL * menuItem;
120 std::string word;
121 S32 wordPositionStart;
122 S32 wordPositionEnd;
123 S32 wordY;
124 };
125
112 // LLEditMenuHandler interface 126 // LLEditMenuHandler interface
113 virtual void undo(); 127 virtual void undo();
114 virtual BOOL canUndo() const; 128 virtual BOOL canUndo() const;
115 virtual void redo(); 129 virtual void redo();
116 virtual BOOL canRedo() const; 130 virtual BOOL canRedo() const;
117
118 virtual void cut(); 131 virtual void cut();
119 virtual BOOL canCut() const; 132 virtual BOOL canCut() const;
120 virtual void copy(); 133 virtual void copy();
121 virtual BOOL canCopy() const; 134 virtual BOOL canCopy() const;
122 virtual void paste(); 135 virtual void paste();
123 virtual BOOL canPaste() const; 136 virtual BOOL canPaste() const;
137
138 virtual void spellReplace(SpellMenuBind* spellData);
139 virtual void translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length);
140 virtual BOOL canTranslate() const;
141
124 virtual void updatePrimary(); 142 virtual void updatePrimary();
125 virtual void copyPrimary(); 143 virtual void copyPrimary();
126 virtual void pastePrimary(); 144 virtual void pastePrimary();
127 virtual BOOL canPastePrimary() const; 145 virtual BOOL canPastePrimary() const;
146
128 virtual void doDelete(); 147 virtual void doDelete();
129 virtual BOOL canDoDelete() const; 148 virtual BOOL canDoDelete() const;
130 virtual void selectAll(); 149 virtual void selectAll();
@@ -132,6 +151,26 @@ public:
132 virtual void deselect(); 151 virtual void deselect();
133 virtual BOOL canDeselect() const; 152 virtual BOOL canDeselect() const;
134 153
154 static BOOL context_enable_cut(void* data);
155 static void context_cut(void* data);
156 static BOOL context_enable_copy(void* data);
157 static void context_copy(void* data);
158 static BOOL context_enable_paste(void* data);
159 static void context_paste(void* data);
160 static BOOL context_enable_delete(void* data);
161 static void context_delete(void* data);
162 static BOOL context_enable_selectall(void* data);
163 static void context_selectall(void* data);
164 static BOOL context_enable_translate(void * data);
165 static void context_translate(void * data);
166 static void spell_correct(void* data);
167 static void spell_add(void* data);
168 static void spell_show(void* data);
169
170 void getMisspelledWordsPositions(std::vector<S32>& misspell_positions);
171
172 void defineMenuCallbacks(LLMenuGL* menu);
173
135 void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); 174 void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
136 BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE); 175 BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
137 void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive); 176 void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
@@ -145,17 +184,17 @@ public:
145 BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } 184 BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
146 185
147 // inserts text at cursor 186 // inserts text at cursor
148 void insertText(const std::string &text); 187 void insertText(const std::string &text, BOOL deleteSelection = TRUE);
149 // appends text at end 188 // appends text at end
150 void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline, 189 void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline,
151 const LLStyleSP stylep = NULL); 190 const LLStyleSP stylep = NULL);
152 191
153 void appendColoredText(const std::string &wtext, bool allow_undo, 192 void appendColoredText(const std::string &wtext, bool allow_undo,
154 bool prepend_newline, 193 bool prepend_newline,
155 const LLColor4 &color, 194 const LLColor4 &color,
156 const std::string& font_name = LLStringUtil::null); 195 const std::string& font_name = LLStringUtil::null);
157 // if styled text starts a line, you need to prepend a newline. 196 // if styled text starts a line, you need to prepend a newline.
158 void appendStyledText(const std::string &new_text, bool allow_undo, 197 void appendStyledText(const std::string &new_text, bool allow_undo,
159 bool prepend_newline, 198 bool prepend_newline,
160 LLStyleSP stylep = NULL); 199 LLStyleSP stylep = NULL);
161 void appendHighlightedText(const std::string &new_text, bool allow_undo, 200 void appendHighlightedText(const std::string &new_text, bool allow_undo,
@@ -182,6 +221,11 @@ public:
182 const std::vector<std::string>& funcs, 221 const std::vector<std::string>& funcs,
183 const std::vector<std::string>& tooltips, 222 const std::vector<std::string>& tooltips,
184 const LLColor3& func_color); 223 const LLColor3& func_color);
224 void addToken(LLKeywordToken::TOKEN_TYPE type,
225 const std::string& key,
226 const LLColor3& color,
227 const std::string& tool_tip = LLStringUtil::null,
228 const std::string& delimiter = LLStringUtil::null);
185 LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); } 229 LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); }
186 LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); } 230 LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); }
187 231
@@ -196,6 +240,7 @@ public:
196 void setThumbColor( const LLColor4& color ); 240 void setThumbColor( const LLColor4& color );
197 void setHighlightColor( const LLColor4& color ); 241 void setHighlightColor( const LLColor4& color );
198 void setShadowColor( const LLColor4& color ); 242 void setShadowColor( const LLColor4& color );
243 void setSpellCheckable(BOOL b) { mSpellCheckable = b; }
199 244
200 // Hacky methods to make it into a word-wrapping, potentially scrolling, 245 // Hacky methods to make it into a word-wrapping, potentially scrolling,
201 // read-only text box. 246 // read-only text box.
@@ -262,7 +307,7 @@ public:
262 const LLTextSegment* getPreviousSegment() const; 307 const LLTextSegment* getPreviousSegment() const;
263 void getSelectedSegments(std::vector<const LLTextSegment*>& segments) const; 308 void getSelectedSegments(std::vector<const LLTextSegment*>& segments) const;
264 309
265 static bool isPartOfWord(llwchar c) { return (c == '_') || LLStringOps::isAlnum((char)c); } 310 static bool isPartOfWord(llwchar c) { return ( (c == '_') || (c == '\'') || LLStringOps::isAlnum((char)c)); }
266 311
267 BOOL isReadOnly() { return mReadOnly; } 312 BOOL isReadOnly() { return mReadOnly; }
268protected: 313protected:
@@ -270,11 +315,14 @@ protected:
270 // Methods 315 // Methods
271 // 316 //
272 317
318 LLHandle<LLView> mPopupMenuHandle;
319
273 S32 getLength() const { return mWText.length(); } 320 S32 getLength() const { return mWText.length(); }
274 void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const; 321 void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const;
275 void drawPreeditMarker(); 322 void drawPreeditMarker();
276 323public:
277 void updateLineStartList(S32 startpos = 0); 324 void updateLineStartList(S32 startpos = 0);
325protected:
278 void updateScrollFromCursor(); 326 void updateScrollFromCursor();
279 void updateTextRect(); 327 void updateTextRect();
280 const LLRect& getTextRect() const { return mTextRect; } 328 const LLRect& getTextRect() const { return mTextRect; }
@@ -301,8 +349,13 @@ protected:
301 BOOL handleSelectionKey(const KEY key, const MASK mask); 349 BOOL handleSelectionKey(const KEY key, const MASK mask);
302 BOOL handleControlKey(const KEY key, const MASK mask); 350 BOOL handleControlKey(const KEY key, const MASK mask);
303 BOOL handleEditKey(const KEY key, const MASK mask); 351 BOOL handleEditKey(const KEY key, const MASK mask);
304 352 // <edit>
353public:
354 // </edit>
305 BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); } 355 BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
356 // <edit>
357 protected:
358 // </edit>
306 BOOL selectionContainsLineBreaks(); 359 BOOL selectionContainsLineBreaks();
307 void startSelection(); 360 void startSelection();
308 void endSelection(); 361 void endSelection();
@@ -310,6 +363,7 @@ protected:
310 363
311 S32 prevWordPos(S32 cursorPos) const; 364 S32 prevWordPos(S32 cursorPos) const;
312 S32 nextWordPos(S32 cursorPos) const; 365 S32 nextWordPos(S32 cursorPos) const;
366 BOOL getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const;
313 367
314 S32 getLineCount() const { return mLineStartList.size(); } 368 S32 getLineCount() const { return mLineStartList.size(); }
315 S32 getLineStart( S32 line ) const; 369 S32 getLineStart( S32 line ) const;
@@ -330,7 +384,7 @@ protected:
330 virtual void unbindEmbeddedChars(const LLFontGL* font) const {} 384 virtual void unbindEmbeddedChars(const LLFontGL* font) const {}
331 385
332 S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const; 386 S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const;
333 BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const; 387 BOOL findHTML(const std::string &line, S32 *begin, S32 *end, std::string& url) const;
334 388
335 // Abstract inner base class representing an undoable editor command. 389 // Abstract inner base class representing an undoable editor command.
336 // Concrete sub-classes can be defined for operations such as insert, remove, etc. 390 // Concrete sub-classes can be defined for operations such as insert, remove, etc.
@@ -400,8 +454,9 @@ protected:
400 // 454 //
401 455
402 // I-beam is just after the mCursorPos-th character. 456 // I-beam is just after the mCursorPos-th character.
457public:
403 S32 mCursorPos; 458 S32 mCursorPos;
404 459protected:
405 // Use these to determine if a click on an embedded item is a drag or not. 460 // Use these to determine if a click on an embedded item is a drag or not.
406 S32 mMouseDownX; 461 S32 mMouseDownX;
407 S32 mMouseDownY; 462 S32 mMouseDownY;
@@ -447,6 +502,8 @@ private:
447 void drawBackground(); 502 void drawBackground();
448 void drawSelectionBackground(); 503 void drawSelectionBackground();
449 void drawCursor(); 504 void drawCursor();
505 void autoCorrectText();
506 void drawMisspelled();
450 void drawText(); 507 void drawText();
451 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); 508 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);
452 509
@@ -477,6 +534,13 @@ private:
477 mutable std::string mUTF8Text; 534 mutable std::string mUTF8Text;
478 mutable BOOL mTextIsUpToDate; 535 mutable BOOL mTextIsUpToDate;
479 536
537 LLWString mPrevSpelledText; // saved string so we know whether to respell or not
538 S32 spellStart;
539 S32 spellEnd;
540 std::vector<S32> mMisspellLocations; // where all the mispelled words are
541 BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field
542 BOOL mAllowTranslate; // set in xui as "allow_translate".
543
480 S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes 544 S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
481 545
482 const LLFontGL* mGLFont; 546 const LLFontGL* mGLFont;
@@ -513,11 +577,18 @@ private:
513 } 577 }
514 }; 578 };
515 typedef std::vector<line_info> line_list_t; 579 typedef std::vector<line_info> line_list_t;
580
581 //to keep track of what we have to remove before showing menu
582 std::vector<SpellMenuBind* > suggestionMenuItems;
583 S32 mLastContextMenuX;
584 S32 mLastContextMenuY;
585
516 line_list_t mLineStartList; 586 line_list_t mLineStartList;
517 BOOL mReflowNeeded; 587 BOOL mReflowNeeded;
518 BOOL mScrollNeeded; 588 BOOL mScrollNeeded;
519 589
520 LLFrameTimer mKeystrokeTimer; 590 LLFrameTimer mKeystrokeTimer;
591 LLFrameTimer mSpellTimer;
521 592
522 LLColor4 mCursorColor; 593 LLColor4 mCursorColor;
523 594
diff --git a/linden/indra/llui/lltextparser.cpp b/linden/indra/llui/lltextparser.cpp
index 925b118..707dd0a 100644
--- a/linden/indra/llui/lltextparser.cpp
+++ b/linden/indra/llui/lltextparser.cpp
@@ -1,6 +1,5 @@
1/** 1/**
2 * @file lltexteditor.cpp 2 * @file lltextparser.cpp
3 * @brief LLTextEditor base class
4 * 3 *
5 * $LicenseInfo:firstyear=2001&license=viewergpl$ 4 * $LicenseInfo:firstyear=2001&license=viewergpl$
6 * 5 *
@@ -32,6 +31,8 @@
32 31
33#include "linden_common.h" 32#include "linden_common.h"
34 33
34#include "lltextparser.h"
35
35#include "llsd.h" 36#include "llsd.h"
36#include "llsdserialize.h" 37#include "llsdserialize.h"
37#include "llerror.h" 38#include "llerror.h"
@@ -40,23 +41,13 @@
40#include "message.h" 41#include "message.h"
41#include "llmath.h" 42#include "llmath.h"
42#include "v4color.h" 43#include "v4color.h"
43#include "audioengine.h"
44#include "llwindow.h"
45#include "lldir.h" 44#include "lldir.h"
46 45
47#include "lltextparser.h"
48//#include "lltexttospeech.h"
49
50// Routines used for parsing text for TextParsers and html 46// Routines used for parsing text for TextParsers and html
51 47
52LLTextParser* LLTextParser::sInstance = NULL; 48LLTextParser* LLTextParser::sInstance = NULL;
53 49
54// 50//
55// Constants
56//
57const F32 SOUND_GAIN = 1.0f;
58
59//
60// Member Functions 51// Member Functions
61// 52//
62 53
@@ -76,38 +67,7 @@ LLTextParser* LLTextParser::getInstance()
76 return sInstance; 67 return sInstance;
77} 68}
78 69
79void LLTextParser::triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window) 70// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency.
80{
81// bool spoken=FALSE;
82 for (S32 i=0;i<mHighlights.size();i++)
83 {
84 if (findPattern(text,mHighlights[i]) >= 0 )
85 {
86 if(gAudiop)
87 {
88 if ((std::string)mHighlights[i]["sound_lluuid"] != LLUUID::null.asString())
89 {
90 gAudiop->triggerSound(mHighlights[i]["sound_lluuid"].asUUID(), agent_id, SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, position);
91 }
92/*
93 if (!spoken)
94 {
95 LLTextToSpeech* text_to_speech = NULL;
96 text_to_speech = LLTextToSpeech::getInstance();
97 spoken = text_to_speech->speak((LLString)mHighlights[i]["voice"],text);
98 }
99 */
100 }
101 if (mHighlights[i]["flash"])
102 {
103 if (viewer_window && viewer_window->getMinimized())
104 {
105 viewer_window->flashIcon(5.f);
106 }
107 }
108 }
109 }
110}
111 71
112S32 LLTextParser::findPattern(const std::string &text, LLSD highlight) 72S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
113{ 73{
diff --git a/linden/indra/llui/lltextparser.h b/linden/indra/llui/lltextparser.h
index d69e3a2..32343a2 100644
--- a/linden/indra/llui/lltextparser.h
+++ b/linden/indra/llui/lltextparser.h
@@ -34,12 +34,8 @@
34#ifndef LL_LLTEXTPARSER_H 34#ifndef LL_LLTEXTPARSER_H
35#define LL_LLTEXTPARSER_H 35#define LL_LLTEXTPARSER_H
36 36
37#include <vector> 37#include "llsd.h"
38#include "linden_common.h"
39 38
40#include "lltextparser.h"
41
42class LLSD;
43class LLUUID; 39class LLUUID;
44class LLVector3d; 40class LLVector3d;
45class LLColor4; 41class LLColor4;
@@ -59,7 +55,6 @@ public:
59 S32 findPattern(const std::string &text, LLSD highlight); 55 S32 findPattern(const std::string &text, LLSD highlight);
60 LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0); 56 LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0);
61 bool parseFullLineHighlights(const std::string &text, LLColor4 *color); 57 bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
62 void triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window);
63 58
64 std::string getFileName(); 59 std::string getFileName();
65 LLSD loadFromDisk(); 60 LLSD loadFromDisk();
diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp
index 57ce13c..75a4467 100644
--- a/linden/indra/llui/llui.cpp
+++ b/linden/indra/llui/llui.cpp
@@ -38,7 +38,6 @@
38#include <map> 38#include <map>
39 39
40// Linden library includes 40// Linden library includes
41#include "audioengine.h"
42#include "v2math.h" 41#include "v2math.h"
43#include "v4color.h" 42#include "v4color.h"
44#include "llrender.h" 43#include "llrender.h"
diff --git a/linden/indra/llui/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp
index 9d97312..3f4ab5e 100644
--- a/linden/indra/llui/lluictrl.cpp
+++ b/linden/indra/llui/lluictrl.cpp
@@ -39,54 +39,7 @@
39 39
40static LLRegisterWidget<LLUICtrl> r("ui_ctrl"); 40static LLRegisterWidget<LLUICtrl> r("ui_ctrl");
41 41
42LLFocusableElement::LLFocusableElement() 42// NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined.
43: mFocusLostCallback(NULL),
44 mFocusReceivedCallback(NULL),
45 mFocusChangedCallback(NULL),
46 mFocusCallbackUserData(NULL)
47{
48}
49
50//virtual
51LLFocusableElement::~LLFocusableElement()
52{
53}
54
55void LLFocusableElement::onFocusReceived()
56{
57 if( mFocusReceivedCallback )
58 {
59 mFocusReceivedCallback( this, mFocusCallbackUserData );
60 }
61 if( mFocusChangedCallback )
62 {
63 mFocusChangedCallback( this, mFocusCallbackUserData );
64 }
65}
66
67void LLFocusableElement::onFocusLost()
68{
69 if( mFocusLostCallback )
70 {
71 mFocusLostCallback( this, mFocusCallbackUserData );
72 }
73
74 if( mFocusChangedCallback )
75 {
76 mFocusChangedCallback( this, mFocusCallbackUserData );
77 }
78}
79
80BOOL LLFocusableElement::hasFocus() const
81{
82 return FALSE;
83}
84
85void LLFocusableElement::setFocus(BOOL b)
86{
87}
88
89
90 43
91LLUICtrl::LLUICtrl() : 44LLUICtrl::LLUICtrl() :
92 mCommitCallback(NULL), 45 mCommitCallback(NULL),
@@ -212,7 +165,7 @@ void LLUICtrl::onFocusReceived()
212 165
213 // find first view in hierarchy above new focus that is a LLUICtrl 166 // find first view in hierarchy above new focus that is a LLUICtrl
214 LLView* viewp = getParent(); 167 LLView* viewp = getParent();
215 LLUICtrl* last_focus = gFocusMgr.getLastKeyboardFocus(); 168 LLUICtrl* last_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getLastKeyboardFocus());
216 169
217 while (viewp && !viewp->isCtrl()) 170 while (viewp && !viewp->isCtrl())
218 { 171 {
@@ -590,6 +543,10 @@ void LLUICtrl::setDoubleClickCallback( void (*cb)(void*) )
590// virtual 543// virtual
591void LLUICtrl::setColor(const LLColor4& color) 544void LLUICtrl::setColor(const LLColor4& color)
592{ } 545{ }
546// virtual
547
548void LLUICtrl::setAlpha(F32 alpha)
549{ }
593 550
594// virtual 551// virtual
595void LLUICtrl::setMinValue(LLSD min_value) 552void LLUICtrl::setMinValue(LLSD min_value)
diff --git a/linden/indra/llui/lluictrl.h b/linden/indra/llui/lluictrl.h
index db41af8..be8e863 100644
--- a/linden/indra/llui/lluictrl.h
+++ b/linden/indra/llui/lluictrl.h
@@ -39,31 +39,8 @@
39#include "llsd.h" 39#include "llsd.h"
40 40
41 41
42class LLFocusableElement
43{
44 friend class LLFocusMgr; // allow access to focus change handlers
45public:
46 LLFocusableElement();
47 virtual ~LLFocusableElement();
48
49 virtual void setFocus( BOOL b );
50 virtual BOOL hasFocus() const;
51
52 void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; }
53 void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; }
54 void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; }
55
56protected:
57 virtual void onFocusReceived();
58 virtual void onFocusLost();
59 void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata );
60 void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata );
61 void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata );
62 void* mFocusCallbackUserData;
63};
64
65class LLUICtrl 42class LLUICtrl
66: public LLView, public LLFocusableElement 43: public LLView
67{ 44{
68public: 45public:
69 typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata); 46 typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
@@ -117,6 +94,7 @@ public:
117 virtual void clear(); 94 virtual void clear();
118 virtual void setDoubleClickCallback( void (*cb)(void*) ); 95 virtual void setDoubleClickCallback( void (*cb)(void*) );
119 virtual void setColor(const LLColor4& color); 96 virtual void setColor(const LLColor4& color);
97 virtual void setAlpha(F32 alpha);
120 virtual void setMinValue(LLSD min_value); 98 virtual void setMinValue(LLSD min_value);
121 virtual void setMaxValue(LLSD max_value); 99 virtual void setMaxValue(LLSD max_value);
122 100
diff --git a/linden/indra/llui/lluixmltags.h b/linden/indra/llui/lluixmltags.h
index 4166131..6bbb788 100644
--- a/linden/indra/llui/lluixmltags.h
+++ b/linden/indra/llui/lluixmltags.h
@@ -32,100 +32,100 @@
32#ifndef LL_UI_XML_TAGS_H 32#ifndef LL_UI_XML_TAGS_H
33#define LL_UI_XML_TAGS_H 33#define LL_UI_XML_TAGS_H
34 34
35const std::string 35char const* const LL_BUTTON_TAG = "button";
36 LL_BUTTON_TAG("button"), 36char const* const LL_UI_CTRL_LOCATE_TAG = "locate";
37 LL_UI_CTRL_LOCATE_TAG("locate"), 37char const* const LL_PAD_TAG = "pad";
38 LL_PAD_TAG("pad"), 38char const* const LL_CHECK_BOX_CTRL_TAG = "check_box";
39 LL_CHECK_BOX_CTRL_TAG("check_box"), 39char const* const LL_COMBO_BOX_TAG = "combo_box";
40 LL_COMBO_BOX_TAG("combo_box"), 40char const* const LL_DRAG_HANDLE_TOP_TAG = "drag_handle_top";
41 LL_DRAG_HANDLE_TOP_TAG("drag_handle_top"), 41char const* const LL_DRAG_HANDLE_LEFT_TAG = "drag_handle_left";
42 LL_DRAG_HANDLE_LEFT_TAG("drag_handle_left"), 42char const* const LL_FLOATER_TAG = "floater";
43 LL_FLOATER_TAG("floater"), 43char const* const LL_FLOATER_VIEW_TAG = "floater_view";
44 LL_FLOATER_VIEW_TAG("floater_view"), 44char const* const LL_MULTI_FLOATER_TAG = "multi_floater";
45 LL_MULTI_FLOATER_TAG("multi_floater"), 45char const* const LL_ICON_CTRL_TAG = "icon";
46 LL_ICON_CTRL_TAG("icon"), 46char const* const LL_LINE_EDITOR_TAG = "line_editor";
47 LL_LINE_EDITOR_TAG("line_editor"), 47char const* const LL_SEARCH_EDITOR_TAG = "search_editor";
48 LL_SEARCH_EDITOR_TAG("search_editor"), 48char const* const LL_MENU_ITEM_TAG = "menu_item";
49 LL_MENU_ITEM_TAG("menu_item"), 49char const* const LL_MENU_GL_TAG = "menu";
50 LL_MENU_GL_TAG("menu"), 50char const* const LL_MENU_BAR_GL_TAG = "menu_bar";
51 LL_MENU_BAR_GL_TAG("menu_bar"), 51char const* const LL_MENU_HOLDER_GL_TAG = "menu_holder";
52 LL_MENU_HOLDER_GL_TAG("menu_holder"), 52char const* const LL_PANEL_TAG = "panel";
53 LL_PANEL_TAG("panel"), 53char const* const LL_RADIO_GROUP_TAG = "radio_group";
54 LL_RADIO_GROUP_TAG("radio_group"), 54char const* const LL_RESIZE_BAR_TAG = "resize_bar";
55 LL_RESIZE_BAR_TAG("resize_bar"), 55char const* const LL_RESIZE_HANDLE_TAG = "resize_handle";
56 LL_RESIZE_HANDLE_TAG("resize_handle"), 56char const* const LL_SCROLLBAR_TAG = "scrollbar";
57 LL_SCROLLBAR_TAG("scrollbar"), 57char const* const LL_SCROLLABLE_CONTAINER_VIEW_TAG = "scroll_container";
58 LL_SCROLLABLE_CONTAINER_VIEW_TAG("scroll_container"), 58char const* const LL_SCROLL_LIST_CTRL_TAG = "scroll_list";
59 LL_SCROLL_LIST_CTRL_TAG("scroll_list"), 59char const* const LL_SLIDER_CTRL_TAG = "slider";
60 LL_SLIDER_CTRL_TAG("slider"), 60char const* const LL_SLIDER_TAG = "slider_bar";
61 LL_SLIDER_TAG("slider_bar"), 61char const* const LL_MULTI_SLIDER_CTRL_TAG = "multi_slider";
62 LL_MULTI_SLIDER_CTRL_TAG("multi_slider"), 62char const* const LL_MULTI_SLIDER_TAG = "multi_slider_bar";
63 LL_MULTI_SLIDER_TAG("multi_slider_bar"), 63char const* const LL_SPIN_CTRL_TAG = "spinner";
64 LL_SPIN_CTRL_TAG("spinner"), 64char const* const LL_TAB_CONTAINER_COMMON_TAG = "tab_container";
65 LL_TAB_CONTAINER_COMMON_TAG("tab_container"), 65char const* const LL_TEXT_BOX_TAG = "text";
66 LL_TEXT_BOX_TAG("text"), 66char const* const LL_TEXT_EDITOR_TAG = "text_editor";
67 LL_TEXT_EDITOR_TAG("text_editor"), 67char const* const LL_VIEW_BORDER_TAG = "view_border";
68 LL_VIEW_BORDER_TAG("view_border"), 68char const* const LL_COLOR_SWATCH_TAG = "color_swatch";
69 LL_COLOR_SWATCH_TAG("color_swatch"), 69char const* const LL_INVENTORY_PANEL_TAG = "inventory_panel";
70 LL_INVENTORY_PANEL_TAG("inventory_panel"), 70char const* const LL_NAME_EDITOR_TAG = "name_editor";
71 LL_NAME_EDITOR_TAG("name_editor"), 71char const* const LL_NAME_LIST_TAG = "name_list";
72 LL_NAME_LIST_TAG("name_list"), 72char const* const LL_TEXTURE_PICKER_TAG = "texture_picker";
73 LL_TEXTURE_PICKER_TAG("texture_picker"), 73char const* const LL_VOLUME_SLIDER_CTRL_TAG = "volume_slider";
74 LL_VOLUME_SLIDER_CTRL_TAG("volume_slider"), 74char const* const LL_WEB_BROWSER_CTRL_TAG = "web_browser";
75 LL_WEB_BROWSER_CTRL_TAG("web_browser"), 75char const* const LL_STAT_VIEW_TAG = "stat_view";
76 LL_STAT_VIEW_TAG("stat_view"), 76char const* const LL_PROGRESS_VIEW_TAG = "progress_view";
77 LL_PROGRESS_VIEW_TAG("progress_view"), 77char const* const LL_STAT_BAR_TAG = "stat_bar";
78 LL_STAT_BAR_TAG("stat_bar"), 78char const* const LL_STATUS_BAR_TAG = "status_bar";
79 LL_STATUS_BAR_TAG("status_bar"), 79char const* const LL_VIEWER_TEXT_EDITOR_TAG = "viewer_text_editor";
80 LL_VIEWER_TEXT_EDITOR_TAG("viewer_text_editor"), 80char const* const LL_TALK_VIEW_TAG = "talk_view";
81 LL_TALK_VIEW_TAG("talk_view"), 81char const* const LL_COLOR_SWATCH_CTRL_TAG = "color_swatch";
82 LL_COLOR_SWATCH_CTRL_TAG("color_swatch"), 82char const* const LL_GL_TEX_MEM_BAR_TAG = "tex_mem_bar";
83 LL_GL_TEX_MEM_BAR_TAG("tex_mem_bar"), 83char const* const LL_TEXTURE_CTRL_TAG = "texture_picker";
84 LL_TEXTURE_CTRL_TAG("texture_picker"), 84char const* const LL_TEXTURE_VIEW_TAG = "texture_view";
85 LL_TEXTURE_VIEW_TAG("texture_view"), 85char const* const LL_NAME_LIST_CTRL_TAG = "name_list";
86 LL_NAME_LIST_CTRL_TAG("name_list"), 86char const* const LL_STAT_GRAPH_TAG = "stat_graph";
87 LL_STAT_GRAPH_TAG("stat_graph"), 87char const* const LL_DROP_TARGET_TAG = "drop_target";
88 LL_DROP_TARGET_TAG("drop_target"), 88char const* const LL_OVERLAY_BAR_TAG = "overlay_bar";
89 LL_OVERLAY_BAR_TAG("overlay_bar"), 89char const* const LL_NET_MAP_TAG = "net_map";
90 LL_NET_MAP_TAG("net_map"), 90char const* const LL_HUD_VIEW_TAG = "hud_view";
91 LL_HUD_VIEW_TAG("hud_view"), 91char const* const LL_MEMORY_VIEW_TAG = "memory_view";
92 LL_MEMORY_VIEW_TAG("memory_view"), 92char const* const LL_MEDIA_REMOTE_CTRL_TAG = "media_remote";
93 LL_MEDIA_REMOTE_CTRL_TAG("media_remote"), 93char const* const LL_MORPH_VIEW_TAG = "morph_view";
94 LL_MORPH_VIEW_TAG("morph_view"), 94char const* const LL_FRAME_STAT_VIEW_TAG = "frame_stat_view";
95 LL_FRAME_STAT_VIEW_TAG("frame_stat_view"), 95char const* const LL_FOLDER_VIEW_TAG = "folder_view";
96 LL_FOLDER_VIEW_TAG("folder_view"), 96char const* const LL_SNAPSHOT_LIVE_PREVIEW_TAG = "snapshot_preview";
97 LL_SNAPSHOT_LIVE_PREVIEW_TAG("snapshot_preview"), 97char const* const LL_HOVER_VIEW_TAG = "hover_view";
98 LL_HOVER_VIEW_TAG("hover_view"), 98char const* const LL_VELOCITY_BAR_TAG = "velocity_bar";
99 LL_VELOCITY_BAR_TAG("velocity_bar"), 99char const* const LL_PERMISSIONS_VIEW_TAG = "permissions_view";
100 LL_PERMISSIONS_VIEW_TAG("permissions_view"), 100char const* const LL_SCROLLING_PANEL_LIST_TAG = "scrolling_panel_list";
101 LL_SCROLLING_PANEL_LIST_TAG("scrolling_panel_list"), 101char const* const LL_CONTAINER_VIEW_TAG = "container_view";
102 LL_CONTAINER_VIEW_TAG("container_view"), 102char const* const LL_CONSOLE_TAG = "console";
103 LL_CONSOLE_TAG("console"), 103char const* const LL_DEBUG_VIEW_TAG = "debug_view";
104 LL_DEBUG_VIEW_TAG("debug_view"), 104char const* const LL_AUDIOSTATUS_TAG = "audio_status";
105 LL_AUDIOSTATUS_TAG("audio_status"), 105char const* const LL_FAST_TIMER_VIEW_TAG = "fast_timer_view";
106 LL_FAST_TIMER_VIEW_TAG("fast_timer_view"), 106char const* const LL_MENU_ITEM_TEAR_OFF_GL_TAG = "tearoff_menu";
107 LL_MENU_ITEM_TEAR_OFF_GL_TAG("tearoff_menu"), 107char const* const LL_MENU_ITEM_BLANK_GL_TAG = "menu_item_blank";
108 LL_MENU_ITEM_BLANK_GL_TAG("menu_item_blank"), 108char const* const LL_MENU_ITEM_CALL_GL_TAG = "menu_item_call";
109 LL_MENU_ITEM_CALL_GL_TAG("menu_item_call"), 109char const* const LL_MENU_ITEM_CHECK_GL_TAG = "menu_item_check";
110 LL_MENU_ITEM_CHECK_GL_TAG("menu_item_check"), 110char const* const LL_MENU_ITEM_BRANCH_GL_TAG = "menu_item_branch";
111 LL_MENU_ITEM_BRANCH_GL_TAG("menu_item_branch"), 111char const* const LL_MENU_ITEM_BRANCH_DOWN_GL_TAG = "menu_item_branch_down";
112 LL_MENU_ITEM_BRANCH_DOWN_GL_TAG("menu_item_branch_down"), 112char const* const LL_PIE_MENU_BRANCH_TAG = "pie_menu_branch";
113 LL_PIE_MENU_BRANCH_TAG("pie_menu_branch"), 113char const* const LL_PIE_MENU_TAG = "pie_menu";
114 LL_PIE_MENU_TAG("pie_menu"), 114char const* const LL_MENU_ITEM_SEPARATOR_GL_TAG = "menu_item_separator";
115 LL_MENU_ITEM_SEPARATOR_GL_TAG("menu_item_separator"), 115char const* const LL_MENU_ITEM_VERTICAL_SEPARATOR_GL_TAG = "menu_item_vertical_separator";
116 LL_MENU_ITEM_VERTICAL_SEPARATOR_GL_TAG("menu_item_vertical_separator"), 116char const* const LL_ROOT_VIEW_TAG = "root_view";
117 LL_ROOT_VIEW_TAG("root_view"), 117char const* const LL_FOLDER_VIEW_ITEM_TAG = "folder_item";
118 LL_FOLDER_VIEW_ITEM_TAG("folder_item"), 118char const* const LL_FOLDER_VIEW_FOLDER_TAG = "folder";
119 LL_FOLDER_VIEW_FOLDER_TAG("folder"), 119char const* const LL_TEXTURE_BAR_TAG = "texture_bar";
120 LL_TEXTURE_BAR_TAG("texture_bar"), 120char const* const LL_JOYSTICK_SLIDE = "joystick_slide";
121 LL_JOYSTICK_SLIDE("joystick_slide"), 121char const* const LL_JOYSTICK_TURN = "joystick_turn";
122 LL_JOYSTICK_TURN("joystick_turn"), 122char const* const LL_GROUP_DROP_TARGET_TAG = "group_drop_target";
123 LL_GROUP_DROP_TARGET_TAG("group_drop_target"), 123char const* const LL_LAYOUT_STACK_TAG = "layout_stack";
124 LL_LAYOUT_STACK_TAG("layout_stack"), 124char const* const LL_LAYOUT_PANEL_TAG = "layout_panel";
125 LL_LAYOUT_PANEL_TAG("layout_panel"), 125char const* const LL_FLYOUT_BUTTON_TAG = "flyout_button";
126 LL_FLYOUT_BUTTON_TAG("flyout_button"), 126char const* const LL_FLYOUT_BUTTON_ITEM_TAG = "flyout_button_item";
127 LL_FLYOUT_BUTTON_ITEM_TAG("flyout_button_item"), 127char const* const LL_SIMPLE_TEXT_EDITOR_TAG = "simple_text_editor";
128 LL_SIMPLE_TEXT_EDITOR_TAG("simple_text_editor"), 128char const* const LL_RADIO_ITEM_TAG = "radio_item";
129 LL_RADIO_ITEM_TAG("radio_item"), 129char const* const LL_PROGRESS_BAR_TAG = "progress_bar";
130 LL_PROGRESS_BAR_TAG("progress_bar"); 130
131#endif 131#endif
diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp
index 8de376f..507c5f5 100644
--- a/linden/indra/llui/llview.cpp
+++ b/linden/indra/llui/llview.cpp
@@ -136,11 +136,6 @@ LLView::~LLView()
136{ 136{
137 //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl; 137 //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl;
138// llassert(LLView::sIsDrawing == FALSE); 138// llassert(LLView::sIsDrawing == FALSE);
139 if( gFocusMgr.getKeyboardFocus() == this )
140 {
141 llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl;
142 gFocusMgr.removeKeyboardFocusWithoutCallback( this );
143 }
144 139
145 if( hasMouseCapture() ) 140 if( hasMouseCapture() )
146 { 141 {
@@ -965,6 +960,19 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
965 return handled; 960 return handled;
966} 961}
967 962
963BOOL LLView::handleHScrollWheel(S32 x, S32 y, S32 clicks)
964{
965 BOOL handled = FALSE;
966 if( getVisible() && getEnabled() )
967 {
968 handled = childrenHandleHScrollWheel( x, y, clicks ) != NULL;
969 if( !handled && blockMouseEvent(x, y) )
970 {
971 handled = TRUE;
972 }
973 }
974 return handled;
975}
968BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask) 976BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
969{ 977{
970 BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; 978 BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
@@ -1037,6 +1045,34 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
1037 return handled_view; 1045 return handled_view;
1038} 1046}
1039 1047
1048LLView* LLView::childrenHandleHScrollWheel(S32 x, S32 y, S32 clicks)
1049{
1050 LLView* handled_view = NULL;
1051 if (getVisible() && getEnabled() )
1052 {
1053 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
1054 {
1055 LLView* viewp = *child_it;
1056 S32 local_x = x - viewp->getRect().mLeft;
1057 S32 local_y = y - viewp->getRect().mBottom;
1058 if (viewp->pointInView(local_x, local_y)
1059 && viewp->getVisible()
1060 && viewp->getEnabled()
1061 && viewp->handleHScrollWheel( local_x, local_y, clicks ))
1062 {
1063 if (sDebugMouseHandling)
1064 {
1065 sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
1066 }
1067
1068 handled_view = viewp;
1069 break;
1070 }
1071 }
1072 }
1073 return handled_view;
1074}
1075
1040LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) 1076LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
1041{ 1077{
1042 LLView* handled_view = NULL; 1078 LLView* handled_view = NULL;
@@ -1327,7 +1363,7 @@ void LLView::draw()
1327 LLRect screenRect; 1363 LLRect screenRect;
1328 1364
1329 // draw focused control on top of everything else 1365 // draw focused control on top of everything else
1330 LLView* focus_view = gFocusMgr.getKeyboardFocus(); 1366 LLUICtrl* focus_view = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
1331 if (focus_view && focus_view->getParent() != this) 1367 if (focus_view && focus_view->getParent() != this)
1332 { 1368 {
1333 focus_view = NULL; 1369 focus_view = NULL;
@@ -1547,7 +1583,7 @@ void LLView::updateBoundingRect()
1547 1583
1548 LLRect child_bounding_rect = childp->getBoundingRect(); 1584 LLRect child_bounding_rect = childp->getBoundingRect();
1549 1585
1550 if (local_bounding_rect.isNull()) 1586 if (local_bounding_rect.isEmpty())
1551 { 1587 {
1552 // start out with bounding rect equal to first visible child's bounding rect 1588 // start out with bounding rect equal to first visible child's bounding rect
1553 local_bounding_rect = child_bounding_rect; 1589 local_bounding_rect = child_bounding_rect;
@@ -1555,7 +1591,7 @@ void LLView::updateBoundingRect()
1555 else 1591 else
1556 { 1592 {
1557 // accumulate non-null children rectangles 1593 // accumulate non-null children rectangles
1558 if (!child_bounding_rect.isNull()) 1594 if (!child_bounding_rect.isEmpty())
1559 { 1595 {
1560 local_bounding_rect.unionWith(child_bounding_rect); 1596 local_bounding_rect.unionWith(child_bounding_rect);
1561 } 1597 }
diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h
index 7e09dfa..9243f4f 100644
--- a/linden/indra/llui/llview.h
+++ b/linden/indra/llui/llview.h
@@ -53,6 +53,7 @@
53#include "stdenums.h" 53#include "stdenums.h"
54#include "lluistring.h" 54#include "lluistring.h"
55#include "llcursortypes.h" 55#include "llcursortypes.h"
56#include "llfocusmgr.h"
56 57
57const U32 FOLLOWS_NONE = 0x00; 58const U32 FOLLOWS_NONE = 0x00;
58const U32 FOLLOWS_LEFT = 0x01; 59const U32 FOLLOWS_LEFT = 0x01;
@@ -207,7 +208,7 @@ public:
207 } 208 }
208}; 209};
209 210
210class LLView : public LLMouseHandler, public LLMortician 211class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElement
211{ 212{
212 213
213public: 214public:
@@ -398,9 +399,11 @@ public:
398 virtual BOOL canSnapTo(const LLView* other_view); 399 virtual BOOL canSnapTo(const LLView* other_view);
399 400
400 virtual void snappedTo(const LLView* snap_view); 401 virtual void snappedTo(const LLView* snap_view);
402
403 // inherited from LLFocusableElement
404 /* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
405 /* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
401 406
402 virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
403 virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
404 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, 407 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
405 EDragAndDropType cargo_type, 408 EDragAndDropType cargo_type,
406 void* cargo_data, 409 void* cargo_data,
@@ -421,8 +424,9 @@ public:
421 BOOL getSaveToXML() const { return mSaveToXML; } 424 BOOL getSaveToXML() const { return mSaveToXML; }
422 void setSaveToXML(BOOL b) { mSaveToXML = b; } 425 void setSaveToXML(BOOL b) { mSaveToXML = b; }
423 426
424 virtual void onFocusLost(); 427 // inherited from LLFocusableElement
425 virtual void onFocusReceived(); 428 /* virtual */ void onFocusLost();
429 /* virtual */ void onFocusReceived();
426 430
427 typedef enum e_hit_test_type 431 typedef enum e_hit_test_type
428 { 432 {
@@ -469,6 +473,7 @@ public:
469 /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); 473 /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
470 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); 474 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
471 /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 475 /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
476 /*virtual*/ BOOL handleHScrollWheel(S32 x, S32 y, S32 clicks);
472 /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); 477 /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
473 /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); 478 /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
474 /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it. 479 /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it.
@@ -609,6 +614,7 @@ protected:
609 LLView* childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask); 614 LLView* childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask);
610 LLView* childrenHandleDoubleClick(S32 x, S32 y, MASK mask); 615 LLView* childrenHandleDoubleClick(S32 x, S32 y, MASK mask);
611 LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks); 616 LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
617 LLView* childrenHandleHScrollWheel(S32 x, S32 y, S32 clicks);
612 LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask); 618 LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
613 LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask); 619 LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
614 620