aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui
diff options
context:
space:
mode:
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