aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llui')
-rw-r--r--linden/indra/llui/files.lst1
-rw-r--r--linden/indra/llui/llalertdialog.cpp1
-rw-r--r--linden/indra/llui/llalertdialog.h1
-rw-r--r--linden/indra/llui/llbutton.cpp63
-rw-r--r--linden/indra/llui/llbutton.h12
-rw-r--r--linden/indra/llui/llcallbackmap.h1
-rw-r--r--linden/indra/llui/llcheckboxctrl.cpp3
-rw-r--r--linden/indra/llui/llcheckboxctrl.h1
-rw-r--r--linden/indra/llui/llclipboard.cpp1
-rw-r--r--linden/indra/llui/llclipboard.h1
-rw-r--r--linden/indra/llui/llcombobox.cpp292
-rw-r--r--linden/indra/llui/llcombobox.h30
-rw-r--r--linden/indra/llui/llctrlselectioninterface.cpp1
-rw-r--r--linden/indra/llui/llctrlselectioninterface.h1
-rw-r--r--linden/indra/llui/lldraghandle.cpp9
-rw-r--r--linden/indra/llui/lldraghandle.h1
-rw-r--r--linden/indra/llui/lleditmenuhandler.cpp1
-rw-r--r--linden/indra/llui/lleditmenuhandler.h1
-rw-r--r--linden/indra/llui/llfloater.cpp73
-rw-r--r--linden/indra/llui/llfloater.h1
-rw-r--r--linden/indra/llui/llfocusmgr.cpp70
-rw-r--r--linden/indra/llui/llfocusmgr.h17
-rw-r--r--linden/indra/llui/llhtmlhelp.h40
-rw-r--r--linden/indra/llui/lliconctrl.cpp1
-rw-r--r--linden/indra/llui/lliconctrl.h1
-rw-r--r--linden/indra/llui/llkeywords.cpp1
-rw-r--r--linden/indra/llui/llkeywords.h1
-rw-r--r--linden/indra/llui/lllineeditor.cpp35
-rw-r--r--linden/indra/llui/lllineeditor.h8
-rwxr-xr-xlinden/indra/llui/llmemberlistener.h1
-rw-r--r--linden/indra/llui/llmenugl.cpp31
-rw-r--r--linden/indra/llui/llmenugl.h2
-rw-r--r--linden/indra/llui/llmodaldialog.cpp21
-rw-r--r--linden/indra/llui/llmodaldialog.h1
-rw-r--r--linden/indra/llui/llpanel.cpp1
-rw-r--r--linden/indra/llui/llpanel.h1
-rw-r--r--linden/indra/llui/llradiogroup.cpp1
-rw-r--r--linden/indra/llui/llradiogroup.h1
-rw-r--r--linden/indra/llui/llresizebar.cpp130
-rw-r--r--linden/indra/llui/llresizebar.h5
-rw-r--r--linden/indra/llui/llresizehandle.cpp118
-rw-r--r--linden/indra/llui/llresizehandle.h5
-rw-r--r--linden/indra/llui/llresmgr.cpp5
-rw-r--r--linden/indra/llui/llresmgr.h1
-rw-r--r--linden/indra/llui/llrootview.cpp1
-rw-r--r--linden/indra/llui/llrootview.h1
-rw-r--r--linden/indra/llui/llscrollbar.cpp11
-rw-r--r--linden/indra/llui/llscrollbar.h1
-rw-r--r--linden/indra/llui/llscrollcontainer.cpp3
-rw-r--r--linden/indra/llui/llscrollcontainer.h1
-rw-r--r--linden/indra/llui/llscrollingpanellist.cpp1
-rw-r--r--linden/indra/llui/llscrollingpanellist.h1
-rw-r--r--linden/indra/llui/llscrolllistctrl.cpp972
-rw-r--r--linden/indra/llui/llscrolllistctrl.h163
-rw-r--r--linden/indra/llui/llslider.cpp13
-rw-r--r--linden/indra/llui/llslider.h1
-rw-r--r--linden/indra/llui/llsliderctrl.cpp5
-rw-r--r--linden/indra/llui/llsliderctrl.h1
-rw-r--r--linden/indra/llui/llspinctrl.cpp29
-rw-r--r--linden/indra/llui/llspinctrl.h1
-rw-r--r--linden/indra/llui/llstyle.cpp1
-rw-r--r--linden/indra/llui/llstyle.h1
-rw-r--r--linden/indra/llui/lltabcontainer.cpp141
-rw-r--r--linden/indra/llui/lltabcontainer.h5
-rw-r--r--linden/indra/llui/lltabcontainervertical.cpp9
-rw-r--r--linden/indra/llui/lltabcontainervertical.h1
-rw-r--r--linden/indra/llui/lltextbox.cpp9
-rw-r--r--linden/indra/llui/lltextbox.h1
-rw-r--r--linden/indra/llui/lltexteditor.cpp42
-rw-r--r--linden/indra/llui/lltexteditor.h8
-rw-r--r--linden/indra/llui/llui.cpp20
-rw-r--r--linden/indra/llui/llui.h4
-rw-r--r--linden/indra/llui/llui.vcproj3
-rw-r--r--linden/indra/llui/lluiconstants.h1
-rw-r--r--linden/indra/llui/lluictrl.cpp14
-rw-r--r--linden/indra/llui/lluictrl.h3
-rw-r--r--linden/indra/llui/lluictrlfactory.cpp5
-rw-r--r--linden/indra/llui/lluictrlfactory.h1
-rwxr-xr-xlinden/indra/llui/lluistring.cpp1
-rwxr-xr-xlinden/indra/llui/lluistring.h1
-rw-r--r--linden/indra/llui/lluixmltags.h1
-rw-r--r--linden/indra/llui/llundo.cpp1
-rw-r--r--linden/indra/llui/llundo.h1
-rw-r--r--linden/indra/llui/llview.cpp39
-rw-r--r--linden/indra/llui/llview.h11
-rw-r--r--linden/indra/llui/llviewborder.cpp1
-rw-r--r--linden/indra/llui/llviewborder.h1
-rw-r--r--linden/indra/llui/llviewquery.cpp1
-rw-r--r--linden/indra/llui/llviewquery.h1
89 files changed, 1753 insertions, 773 deletions
diff --git a/linden/indra/llui/files.lst b/linden/indra/llui/files.lst
index 96bb170..5a62573 100644
--- a/linden/indra/llui/files.lst
+++ b/linden/indra/llui/files.lst
@@ -8,6 +8,7 @@ llui/lldraghandle.cpp
8llui/lleditmenuhandler.cpp 8llui/lleditmenuhandler.cpp
9llui/llfloater.cpp 9llui/llfloater.cpp
10llui/llfocusmgr.cpp 10llui/llfocusmgr.cpp
11llui/llhtmlhelp.h
11llui/lliconctrl.cpp 12llui/lliconctrl.cpp
12llui/llkeywords.cpp 13llui/llkeywords.cpp
13llui/lllineeditor.cpp 14llui/lllineeditor.cpp
diff --git a/linden/indra/llui/llalertdialog.cpp b/linden/indra/llui/llalertdialog.cpp
index 6523e44..547efae 100644
--- a/linden/indra/llui/llalertdialog.cpp
+++ b/linden/indra/llui/llalertdialog.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llalertdialog.h b/linden/indra/llui/llalertdialog.h
index 1085f23..d389236 100644
--- a/linden/indra/llui/llalertdialog.h
+++ b/linden/indra/llui/llalertdialog.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp
index 41c2269..d35dd57 100644
--- a/linden/indra/llui/llbutton.cpp
+++ b/linden/indra/llui/llbutton.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -65,7 +66,9 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co
65 mMouseUpCallback( NULL ), 66 mMouseUpCallback( NULL ),
66 mHeldDownCallback( NULL ), 67 mHeldDownCallback( NULL ),
67 mGLFont( NULL ), 68 mGLFont( NULL ),
69 mMouseDownFrame( 0 ),
68 mHeldDownDelay( 0.5f ), // seconds until held-down callback is called 70 mHeldDownDelay( 0.5f ), // seconds until held-down callback is called
71 mHeldDownFrameDelay( 0 ),
69 mImageUnselected( NULL ), 72 mImageUnselected( NULL ),
70 mImageSelected( NULL ), 73 mImageSelected( NULL ),
71 mImageHoverSelected( NULL ), 74 mImageHoverSelected( NULL ),
@@ -118,7 +121,9 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
118 mMouseUpCallback( NULL ), 121 mMouseUpCallback( NULL ),
119 mHeldDownCallback( NULL ), 122 mHeldDownCallback( NULL ),
120 mGLFont( NULL ), 123 mGLFont( NULL ),
124 mMouseDownFrame( 0 ),
121 mHeldDownDelay( 0.5f ), // seconds until held-down callback is called 125 mHeldDownDelay( 0.5f ), // seconds until held-down callback is called
126 mHeldDownFrameDelay( 0 ),
122 mImageUnselected( NULL ), 127 mImageUnselected( NULL ),
123 mImageSelected( NULL ), 128 mImageSelected( NULL ),
124 mImageHoverSelected( NULL ), 129 mImageHoverSelected( NULL ),
@@ -215,9 +220,9 @@ void LLButton::init(void (*click_callback)(void*), void *callback_data, const LL
215 220
216LLButton::~LLButton() 221LLButton::~LLButton()
217{ 222{
218 if( this == gFocusMgr.getMouseCapture() ) 223 if( hasMouseCapture() )
219 { 224 {
220 gFocusMgr.setMouseCapture( NULL, NULL ); 225 gFocusMgr.setMouseCapture( NULL );
221 } 226 }
222} 227}
223 228
@@ -303,7 +308,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
303BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) 308BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
304{ 309{
305 // Route future Mouse messages here preemptively. (Release on mouse up.) 310 // Route future Mouse messages here preemptively. (Release on mouse up.)
306 gFocusMgr.setMouseCapture( this, &LLButton::onMouseCaptureLost ); 311 gFocusMgr.setMouseCapture( this );
307 312
308 if (hasTabStop() && !getIsChrome()) 313 if (hasTabStop() && !getIsChrome())
309 { 314 {
@@ -316,6 +321,7 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
316 } 321 }
317 322
318 mMouseDownTimer.start(); 323 mMouseDownTimer.start();
324 mMouseDownFrame = LLFrameTimer::getFrameCount();
319 325
320 if (mSoundFlags & MOUSE_DOWN) 326 if (mSoundFlags & MOUSE_DOWN)
321 { 327 {
@@ -329,19 +335,17 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
329BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) 335BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
330{ 336{
331 // We only handle the click if the click both started and ended within us 337 // We only handle the click if the click both started and ended within us
332 if( this == gFocusMgr.getMouseCapture() ) 338 if( hasMouseCapture() )
333 { 339 {
340 // Always release the mouse
341 gFocusMgr.setMouseCapture( NULL );
342
334 // Regardless of where mouseup occurs, handle callback 343 // Regardless of where mouseup occurs, handle callback
335 if (mMouseUpCallback) 344 if (mMouseUpCallback)
336 { 345 {
337 (*mMouseUpCallback)(mCallbackUserData); 346 (*mMouseUpCallback)(mCallbackUserData);
338 } 347 }
339 348
340 mMouseDownTimer.stop();
341
342 // Always release the mouse
343 gFocusMgr.setMouseCapture( NULL, NULL );
344
345 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. 349 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
346 // If mouseup in the widget, it's been clicked 350 // If mouseup in the widget, it's been clicked
347 if (pointInView(x, y)) 351 if (pointInView(x, y))
@@ -356,6 +360,9 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
356 (*mClickedCallback)( mCallbackUserData ); 360 (*mClickedCallback)( mCallbackUserData );
357 } 361 }
358 } 362 }
363
364 mMouseDownTimer.stop();
365 mMouseDownTimer.reset();
359 } 366 }
360 367
361 return TRUE; 368 return TRUE;
@@ -375,14 +382,14 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
375 if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback) 382 if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback)
376 { 383 {
377 F32 elapsed = mMouseDownTimer.getElapsedTimeF32(); 384 F32 elapsed = mMouseDownTimer.getElapsedTimeF32();
378 if( mHeldDownDelay < elapsed ) 385 if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= LLFrameTimer::getFrameCount() - mMouseDownFrame)
379 { 386 {
380 mHeldDownCallback( mCallbackUserData ); 387 mHeldDownCallback( mCallbackUserData );
381 } 388 }
382 } 389 }
383 390
384 // We only handle the click if the click both started and ended within us 391 // We only handle the click if the click both started and ended within us
385 if( this == gFocusMgr.getMouseCapture() ) 392 if( hasMouseCapture() )
386 { 393 {
387 handled = TRUE; 394 handled = TRUE;
388 } 395 }
@@ -431,7 +438,7 @@ void LLButton::draw()
431 cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); 438 cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
432 screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); 439 screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
433 440
434 BOOL pressed = pressed_by_keyboard || (this == gFocusMgr.getMouseCapture() && pointInView(local_mouse_x, local_mouse_y)); 441 BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y));
435 442
436 BOOL display_state = FALSE; 443 BOOL display_state = FALSE;
437 if( pressed ) 444 if( pressed )
@@ -819,11 +826,10 @@ void LLButton::setHoverImages( const LLString& image_name, const LLString& selec
819 setImageHoverSelected(selected_name); 826 setImageHoverSelected(selected_name);
820} 827}
821 828
822// static 829void LLButton::onMouseCaptureLost()
823void LLButton::onMouseCaptureLost( LLMouseHandler* old_captor )
824{ 830{
825 LLButton* self = (LLButton*) old_captor; 831 mMouseDownTimer.stop();
826 self->mMouseDownTimer.stop(); 832 mMouseDownTimer.reset();
827} 833}
828 834
829//------------------------------------------------------------------------- 835//-------------------------------------------------------------------------
@@ -947,6 +953,19 @@ LLXMLNodePtr LLButton::getXML(bool save_children) const
947 return node; 953 return node;
948} 954}
949 955
956void clicked_help(void* data)
957{
958 LLButton* self = (LLButton*)data;
959 if (!self) return;
960
961 if (!LLUI::sHtmlHelp)
962 {
963 return;
964 }
965
966 LLUI::sHtmlHelp->show(self->getHelpURL());
967}
968
950// static 969// static
951LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) 970LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
952{ 971{
@@ -1023,9 +1042,21 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
1023 { 1042 {
1024 button->setLabelSelected(node->getTextContents()); 1043 button->setLabelSelected(node->getTextContents());
1025 } 1044 }
1045
1046 if (node->hasAttribute("help_url"))
1047 {
1048 LLString help_url;
1049 node->getAttributeString("help_url",help_url);
1050 button->setHelpURLCallback(help_url);
1051 }
1026 1052
1027 button->initFromXML(node, parent); 1053 button->initFromXML(node, parent);
1028 1054
1029 return button; 1055 return button;
1030} 1056}
1031 1057
1058void LLButton::setHelpURLCallback(std::string help_url)
1059{
1060 mHelpURL = help_url;
1061 setClickedCallback(clicked_help,this);
1062}
diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h
index fe906a6..44e8776 100644
--- a/linden/indra/llui/llbutton.h
+++ b/linden/indra/llui/llbutton.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -94,6 +95,8 @@ public:
94 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 95 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
95 virtual void draw(); 96 virtual void draw();
96 97
98 virtual void onMouseCaptureLost();
99
97 // HACK: "committing" a button is the same as clicking on it. 100 // HACK: "committing" a button is the same as clicking on it.
98 virtual void onCommit(); 101 virtual void onCommit();
99 102
@@ -104,7 +107,7 @@ public:
104 void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button 107 void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button
105 void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON 108 void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON
106 void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button 109 void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button
107 void setHeldDownDelay( F32 seconds) { mHeldDownDelay = seconds; } 110 void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; }
108 111
109 F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } 112 F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); }
110 113
@@ -159,7 +162,6 @@ public:
159 void setBorderEnabled(BOOL b) { mBorderEnabled = b; } 162 void setBorderEnabled(BOOL b) { mBorderEnabled = b; }
160 163
161 static void onHeldDown(void *userdata); // to be called by gIdleCallbacks 164 static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
162 static void onMouseCaptureLost(LLMouseHandler* old_captor);
163 165
164 void setFixedBorder(S32 width, S32 height) { mFixedWidth = width; mFixedHeight = height; } 166 void setFixedBorder(S32 width, S32 height) { mFixedWidth = width; mFixedHeight = height; }
165 void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } 167 void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; }
@@ -181,6 +183,8 @@ public:
181 void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } 183 void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
182 BOOL getCommitOnReturn() { return mCommitOnReturn; } 184 BOOL getCommitOnReturn() { return mCommitOnReturn; }
183 185
186 void setHelpURLCallback(std::string help_url);
187 LLString getHelpURL() { return mHelpURL; }
184protected: 188protected:
185 virtual void drawBorder(const LLColor4& color, S32 size); 189 virtual void drawBorder(const LLColor4& color, S32 size);
186 190
@@ -194,7 +198,9 @@ protected:
194 const LLFontGL *mGLFont; 198 const LLFontGL *mGLFont;
195 199
196 LLFrameTimer mMouseDownTimer; 200 LLFrameTimer mMouseDownTimer;
201 S32 mMouseDownFrame;
197 F32 mHeldDownDelay; // seconds, after which held-down callbacks get called 202 F32 mHeldDownDelay; // seconds, after which held-down callbacks get called
203 S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called
198 204
199 LLPointer<LLImageGL> mImageUnselected; 205 LLPointer<LLImageGL> mImageUnselected;
200 LLUIString mUnselectedLabel; 206 LLUIString mUnselectedLabel;
@@ -259,6 +265,8 @@ protected:
259 BOOL mNeedsHighlight; 265 BOOL mNeedsHighlight;
260 BOOL mCommitOnReturn; 266 BOOL mCommitOnReturn;
261 267
268 LLString mHelpURL;
269
262 LLPointer<LLImageGL> mImagep; 270 LLPointer<LLImageGL> mImagep;
263 271
264 static LLFrameTimer sFlashingTimer; 272 static LLFrameTimer sFlashingTimer;
diff --git a/linden/indra/llui/llcallbackmap.h b/linden/indra/llui/llcallbackmap.h
index 3a0e3b3..4a47f60 100644
--- a/linden/indra/llui/llcallbackmap.h
+++ b/linden/indra/llui/llcallbackmap.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llcheckboxctrl.cpp b/linden/indra/llui/llcheckboxctrl.cpp
index 9f11ff8..5f3350e 100644
--- a/linden/indra/llui/llcheckboxctrl.cpp
+++ b/linden/indra/llui/llcheckboxctrl.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -175,7 +176,7 @@ void LLCheckBoxCtrl::onCommit()
175 176
176void LLCheckBoxCtrl::setEnabled(BOOL b) 177void LLCheckBoxCtrl::setEnabled(BOOL b)
177{ 178{
178 LLUICtrl::setEnabled(b); 179 LLView::setEnabled(b);
179 mButton->setEnabled(b); 180 mButton->setEnabled(b);
180} 181}
181 182
diff --git a/linden/indra/llui/llcheckboxctrl.h b/linden/indra/llui/llcheckboxctrl.h
index 77dc39d..1b895cb 100644
--- a/linden/indra/llui/llcheckboxctrl.h
+++ b/linden/indra/llui/llcheckboxctrl.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llclipboard.cpp b/linden/indra/llui/llclipboard.cpp
index d7c25fb..19f0188 100644
--- a/linden/indra/llui/llclipboard.cpp
+++ b/linden/indra/llui/llclipboard.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llclipboard.h b/linden/indra/llui/llclipboard.h
index 00bd73e..dc4cb32 100644
--- a/linden/indra/llui/llclipboard.h
+++ b/linden/indra/llui/llclipboard.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llcombobox.cpp b/linden/indra/llui/llcombobox.cpp
index 7c3755a..983dd43 100644
--- a/linden/indra/llui/llcombobox.cpp
+++ b/linden/indra/llui/llcombobox.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -59,7 +60,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
59 ) 60 )
60: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata, 61: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata,
61 FOLLOWS_LEFT | FOLLOWS_TOP), 62 FOLLOWS_LEFT | FOLLOWS_TOP),
62 mDrawButton(TRUE), 63 mDrawArrow(TRUE),
63 mTextEntry(NULL), 64 mTextEntry(NULL),
64 mArrowImage(NULL), 65 mArrowImage(NULL),
65 mArrowImageWidth(8), 66 mArrowImageWidth(8),
@@ -67,8 +68,8 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
67 mMaxChars(20), 68 mMaxChars(20),
68 mTextEntryTentative(TRUE), 69 mTextEntryTentative(TRUE),
69 mPrearrangeCallback( NULL ), 70 mPrearrangeCallback( NULL ),
70 mTextEntryCallback( NULL ), 71 mListPosition(BELOW),
71 mListWidth(list_width) 72 mTextEntryCallback( NULL )
72{ 73{
73 // For now, all comboboxes don't take keyboard focus when clicked. 74 // For now, all comboboxes don't take keyboard focus when clicked.
74 // This might change if it is part of a modal dialog. 75 // This might change if it is part of a modal dialog.
@@ -76,7 +77,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
76 77
77 // Revert to standard behavior. When this control's parent is hidden, it needs to 78 // Revert to standard behavior. When this control's parent is hidden, it needs to
78 // hide this ctrl--which won't just happen automatically since when LLComboBox is 79 // hide this ctrl--which won't just happen automatically since when LLComboBox is
79 // showing its list, it's also set to TopView. When keyboard focus is cleared all 80 // showing its list, it's also set to TopCtrl. When keyboard focus is cleared all
80 // controls (including this one) know that they are no longer editing. 81 // controls (including this one) know that they are no longer editing.
81 mKeyboardFocusOnClick = TRUE; 82 mKeyboardFocusOnClick = TRUE;
82 83
@@ -87,7 +88,8 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
87 // Text label button 88 // Text label button
88 mButton = new LLSquareButton("comboxbox button", 89 mButton = new LLSquareButton("comboxbox button",
89 r, label, NULL, LLString::null, 90 r, label, NULL, LLString::null,
90 &LLComboBox::onButtonClick, this); 91 NULL, this);
92 mButton->setMouseDownCallback(onButtonDown);
91 mButton->setFont(LLFontGL::sSansSerifSmall); 93 mButton->setFont(LLFontGL::sSansSerifSmall);
92 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); 94 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
93 mButton->setHAlign( LLFontGL::LEFT ); 95 mButton->setHAlign( LLFontGL::LEFT );
@@ -110,6 +112,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
110 mList->setVisible(FALSE); 112 mList->setVisible(FALSE);
111 mList->setBgWriteableColor( LLColor4(1,1,1,1) ); 113 mList->setBgWriteableColor( LLColor4(1,1,1,1) );
112 mList->setCommitOnKeyboardMovement(FALSE); 114 mList->setCommitOnKeyboardMovement(FALSE);
115 mList->setFocusChangedCallback(onListFocusChanged);
113 addChild(mList); 116 addChild(mList);
114 117
115 LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0); 118 LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
@@ -119,7 +122,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
119 122
120 LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") ); 123 LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") );
121 mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id); 124 mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id);
122 mArrowImageWidth = llmax(8,mArrowImage->getWidth()); // In case image hasn't loaded yet 125 mArrowImageWidth = llmax(8,mArrowImage->getWidth(0)); // In case image hasn't loaded yet
123} 126}
124 127
125 128
@@ -219,115 +222,10 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
219 222
220void LLComboBox::setEnabled(BOOL enabled) 223void LLComboBox::setEnabled(BOOL enabled)
221{ 224{
222 LLUICtrl::setEnabled(enabled); 225 LLView::setEnabled(enabled);
223 mButton->setEnabled(enabled); 226 mButton->setEnabled(enabled);
224} 227}
225 228
226// *HACK: these are all hacks to support the fact that the combobox
227// has mouse capture so we can hide the list when we don't handle the
228// mouse up event
229BOOL LLComboBox::handleHover(S32 x, S32 y, MASK mask)
230{
231 if (mList->getVisible())
232 {
233 S32 local_x, local_y;
234 LLView::localPointToOtherView(x, y, &local_x, &local_y, mList);
235 if (mList->pointInView(local_x, local_y))
236 {
237 return mList->handleHover(local_x, local_y, mask);
238 }
239 }
240 return LLUICtrl::handleHover(x, y, mask);
241}
242
243BOOL LLComboBox::handleMouseDown(S32 x, S32 y, MASK mask)
244{
245 if (mList->getVisible())
246 {
247 S32 local_x, local_y;
248 LLView::localPointToOtherView(x, y, &local_x, &local_y, mList);
249 if (mList->pointInView(local_x, local_y))
250 {
251 return mList->handleMouseDown(local_x, local_y, mask);
252 }
253 }
254 BOOL has_focus_now = hasFocus();
255 BOOL handled = LLUICtrl::handleMouseDown(x, y, mask);
256 if (handled && !has_focus_now)
257 {
258 onFocusReceived();
259 }
260
261 return handled;
262}
263
264BOOL LLComboBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
265{
266 if (mList->getVisible())
267 {
268 S32 local_x, local_y;
269 LLView::localPointToOtherView(x, y, &local_x, &local_y, mList);
270 if (mList->pointInView(local_x, local_y))
271 {
272 return mList->handleRightMouseDown(local_x, local_y, mask);
273 }
274 }
275 return LLUICtrl::handleRightMouseDown(x, y, mask);
276}
277
278BOOL LLComboBox::handleRightMouseUp(S32 x, S32 y, MASK mask)
279{
280 if (mList->getVisible())
281 {
282 S32 local_x, local_y;
283 LLView::localPointToOtherView(x, y, &local_x, &local_y, mList);
284 if (mList->pointInView(local_x, local_y))
285 {
286 return mList->handleRightMouseUp(local_x, local_y, mask);
287 }
288 }
289 return LLUICtrl::handleRightMouseUp(x, y, mask);
290}
291
292BOOL LLComboBox::handleDoubleClick(S32 x, S32 y, MASK mask)
293{
294 if (mList->getVisible())
295 {
296 S32 local_x, local_y;
297 LLView::localPointToOtherView(x, y, &local_x, &local_y, mList);
298 if (mList->pointInView(local_x, local_y))
299 {
300 return mList->handleDoubleClick(local_x, local_y, mask);
301 }
302 }
303 return LLUICtrl::handleDoubleClick(x, y, mask);
304}
305
306BOOL LLComboBox::handleMouseUp(S32 x, S32 y, MASK mask)
307{
308 BOOL handled = childrenHandleMouseUp(x, y, mask) != NULL;
309
310 if (!handled && mList->getVisible())
311 {
312 S32 local_x, local_y;
313 LLView::localPointToOtherView(x, y, &local_x, &local_y, mList);
314 if (mList->pointInView(local_x, local_y))
315 {
316 handled = mList->handleMouseUp(local_x, local_y, mask);
317 }
318 }
319
320 if( !handled && gFocusMgr.getMouseCapture() == this )
321 {
322 // Mouse events that we didn't handle cause the list to be hidden.
323 // Eat mouse event, regardless of where on the screen it happens.
324 hideList();
325 handled = TRUE;
326 }
327
328 return handled;
329}
330
331void LLComboBox::clear() 229void LLComboBox::clear()
332{ 230{
333 if (mTextEntry) 231 if (mTextEntry)
@@ -512,12 +410,13 @@ void LLComboBox::onFocusLost()
512 { 410 {
513 mTextEntry->selectAll(); 411 mTextEntry->selectAll();
514 } 412 }
413 LLUICtrl::onFocusLost();
515} 414}
516 415
517void LLComboBox::setButtonVisible(BOOL visible) 416void LLComboBox::setButtonVisible(BOOL visible)
518{ 417{
519 mButton->setVisible(visible); 418 mButton->setVisible(visible);
520 mDrawButton = visible; 419 mDrawArrow = visible;
521 if (mTextEntry) 420 if (mTextEntry)
522 { 421 {
523 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0); 422 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
@@ -541,15 +440,17 @@ void LLComboBox::draw()
541 // Draw children 440 // Draw children
542 LLUICtrl::draw(); 441 LLUICtrl::draw();
543 442
544 if (mDrawButton) 443 if (mDrawArrow)
545 { 444 {
546 // Paste the graphic on the right edge 445 // Paste the graphic on the right edge
547 if (!mArrowImage.isNull()) 446 if (!mArrowImage.isNull())
548 { 447 {
549 S32 left = mRect.getWidth() - mArrowImageWidth - LLUI::sConfigGroup->getS32("DropShadowButton"); 448 S32 arrow_height = llmin(mRect.getHeight(), mArrowImage->getHeight());
449 S32 arrow_width = llround((F32)mArrowImage->getWidth() * ((F32)arrow_height / (F32)mArrowImage->getHeight()));
450
451 S32 left = mRect.getWidth() - mArrowImage->getWidth() - LLUI::sConfigGroup->getS32("DropShadowButton");
550 452
551 gl_draw_image( left, 0, mArrowImage, 453 gl_draw_scaled_image( left, 0, arrow_width, arrow_height, mArrowImage, LLColor4::white);
552 LLColor4::white);
553 } 454 }
554 } 455 }
555 } 456 }
@@ -595,18 +496,61 @@ void LLComboBox::showList()
595 //HACK: shouldn't have to know about scale here 496 //HACK: shouldn't have to know about scale here
596 mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); 497 mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
597 498
598 // Move rect so it hangs off the bottom of this view 499 // Make sure that we can see the whole list
500 LLRect root_view_local;
501 LLView* root_view = getRootView();
502 root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this);
503
599 LLRect rect = mList->getRect(); 504 LLRect rect = mList->getRect();
600 505
601 rect.setLeftTopAndSize(0, 0, rect.getWidth(), rect.getHeight() ); 506 if (mListPosition == BELOW)
602 mList->setRect(rect); 507 {
508 if (rect.getHeight() <= -root_view_local.mBottom)
509 {
510 // Move rect so it hangs off the bottom of this view
511 rect.setLeftTopAndSize(0, 0, rect.getWidth(), rect.getHeight() );
512 }
513 else
514 {
515 // stack on top or bottom, depending on which has more room
516 if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight())
517 {
518 // Move rect so it hangs off the bottom of this view
519 rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight()));
520 }
521 else
522 {
523 // move rect so it stacks on top of this view (clipped to size of screen)
524 rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
525 }
526 }
527 }
528 else // ABOVE
529 {
530 if (rect.getHeight() <= root_view_local.mTop - mRect.getHeight())
531 {
532 // move rect so it stacks on top of this view (clipped to size of screen)
533 rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
534 }
535 else
536 {
537 // stack on top or bottom, depending on which has more room
538 if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight())
539 {
540 // Move rect so it hangs off the bottom of this view
541 rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight()));
542 }
543 else
544 {
545 // move rect so it stacks on top of this view (clipped to size of screen)
546 rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
547 }
548 }
603 549
604 // Make sure that we can see the whole list 550 }
605 LLRect floater_area_screen; 551 mList->setOrigin(rect.mLeft, rect.mBottom);
606 LLRect floater_area_local; 552 mList->reshape(rect.getWidth(), rect.getHeight());
607 gFloaterView->getParent()->localRectToScreen( gFloaterView->getRect(), &floater_area_screen ); 553 mList->translateIntoRect(root_view_local, FALSE);
608 screenRectToLocal( floater_area_screen, &floater_area_local );
609 mList->translateIntoRect( floater_area_local, FALSE );
610 554
611 // Make sure we didn't go off bottom of screen 555 // Make sure we didn't go off bottom of screen
612 S32 x, y; 556 S32 x, y;
@@ -617,7 +561,12 @@ void LLComboBox::showList()
617 mList->translate(0, -y); 561 mList->translate(0, -y);
618 } 562 }
619 563
620 gFocusMgr.setMouseCapture( this, LLComboBox::onMouseCaptureLost ); 564 // pass mouse capture on to list if button is depressed
565 if (mButton->hasMouseCapture())
566 {
567 gFocusMgr.setMouseCapture(mList);
568 }
569
621 // NB: this call will trigger the focuslost callback which will hide the list, so do it first 570 // NB: this call will trigger the focuslost callback which will hide the list, so do it first
622 // before finally showing the list 571 // before finally showing the list
623 572
@@ -627,14 +576,13 @@ void LLComboBox::showList()
627 // so that the callback is not immediately triggered on setFocus() 576 // so that the callback is not immediately triggered on setFocus()
628 mList->selectFirstItem(); 577 mList->selectFirstItem();
629 } 578 }
630 gFocusMgr.setKeyboardFocus(mList, onListFocusLost); 579 mList->setFocus(TRUE);
631 580
632 // Show the list and push the button down 581 // Show the list and push the button down
633 mButton->setToggleState(TRUE); 582 mButton->setToggleState(TRUE);
634 mList->setVisible(TRUE); 583 mList->setVisible(TRUE);
635 584
636 gFocusMgr.setTopView(mList, LLComboBox::onTopViewLost ); 585 gFocusMgr.setTopCtrl(mList);
637
638} 586}
639 587
640void LLComboBox::hideList() 588void LLComboBox::hideList()
@@ -643,37 +591,21 @@ void LLComboBox::hideList()
643 mList->setVisible(FALSE); 591 mList->setVisible(FALSE);
644 mList->highlightNthItem(-1); 592 mList->highlightNthItem(-1);
645 593
646 if( gFocusMgr.getTopView() == mList ) 594 if( gFocusMgr.getTopCtrl() == mList )
647 {
648 gFocusMgr.setTopView(NULL, NULL);
649 }
650
651 if( gFocusMgr.getMouseCapture() == this )
652 { 595 {
653 gFocusMgr.setMouseCapture( NULL, NULL ); 596 gFocusMgr.setTopCtrl(NULL);
654 } 597 }
655 598
656 if( gFocusMgr.getKeyboardFocus() == mList ) 599 //mList->setFocus(FALSE);
657 {
658 if (mAllowTextEntry)
659 {
660 mTextEntry->setFocus(TRUE);
661 }
662 else
663 {
664 setFocus(TRUE);
665 }
666 }
667} 600}
668 601
669 602
670
671//------------------------------------------------------------------ 603//------------------------------------------------------------------
672// static functions 604// static functions
673//------------------------------------------------------------------ 605//------------------------------------------------------------------
674 606
675// static 607// static
676void LLComboBox::onButtonClick(void *userdata) 608void LLComboBox::onButtonDown(void *userdata)
677{ 609{
678 LLComboBox *self = (LLComboBox *)userdata; 610 LLComboBox *self = (LLComboBox *)userdata;
679 611
@@ -720,50 +652,47 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
720 652
721 const LLString& name = self->mList->getSimpleSelectedItem(); 653 const LLString& name = self->mList->getSimpleSelectedItem();
722 654
723 self->hideList();
724
725 S32 cur_id = self->getCurrentIndex(); 655 S32 cur_id = self->getCurrentIndex();
726 if (cur_id != -1) 656 if (cur_id != -1)
727 { 657 {
728 self->setLabel(self->mList->getSimpleSelectedItem()); 658 self->setLabel(name);
729 659
730 if (self->mAllowTextEntry) 660 if (self->mAllowTextEntry)
731 { 661 {
732 self->mTextEntry->setText(name);
733 self->mTextEntry->setTentative(FALSE);
734 gFocusMgr.setKeyboardFocus(self->mTextEntry, NULL); 662 gFocusMgr.setKeyboardFocus(self->mTextEntry, NULL);
735 self->mTextEntry->selectAll(); 663 self->mTextEntry->selectAll();
736 } 664 }
737 else 665 }
738 { 666 else
739 self->mButton->setLabelUnselected( name ); 667 {
740 self->mButton->setLabelSelected( name ); 668 // invalid selection, just restore existing value
741 self->mButton->setDisabledLabel( name ); 669 self->mList->selectSimpleItem(self->mButton->getLabelSelected());
742 self->mButton->setDisabledSelectedLabel( name );
743 }
744 } 670 }
745 self->onCommit(); 671 self->onCommit();
746}
747 672
748// static
749void LLComboBox::onTopViewLost(LLView* old_focus)
750{
751 LLComboBox *self = (LLComboBox *) old_focus->getParent();
752 self->hideList(); 673 self->hideList();
753} 674}
754 675
755
756// static 676// static
757void LLComboBox::onMouseCaptureLost(LLMouseHandler*) 677void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data)
758{ 678{
759 // Can't hide the list here. If the list scrolls off the screen, 679 LLComboBox *self = (LLComboBox *) list->getParent();
760 // and you click in the arrow buttons of the scroll bar, they must capture 680 // user not manipulating list or clicking on drop down button
761 // the mouse to handle scrolling-while-mouse-down. 681 if (!self->mList->hasFocus() && !self->mButton->hasMouseCapture())
682 {
683 //*HACK: store the original value explicitly somewhere, not just in label
684 LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
685
686 self->hideList();
687
688 // reassert original selection
689 self->mList->selectSimpleItem(orig_selection, FALSE);
690 }
762} 691}
763 692
764BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) 693BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
765{ 694{
766 695
767 LLString tool_tip; 696 LLString tool_tip;
768 697
769 if (LLUI::sShowXUINames) 698 if (LLUI::sShowXUINames)
@@ -875,6 +804,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
875 mTextEntry->setCommitOnFocusLost(FALSE); 804 mTextEntry->setCommitOnFocusLost(FALSE);
876 mTextEntry->setText(cur_label); 805 mTextEntry->setText(cur_label);
877 mTextEntry->setIgnoreTab(TRUE); 806 mTextEntry->setIgnoreTab(TRUE);
807 mTextEntry->setFollowsAll();
878 addChild(mTextEntry); 808 addChild(mTextEntry);
879 mMaxChars = max_chars; 809 mMaxChars = max_chars;
880 } 810 }
@@ -882,6 +812,8 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
882 { 812 {
883 mTextEntry->setVisible(TRUE); 813 mTextEntry->setVisible(TRUE);
884 } 814 }
815
816 mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
885 } 817 }
886 else if (!allow && mAllowTextEntry) 818 else if (!allow && mAllowTextEntry)
887 { 819 {
@@ -892,6 +824,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
892 { 824 {
893 mTextEntry->setVisible(FALSE); 825 mTextEntry->setVisible(FALSE);
894 } 826 }
827 mButton->setFollowsAll();
895 } 828 }
896 mAllowTextEntry = allow; 829 mAllowTextEntry = allow;
897 mTextEntryTentative = set_tentative; 830 mTextEntryTentative = set_tentative;
@@ -927,6 +860,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
927 else 860 else
928 { 861 {
929 line_editor->setTentative(self->mTextEntryTentative); 862 line_editor->setTentative(self->mTextEntryTentative);
863 self->mList->deselectAllItems();
930 } 864 }
931 return; 865 return;
932 } 866 }
@@ -1141,15 +1075,3 @@ BOOL LLComboBox::operateOnAll(EOperation op)
1141 } 1075 }
1142 return FALSE; 1076 return FALSE;
1143} 1077}
1144
1145//static
1146void LLComboBox::onListFocusLost(LLUICtrl* old_focus)
1147{
1148 // if focus is going to nothing (user hit ESC), take it back
1149 LLComboBox* combo = (LLComboBox*)old_focus->getParent();
1150 combo->hideList();
1151 if (gFocusMgr.getKeyboardFocus() == NULL)
1152 {
1153 combo->focusFirstItem();
1154 }
1155}
diff --git a/linden/indra/llui/llcombobox.h b/linden/indra/llui/llcombobox.h
index 5de9463..8c317ee 100644
--- a/linden/indra/llui/llcombobox.h
+++ b/linden/indra/llui/llcombobox.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -53,6 +54,12 @@ class LLComboBox
53: public LLUICtrl, public LLCtrlListInterface 54: public LLUICtrl, public LLCtrlListInterface
54{ 55{
55public: 56public:
57 typedef enum e_preferred_position
58 {
59 ABOVE,
60 BELOW
61 } EPreferredPosition;
62
56 LLComboBox( 63 LLComboBox(
57 const LLString& name, 64 const LLString& name,
58 const LLRect &rect, 65 const LLRect &rect,
@@ -77,12 +84,6 @@ public:
77 virtual BOOL handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect); 84 virtual BOOL handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect);
78 virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); 85 virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
79 virtual BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent); 86 virtual BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent);
80 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
81 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
82 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
83 virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
84 virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
85 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
86 87
87 // LLUICtrl interface 88 // LLUICtrl interface
88 virtual void clear(); // select nothing 89 virtual void clear(); // select nothing
@@ -165,34 +166,31 @@ public:
165 166
166 void setButtonVisible(BOOL visible); 167 void setButtonVisible(BOOL visible);
167 168
168 static void onButtonClick(void *userdata); 169 static void onButtonDown(void *userdata);
169 static void onItemSelected(LLUICtrl* item, void *userdata); 170 static void onItemSelected(LLUICtrl* item, void *userdata);
170 static void onTopViewLost(LLView* old_focus); 171 static void onListFocusChanged(LLUICtrl* item, void *userdata);
171 static void onMouseCaptureLost(LLMouseHandler* old_captor);
172 static void onTextEntry(LLLineEditor* line_editor, void* user_data); 172 static void onTextEntry(LLLineEditor* line_editor, void* user_data);
173 static void onTextCommit(LLUICtrl* caller, void* user_data); 173 static void onTextCommit(LLUICtrl* caller, void* user_data);
174 174
175 void updateSelection(); 175 void updateSelection();
176 void showList(); 176 virtual void showList();
177 void hideList(); 177 virtual void hideList();
178 178
179 static void onListFocusLost(LLUICtrl* old_focus);
180
181protected: 179protected:
182 LLButton* mButton; 180 LLButton* mButton;
183 LLScrollListCtrl* mList; 181 LLScrollListCtrl* mList;
184 LLViewBorder* mBorder; 182 LLViewBorder* mBorder;
185 BOOL mKeyboardFocusOnClick; 183 BOOL mKeyboardFocusOnClick;
186 BOOL mDrawButton; 184 BOOL mDrawArrow;
187 LLLineEditor* mTextEntry; 185 LLLineEditor* mTextEntry;
188 LLPointer<LLImageGL> mArrowImage; 186 LLPointer<LLImageGL> mArrowImage;
189 S32 mArrowImageWidth; 187 S32 mArrowImageWidth;
190 BOOL mAllowTextEntry; 188 BOOL mAllowTextEntry;
191 S32 mMaxChars; 189 S32 mMaxChars;
192 BOOL mTextEntryTentative; 190 BOOL mTextEntryTentative;
191 EPreferredPosition mListPosition;
193 void (*mPrearrangeCallback)(LLUICtrl*,void*); 192 void (*mPrearrangeCallback)(LLUICtrl*,void*);
194 void (*mTextEntryCallback)(LLLineEditor*, void*); 193 void (*mTextEntryCallback)(LLLineEditor*, void*);
195 S32 mListWidth; // width of pop-up list, 0 = use combobox width
196}; 194};
197 195
198#endif 196#endif
diff --git a/linden/indra/llui/llctrlselectioninterface.cpp b/linden/indra/llui/llctrlselectioninterface.cpp
index 446eb63..3b71942 100644
--- a/linden/indra/llui/llctrlselectioninterface.cpp
+++ b/linden/indra/llui/llctrlselectioninterface.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llctrlselectioninterface.h b/linden/indra/llui/llctrlselectioninterface.h
index 189d2e1..878648d 100644
--- a/linden/indra/llui/llctrlselectioninterface.h
+++ b/linden/indra/llui/llctrlselectioninterface.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lldraghandle.cpp b/linden/indra/llui/lldraghandle.cpp
index 261d149..9e80c99 100644
--- a/linden/indra/llui/lldraghandle.cpp
+++ b/linden/indra/llui/lldraghandle.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -288,7 +289,7 @@ BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask)
288{ 289{
289 // Route future Mouse messages here preemptively. (Release on mouse up.) 290 // Route future Mouse messages here preemptively. (Release on mouse up.)
290 // No handler needed for focus lost since this clas has no state that depends on it. 291 // No handler needed for focus lost since this clas has no state that depends on it.
291 gFocusMgr.setMouseCapture(this, NULL ); 292 gFocusMgr.setMouseCapture(this);
292 293
293 localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY); 294 localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
294 mLastMouseScreenX = mDragLastScreenX; 295 mLastMouseScreenX = mDragLastScreenX;
@@ -301,10 +302,10 @@ BOOL LLDragHandle::handleMouseDown(S32 x, S32 y, MASK mask)
301 302
302BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask) 303BOOL LLDragHandle::handleMouseUp(S32 x, S32 y, MASK mask)
303{ 304{
304 if( gFocusMgr.getMouseCapture() == this ) 305 if( hasMouseCapture() )
305 { 306 {
306 // Release the mouse 307 // Release the mouse
307 gFocusMgr.setMouseCapture( NULL, NULL ); 308 gFocusMgr.setMouseCapture( NULL );
308 } 309 }
309 310
310 // Note: don't pass on to children 311 // Note: don't pass on to children
@@ -317,7 +318,7 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)
317 BOOL handled = FALSE; 318 BOOL handled = FALSE;
318 319
319 // We only handle the click if the click both started and ended within us 320 // We only handle the click if the click both started and ended within us
320 if( gFocusMgr.getMouseCapture() == this ) 321 if( hasMouseCapture() )
321 { 322 {
322 S32 screen_x; 323 S32 screen_x;
323 S32 screen_y; 324 S32 screen_y;
diff --git a/linden/indra/llui/lldraghandle.h b/linden/indra/llui/lldraghandle.h
index 5344358..691851d 100644
--- a/linden/indra/llui/lldraghandle.h
+++ b/linden/indra/llui/lldraghandle.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lleditmenuhandler.cpp b/linden/indra/llui/lleditmenuhandler.cpp
index 7425aa8..85b4464 100644
--- a/linden/indra/llui/lleditmenuhandler.cpp
+++ b/linden/indra/llui/lleditmenuhandler.cpp
@@ -4,6 +4,7 @@
4* 4*
5* Copyright (c) 2006-2007, Linden Research, Inc. 5* Copyright (c) 2006-2007, Linden Research, Inc.
6* 6*
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lleditmenuhandler.h b/linden/indra/llui/lleditmenuhandler.h
index 35e223b..ec3d246 100644
--- a/linden/indra/llui/lleditmenuhandler.h
+++ b/linden/indra/llui/lleditmenuhandler.h
@@ -4,6 +4,7 @@
4* 4*
5* Copyright (c) 2006-2007, Linden Research, Inc. 5* Copyright (c) 2006-2007, Linden Research, Inc.
6* 6*
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp
index 02a410e..12758b3 100644
--- a/linden/indra/llui/llfloater.cpp
+++ b/linden/indra/llui/llfloater.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -57,6 +58,8 @@ extern BOOL gNoRender;
57 58
58const S32 MINIMIZED_WIDTH = 160; 59const S32 MINIMIZED_WIDTH = 160;
59const S32 CLOSE_BOX_FROM_TOP = 1; 60const S32 CLOSE_BOX_FROM_TOP = 1;
61// use this to control "jumping" behavior when Ctrl-Tabbing
62const S32 TABBED_FLOATER_OFFSET = 0;
60 63
61LLString LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = 64LLString LLFloater::sButtonActiveImageNames[BUTTON_COUNT] =
62{ 65{
@@ -298,7 +301,6 @@ void LLFloater::init(const LLString& title,
298 mRect.getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); 301 mRect.getHeight() - LLPANEL_BORDER_WIDTH - close_box_size);
299 mDragHandle = new LLDragHandleLeft("drag", drag_handle_rect, title ); 302 mDragHandle = new LLDragHandleLeft("drag", drag_handle_rect, title );
300 } 303 }
301 mDragHandle->setSaveToXML(false);
302 addChild(mDragHandle); 304 addChild(mDragHandle);
303 305
304 // Resize Handle 306 // Resize Handle
@@ -314,28 +316,24 @@ void LLFloater::init(const LLString& title,
314 "resizebar_left", 316 "resizebar_left",
315 LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0), 317 LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0),
316 min_width, min_height, LLResizeBar::LEFT ); 318 min_width, min_height, LLResizeBar::LEFT );
317 mResizeBar[0]->setSaveToXML(false);
318 addChild( mResizeBar[0] ); 319 addChild( mResizeBar[0] );
319 320
320 mResizeBar[1] = new LLResizeBar( 321 mResizeBar[1] = new LLResizeBar(
321 "resizebar_top", 322 "resizebar_top",
322 LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS), 323 LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS),
323 min_width, min_height, LLResizeBar::TOP ); 324 min_width, min_height, LLResizeBar::TOP );
324 mResizeBar[1]->setSaveToXML(false);
325 addChild( mResizeBar[1] ); 325 addChild( mResizeBar[1] );
326 326
327 mResizeBar[2] = new LLResizeBar( 327 mResizeBar[2] = new LLResizeBar(
328 "resizebar_right", 328 "resizebar_right",
329 LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0), 329 LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
330 min_width, min_height, LLResizeBar::RIGHT ); 330 min_width, min_height, LLResizeBar::RIGHT );
331 mResizeBar[2]->setSaveToXML(false);
332 addChild( mResizeBar[2] ); 331 addChild( mResizeBar[2] );
333 332
334 mResizeBar[3] = new LLResizeBar( 333 mResizeBar[3] = new LLResizeBar(
335 "resizebar_bottom", 334 "resizebar_bottom",
336 LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0), 335 LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0),
337 min_width, min_height, LLResizeBar::BOTTOM ); 336 min_width, min_height, LLResizeBar::BOTTOM );
338 mResizeBar[3]->setSaveToXML(false);
339 addChild( mResizeBar[3] ); 337 addChild( mResizeBar[3] );
340 338
341 339
@@ -346,7 +344,6 @@ void LLFloater::init(const LLString& title,
346 min_width, 344 min_width,
347 min_height, 345 min_height,
348 LLResizeHandle::RIGHT_BOTTOM); 346 LLResizeHandle::RIGHT_BOTTOM);
349 mResizeHandle[0]->setSaveToXML(false);
350 addChild(mResizeHandle[0]); 347 addChild(mResizeHandle[0]);
351 348
352 mResizeHandle[1] = new LLResizeHandle( "resize", 349 mResizeHandle[1] = new LLResizeHandle( "resize",
@@ -354,7 +351,6 @@ void LLFloater::init(const LLString& title,
354 min_width, 351 min_width,
355 min_height, 352 min_height,
356 LLResizeHandle::RIGHT_TOP ); 353 LLResizeHandle::RIGHT_TOP );
357 mResizeHandle[1]->setSaveToXML(false);
358 addChild(mResizeHandle[1]); 354 addChild(mResizeHandle[1]);
359 355
360 mResizeHandle[2] = new LLResizeHandle( "resize", 356 mResizeHandle[2] = new LLResizeHandle( "resize",
@@ -362,7 +358,6 @@ void LLFloater::init(const LLString& title,
362 min_width, 358 min_width,
363 min_height, 359 min_height,
364 LLResizeHandle::LEFT_BOTTOM ); 360 LLResizeHandle::LEFT_BOTTOM );
365 mResizeHandle[2]->setSaveToXML(false);
366 addChild(mResizeHandle[2]); 361 addChild(mResizeHandle[2]);
367 362
368 mResizeHandle[3] = new LLResizeHandle( "resize", 363 mResizeHandle[3] = new LLResizeHandle( "resize",
@@ -370,7 +365,6 @@ void LLFloater::init(const LLString& title,
370 min_width, 365 min_width,
371 min_height, 366 min_height,
372 LLResizeHandle::LEFT_TOP ); 367 LLResizeHandle::LEFT_TOP );
373 mResizeHandle[3]->setSaveToXML(false);
374 addChild(mResizeHandle[3]); 368 addChild(mResizeHandle[3]);
375 } 369 }
376 else 370 else
@@ -482,14 +476,14 @@ void LLFloater::setVisible( BOOL visible )
482 476
483 if( !visible ) 477 if( !visible )
484 { 478 {
485 if( gFocusMgr.childIsTopView( this ) ) 479 if( gFocusMgr.childIsTopCtrl( this ) )
486 { 480 {
487 gFocusMgr.setTopView(NULL, NULL); 481 gFocusMgr.setTopCtrl(NULL);
488 } 482 }
489 483
490 if( gFocusMgr.childHasMouseCapture( this ) ) 484 if( gFocusMgr.childHasMouseCapture( this ) )
491 { 485 {
492 gFocusMgr.setMouseCapture(NULL, NULL); 486 gFocusMgr.setMouseCapture(NULL);
493 } 487 }
494 } 488 }
495 489
@@ -603,9 +597,9 @@ void LLFloater::close(bool app_quitting)
603 597
604void LLFloater::releaseFocus() 598void LLFloater::releaseFocus()
605{ 599{
606 if( gFocusMgr.childIsTopView( this ) ) 600 if( gFocusMgr.childIsTopCtrl( this ) )
607 { 601 {
608 gFocusMgr.setTopView(NULL, NULL); 602 gFocusMgr.setTopCtrl(NULL);
609 } 603 }
610 604
611 if( gFocusMgr.childHasKeyboardFocus( this ) ) 605 if( gFocusMgr.childHasKeyboardFocus( this ) )
@@ -615,7 +609,7 @@ void LLFloater::releaseFocus()
615 609
616 if( gFocusMgr.childHasMouseCapture( this ) ) 610 if( gFocusMgr.childHasMouseCapture( this ) )
617 { 611 {
618 gFocusMgr.setMouseCapture(NULL, NULL); 612 gFocusMgr.setMouseCapture(NULL);
619 } 613 }
620} 614}
621 615
@@ -1483,28 +1477,24 @@ void LLFloater::setCanResize(BOOL can_resize)
1483 "resizebar_left", 1477 "resizebar_left",
1484 LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0), 1478 LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0),
1485 mMinWidth, mMinHeight, LLResizeBar::LEFT ); 1479 mMinWidth, mMinHeight, LLResizeBar::LEFT );
1486 mResizeBar[0]->setSaveToXML(false);
1487 addChild( mResizeBar[0] ); 1480 addChild( mResizeBar[0] );
1488 1481
1489 mResizeBar[1] = new LLResizeBar( 1482 mResizeBar[1] = new LLResizeBar(
1490 "resizebar_top", 1483 "resizebar_top",
1491 LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS), 1484 LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS),
1492 mMinWidth, mMinHeight, LLResizeBar::TOP ); 1485 mMinWidth, mMinHeight, LLResizeBar::TOP );
1493 mResizeBar[1]->setSaveToXML(false);
1494 addChild( mResizeBar[1] ); 1486 addChild( mResizeBar[1] );
1495 1487
1496 mResizeBar[2] = new LLResizeBar( 1488 mResizeBar[2] = new LLResizeBar(
1497 "resizebar_right", 1489 "resizebar_right",
1498 LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0), 1490 LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
1499 mMinWidth, mMinHeight, LLResizeBar::RIGHT ); 1491 mMinWidth, mMinHeight, LLResizeBar::RIGHT );
1500 mResizeBar[2]->setSaveToXML(false);
1501 addChild( mResizeBar[2] ); 1492 addChild( mResizeBar[2] );
1502 1493
1503 mResizeBar[3] = new LLResizeBar( 1494 mResizeBar[3] = new LLResizeBar(
1504 "resizebar_bottom", 1495 "resizebar_bottom",
1505 LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0), 1496 LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0),
1506 mMinWidth, mMinHeight, LLResizeBar::BOTTOM ); 1497 mMinWidth, mMinHeight, LLResizeBar::BOTTOM );
1507 mResizeBar[3]->setSaveToXML(false);
1508 addChild( mResizeBar[3] ); 1498 addChild( mResizeBar[3] );
1509 1499
1510 1500
@@ -1515,7 +1505,6 @@ void LLFloater::setCanResize(BOOL can_resize)
1515 mMinWidth, 1505 mMinWidth,
1516 mMinHeight, 1506 mMinHeight,
1517 LLResizeHandle::RIGHT_BOTTOM); 1507 LLResizeHandle::RIGHT_BOTTOM);
1518 mResizeHandle[0]->setSaveToXML(false);
1519 addChild(mResizeHandle[0]); 1508 addChild(mResizeHandle[0]);
1520 1509
1521 mResizeHandle[1] = new LLResizeHandle( "resize", 1510 mResizeHandle[1] = new LLResizeHandle( "resize",
@@ -1523,7 +1512,6 @@ void LLFloater::setCanResize(BOOL can_resize)
1523 mMinWidth, 1512 mMinWidth,
1524 mMinHeight, 1513 mMinHeight,
1525 LLResizeHandle::RIGHT_TOP ); 1514 LLResizeHandle::RIGHT_TOP );
1526 mResizeHandle[1]->setSaveToXML(false);
1527 addChild(mResizeHandle[1]); 1515 addChild(mResizeHandle[1]);
1528 1516
1529 mResizeHandle[2] = new LLResizeHandle( "resize", 1517 mResizeHandle[2] = new LLResizeHandle( "resize",
@@ -1531,7 +1519,6 @@ void LLFloater::setCanResize(BOOL can_resize)
1531 mMinWidth, 1519 mMinWidth,
1532 mMinHeight, 1520 mMinHeight,
1533 LLResizeHandle::LEFT_BOTTOM ); 1521 LLResizeHandle::LEFT_BOTTOM );
1534 mResizeHandle[2]->setSaveToXML(false);
1535 addChild(mResizeHandle[2]); 1522 addChild(mResizeHandle[2]);
1536 1523
1537 mResizeHandle[3] = new LLResizeHandle( "resize", 1524 mResizeHandle[3] = new LLResizeHandle( "resize",
@@ -1539,7 +1526,6 @@ void LLFloater::setCanResize(BOOL can_resize)
1539 mMinWidth, 1526 mMinWidth,
1540 mMinHeight, 1527 mMinHeight,
1541 LLResizeHandle::LEFT_TOP ); 1528 LLResizeHandle::LEFT_TOP );
1542 mResizeHandle[3]->setSaveToXML(false);
1543 addChild(mResizeHandle[3]); 1529 addChild(mResizeHandle[3]);
1544 } 1530 }
1545 mResizable = can_resize; 1531 mResizable = can_resize;
@@ -2041,8 +2027,7 @@ void LLFloaterView::focusFrontFloater()
2041void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) 2027void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
2042{ 2028{
2043 S32 col = 0; 2029 S32 col = 0;
2044 LLRect snap_rect_local = getSnapRect(); 2030 LLRect snap_rect_local = getLocalSnapRect();
2045 snap_rect_local.translate(-mRect.mLeft, -mRect.mBottom);
2046 for(S32 row = snap_rect_local.mBottom; 2031 for(S32 row = snap_rect_local.mBottom;
2047 row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE; 2032 row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE;
2048 row += LLFLOATER_HEADER_SIZE ) //loop rows 2033 row += LLFLOATER_HEADER_SIZE ) //loop rows
@@ -2165,8 +2150,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
2165 S32 screen_width = getSnapRect().getWidth(); 2150 S32 screen_width = getSnapRect().getWidth();
2166 S32 screen_height = getSnapRect().getHeight(); 2151 S32 screen_height = getSnapRect().getHeight();
2167 // convert to local coordinate frame 2152 // convert to local coordinate frame
2168 LLRect snap_rect_local = getSnapRect(); 2153 LLRect snap_rect_local = getLocalSnapRect();
2169 snap_rect_local.translate(-mRect.mLeft, -mRect.mBottom);
2170 2154
2171 if( floater->isResizable() ) 2155 if( floater->isResizable() )
2172 { 2156 {
@@ -2207,32 +2191,27 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
2207 2191
2208void LLFloaterView::draw() 2192void LLFloaterView::draw()
2209{ 2193{
2210 if( getVisible() ) 2194 refresh();
2211 {
2212 refresh();
2213
2214 // hide focused floater if in cycle mode, so that it can be drawn on top
2215 LLFloater* focused_floater = getFocusedFloater();
2216 BOOL floater_visible = FALSE;
2217 if (mFocusCycleMode && focused_floater)
2218 {
2219 floater_visible = focused_floater->getVisible();
2220 focused_floater->setVisible(FALSE);
2221 }
2222 2195
2223 // And actually do the draw 2196 // hide focused floater if in cycle mode, so that it can be drawn on top
2224 LLView::draw(); 2197 LLFloater* focused_floater = getFocusedFloater();
2225 2198
2226 // manually draw focused floater on top when in cycle mode 2199 if (mFocusCycleMode && focused_floater)
2227 if (mFocusCycleMode && focused_floater) 2200 {
2201 child_list_const_iter_t child_it = getChildList()->begin();
2202 for (;child_it != getChildList()->end(); ++child_it)
2228 { 2203 {
2229 // draw focused item on top for better feedback 2204 if ((*child_it) != focused_floater)
2230 focused_floater->setVisible(floater_visible);
2231 if (floater_visible)
2232 { 2205 {
2233 drawChild(focused_floater); 2206 drawChild(*child_it);
2234 } 2207 }
2235 } 2208 }
2209
2210 drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET);
2211 }
2212 else
2213 {
2214 LLView::draw();
2236 } 2215 }
2237} 2216}
2238 2217
diff --git a/linden/indra/llui/llfloater.h b/linden/indra/llui/llfloater.h
index 25b2697..e752d8b 100644
--- a/linden/indra/llui/llfloater.h
+++ b/linden/indra/llui/llfloater.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp
index f02996b..f79164e 100644
--- a/linden/indra/llui/llfocusmgr.cpp
+++ b/linden/indra/llui/llfocusmgr.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -40,18 +41,16 @@ LLFocusMgr::LLFocusMgr()
40 mLockedView( NULL ), 41 mLockedView( NULL ),
41 mKeyboardLockedFocusLostCallback( NULL ), 42 mKeyboardLockedFocusLostCallback( NULL ),
42 mMouseCaptor( NULL ), 43 mMouseCaptor( NULL ),
43 mMouseCaptureLostCallback( NULL ),
44 mKeyboardFocus( NULL ), 44 mKeyboardFocus( NULL ),
45 mDefaultKeyboardFocus( NULL ), 45 mDefaultKeyboardFocus( NULL ),
46 mKeyboardFocusLostCallback( NULL ), 46 mKeyboardFocusLostCallback( NULL ),
47 mTopView( NULL ), 47 mTopCtrl( NULL ),
48 mTopViewLostCallback( NULL ),
49 mFocusWeight(0.f), 48 mFocusWeight(0.f),
50 mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true 49 mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true
51 #ifdef _DEBUG 50 #ifdef _DEBUG
52 , mMouseCaptorName("none") 51 , mMouseCaptorName("none")
53 , mKeyboardFocusName("none") 52 , mKeyboardFocusName("none")
54 , mTopViewName("none") 53 , mTopCtrlName("none")
55 #endif 54 #endif
56{ 55{
57} 56}
@@ -65,7 +64,7 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
65{ 64{
66 if( childHasMouseCapture( view ) ) 65 if( childHasMouseCapture( view ) )
67 { 66 {
68 setMouseCapture( NULL, NULL ); 67 setMouseCapture( NULL );
69 } 68 }
70 69
71 if( childHasKeyboardFocus( view )) 70 if( childHasKeyboardFocus( view ))
@@ -82,9 +81,9 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
82 } 81 }
83 } 82 }
84 83
85 if( childIsTopView( view ) ) 84 if( childIsTopCtrl( view ) )
86 { 85 {
87 setTopView( NULL, NULL ); 86 setTopCtrl( NULL );
88 } 87 }
89} 88}
90 89
@@ -127,13 +126,13 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu
127 126
128 // If we've got a default keyboard focus, and the caller is 127 // If we've got a default keyboard focus, and the caller is
129 // releasing keyboard focus, move to the default. 128 // releasing keyboard focus, move to the default.
130 if (mDefaultKeyboardFocus != NULL && new_focus == NULL) 129 if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL)
131 { 130 {
132 mDefaultKeyboardFocus->setFocus(TRUE); 131 mDefaultKeyboardFocus->setFocus(TRUE);
133 } 132 }
134 133
135 LLView* focus_subtree = new_focus; 134 LLView* focus_subtree = mKeyboardFocus;
136 LLView* viewp = new_focus; 135 LLView* viewp = mKeyboardFocus;
137 // find root-most focus root 136 // find root-most focus root
138 while(viewp) 137 while(viewp)
139 { 138 {
@@ -147,13 +146,13 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu
147 146
148 if (focus_subtree) 147 if (focus_subtree)
149 { 148 {
150 mFocusHistory[focus_subtree->mViewHandle] = new_focus ? new_focus->mViewHandle : LLViewHandle::sDeadHandle; 149 mFocusHistory[focus_subtree->mViewHandle] = mKeyboardFocus ? mKeyboardFocus->mViewHandle : LLViewHandle::sDeadHandle;
151 } 150 }
152 } 151 }
153 152
154 if (lock) 153 if (lock)
155 { 154 {
156 mLockedView = new_focus; 155 mLockedView = mKeyboardFocus;
157 mKeyboardLockedFocusLostCallback = on_focus_lost; 156 mKeyboardLockedFocusLostCallback = on_focus_lost;
158 } 157 }
159} 158}
@@ -217,16 +216,13 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( LLView* focus )
217} 216}
218 217
219 218
220void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor, void (*on_capture_lost)(LLMouseHandler* old_captor) ) 219void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor )
221{ 220{
222 //if (mFocusLocked) 221 //if (mFocusLocked)
223 //{ 222 //{
224 // return; 223 // return;
225 //} 224 //}
226 225
227 void (*old_callback)(LLMouseHandler*) = mMouseCaptureLostCallback;
228 mMouseCaptureLostCallback = on_capture_lost;
229
230 if( new_captor != mMouseCaptor ) 226 if( new_captor != mMouseCaptor )
231 { 227 {
232 LLMouseHandler* old_captor = mMouseCaptor; 228 LLMouseHandler* old_captor = mMouseCaptor;
@@ -249,9 +245,9 @@ void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor, void (*on_capture_
249 } 245 }
250 */ 246 */
251 247
252 if( old_callback ) 248 if( old_captor )
253 { 249 {
254 old_callback( old_captor ); 250 old_captor->onMouseCaptureLost();
255 } 251 }
256 252
257 #ifdef _DEBUG 253 #ifdef _DEBUG
@@ -269,7 +265,6 @@ void LLFocusMgr::removeMouseCaptureWithoutCallback( LLMouseHandler* captor )
269 if( mMouseCaptor == captor ) 265 if( mMouseCaptor == captor )
270 { 266 {
271 mMouseCaptor = NULL; 267 mMouseCaptor = NULL;
272 mMouseCaptureLostCallback = NULL;
273 #ifdef _DEBUG 268 #ifdef _DEBUG
274 mMouseCaptorName = "none"; 269 mMouseCaptorName = "none";
275 #endif 270 #endif
@@ -277,9 +272,9 @@ void LLFocusMgr::removeMouseCaptureWithoutCallback( LLMouseHandler* captor )
277} 272}
278 273
279 274
280BOOL LLFocusMgr::childIsTopView( LLView* parent ) 275BOOL LLFocusMgr::childIsTopCtrl( LLView* parent )
281{ 276{
282 LLView* top_view = mTopView; 277 LLView* top_view = (LLView*)mTopCtrl;
283 while( top_view ) 278 while( top_view )
284 { 279 {
285 if( top_view == parent ) 280 if( top_view == parent )
@@ -294,36 +289,25 @@ BOOL LLFocusMgr::childIsTopView( LLView* parent )
294 289
295 290
296// set new_top = NULL to release top_view. 291// set new_top = NULL to release top_view.
297void LLFocusMgr::setTopView( LLView* new_top, void (*on_top_lost)(LLView* old_top) ) 292void LLFocusMgr::setTopCtrl( LLUICtrl* new_top )
298{ 293{
299 void (*old_callback)(LLView*) = mTopViewLostCallback; 294 if( new_top != mTopCtrl )
300 mTopViewLostCallback = on_top_lost;
301
302 if( new_top != mTopView )
303 { 295 {
304 LLView* old_top = mTopView; 296 mTopCtrl = new_top;
305 mTopView = new_top;
306 if( old_callback )
307 {
308 old_callback( old_top );
309 }
310
311 mTopView = new_top;
312 297
313 #ifdef _DEBUG 298 #ifdef _DEBUG
314 mTopViewName = new_top ? new_top->getName() : "none"; 299 mTopCtrlName = new_top ? new_top->getName() : "none";
315 #endif 300 #endif
316 } 301 }
317} 302}
318 303
319void LLFocusMgr::removeTopViewWithoutCallback( LLView* top_view ) 304void LLFocusMgr::removeTopCtrlWithoutCallback( LLUICtrl* top_view )
320{ 305{
321 if( mTopView == top_view ) 306 if( mTopCtrl == top_view )
322 { 307 {
323 mTopView = NULL; 308 mTopCtrl = NULL;
324 mTopViewLostCallback = NULL;
325 #ifdef _DEBUG 309 #ifdef _DEBUG
326 mTopViewName = "none"; 310 mTopCtrlName = "none";
327 #endif 311 #endif
328 } 312 }
329} 313}
@@ -362,6 +346,12 @@ void LLFocusMgr::setAppHasFocus(BOOL focus)
362 { 346 {
363 triggerFocusFlash(); 347 triggerFocusFlash();
364 } 348 }
349
350 // release focus from "top ctrl"s, which generally hides them
351 if (!focus && mTopCtrl && mTopCtrl->hasFocus())
352 {
353 mTopCtrl->setFocus(FALSE);
354 }
365 mAppHasFocus = focus; 355 mAppHasFocus = focus;
366} 356}
367 357
diff --git a/linden/indra/llui/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h
index 5687b99..e189945 100644
--- a/linden/indra/llui/llfocusmgr.h
+++ b/linden/indra/llui/llfocusmgr.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -46,7 +47,7 @@ public:
46 ~LLFocusMgr(); 47 ~LLFocusMgr();
47 48
48 // Mouse Captor 49 // Mouse Captor
49 void setMouseCapture(LLMouseHandler* new_captor,void (*on_capture_lost)(LLMouseHandler* old_captor)); // new_captor = NULL to release the mouse. 50 void setMouseCapture(LLMouseHandler* new_captor); // new_captor = NULL to release the mouse.
50 LLMouseHandler* getMouseCapture() { return mMouseCaptor; } 51 LLMouseHandler* getMouseCapture() { return mMouseCaptor; }
51 void removeMouseCaptureWithoutCallback( LLMouseHandler* captor ); 52 void removeMouseCaptureWithoutCallback( LLMouseHandler* captor );
52 BOOL childHasMouseCapture( LLView* parent ); 53 BOOL childHasMouseCapture( LLView* parent );
@@ -73,10 +74,10 @@ public:
73 74
74 75
75 // Top View 76 // Top View
76 void setTopView(LLView* new_top, void (*on_top_lost)(LLView* old_top)); 77 void setTopCtrl(LLUICtrl* new_top);
77 LLView* getTopView() const { return mTopView; } 78 LLUICtrl* getTopCtrl() const { return mTopCtrl; }
78 void removeTopViewWithoutCallback( LLView* top_view ); 79 void removeTopCtrlWithoutCallback( LLUICtrl* top_view );
79 BOOL childIsTopView( LLView* parent ); 80 BOOL childIsTopCtrl( LLView* parent );
80 81
81 // All Three 82 // All Three
82 void releaseFocusIfNeeded( LLView* top_view ); 83 void releaseFocusIfNeeded( LLView* top_view );
@@ -89,7 +90,6 @@ protected:
89 90
90 // Mouse Captor 91 // Mouse Captor
91 LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object 92 LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object
92 void (*mMouseCaptureLostCallback)(LLMouseHandler*); // The object to which mouse events are routed is called before another object takes its place
93 93
94 // Keyboard Focus 94 // Keyboard Focus
95 LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object 95 LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object
@@ -97,8 +97,7 @@ protected:
97 FocusLostCallback mKeyboardFocusLostCallback; // The object to which keyboard events are routed is called before another object takes its place 97 FocusLostCallback mKeyboardFocusLostCallback; // The object to which keyboard events are routed is called before another object takes its place
98 98
99 // Top View 99 // Top View
100 LLView* mTopView; 100 LLUICtrl* mTopCtrl;
101 void (*mTopViewLostCallback)(LLView*);
102 101
103 LLFrameTimer mFocusTimer; 102 LLFrameTimer mFocusTimer;
104 F32 mFocusWeight; 103 F32 mFocusWeight;
@@ -111,7 +110,7 @@ protected:
111 #ifdef _DEBUG 110 #ifdef _DEBUG
112 LLString mMouseCaptorName; 111 LLString mMouseCaptorName;
113 LLString mKeyboardFocusName; 112 LLString mKeyboardFocusName;
114 LLString mTopViewName; 113 LLString mTopCtrlName;
115 #endif 114 #endif
116}; 115};
117 116
diff --git a/linden/indra/llui/llhtmlhelp.h b/linden/indra/llui/llhtmlhelp.h
new file mode 100644
index 0000000..4b2a43a
--- /dev/null
+++ b/linden/indra/llui/llhtmlhelp.h
@@ -0,0 +1,40 @@
1/**
2 * @file llhtmlhelp.h
3 * @brief HTML Help floater interface
4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 *
7 * Second Life Viewer Source Code
8 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement
11 * ("Other License"), formally executed by you and Linden Lab. Terms of
12 * the GPL can be found in doc/GPL-license.txt in this distribution, or
13 * online at http://secondlife.com/developers/opensource/gplv2
14 *
15 * There are special exceptions to the terms and conditions of the GPL as
16 * it is applied to this Source Code. View the full text of the exception
17 * in the file doc/FLOSS-exception.txt in this software distribution, or
18 * online at http://secondlife.com/developers/opensource/flossexception
19 *
20 * By copying, modifying or distributing this software, you acknowledge
21 * that you have read and understood your obligations described above,
22 * and agree to abide by those obligations.
23 *
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE.
27 */
28
29#ifndef LL_LLHTMLHELP_H
30#define LL_LLHTMLHELP_H
31
32class LLHtmlHelp
33{
34public:
35 virtual ~LLHtmlHelp() {}
36 virtual void show(std::string start_url = "")=0;
37 virtual BOOL getFloaterOpened()=0;
38};
39
40#endif // LL_LLFLOATERHTMLHELP_H
diff --git a/linden/indra/llui/lliconctrl.cpp b/linden/indra/llui/lliconctrl.cpp
index 7dbd2bf..2d3071b 100644
--- a/linden/indra/llui/lliconctrl.cpp
+++ b/linden/indra/llui/lliconctrl.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lliconctrl.h b/linden/indra/llui/lliconctrl.h
index e0a2df0..8dbe6db 100644
--- a/linden/indra/llui/lliconctrl.h
+++ b/linden/indra/llui/lliconctrl.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llkeywords.cpp b/linden/indra/llui/llkeywords.cpp
index 05ec652..8997bd6 100644
--- a/linden/indra/llui/llkeywords.cpp
+++ b/linden/indra/llui/llkeywords.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2000-2007, Linden Research, Inc. 5 * Copyright (c) 2000-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llkeywords.h b/linden/indra/llui/llkeywords.h
index dc2745e..040df53 100644
--- a/linden/indra/llui/llkeywords.h
+++ b/linden/indra/llui/llkeywords.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp
index 1ca17fe..ec156ba 100644
--- a/linden/indra/llui/lllineeditor.cpp
+++ b/linden/indra/llui/lllineeditor.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -115,7 +116,7 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
115 S32 max_length_bytes, 116 S32 max_length_bytes,
116 void (*commit_callback)(LLUICtrl* caller, void* user_data ), 117 void (*commit_callback)(LLUICtrl* caller, void* user_data ),
117 void (*keystroke_callback)(LLLineEditor* caller, void* user_data ), 118 void (*keystroke_callback)(LLLineEditor* caller, void* user_data ),
118 void (*focus_lost_callback)(LLLineEditor* caller, void* user_data ), 119 void (*focus_lost_callback)(LLUICtrl* caller, void* user_data ),
119 void* userdata, 120 void* userdata,
120 LLLinePrevalidateFunc prevalidate_func, 121 LLLinePrevalidateFunc prevalidate_func,
121 LLViewBorder::EBevel border_bevel, 122 LLViewBorder::EBevel border_bevel,
@@ -132,7 +133,6 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
132 mCommitOnFocusLost( TRUE ), 133 mCommitOnFocusLost( TRUE ),
133 mRevertOnEsc( TRUE ), 134 mRevertOnEsc( TRUE ),
134 mKeystrokeCallback( keystroke_callback ), 135 mKeystrokeCallback( keystroke_callback ),
135 mFocusLostCallback( focus_lost_callback ),
136 mIsSelecting( FALSE ), 136 mIsSelecting( FALSE ),
137 mSelectionStart( 0 ), 137 mSelectionStart( 0 ),
138 mSelectionEnd( 0 ), 138 mSelectionEnd( 0 ),
@@ -166,6 +166,8 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
166 mGLFont = LLFontGL::sSansSerifSmall; 166 mGLFont = LLFontGL::sSansSerifSmall;
167 } 167 }
168 168
169 setFocusLostCallback(focus_lost_callback);
170
169 mMinHPixels = mBorderThickness + UI_LINEEDITOR_H_PAD + mBorderLeft; 171 mMinHPixels = mBorderThickness + UI_LINEEDITOR_H_PAD + mBorderLeft;
170 mMaxHPixels = mRect.getWidth() - mMinHPixels - mBorderThickness - mBorderRight; 172 mMaxHPixels = mRect.getWidth() - mMinHPixels - mBorderThickness - mBorderRight;
171 173
@@ -186,7 +188,6 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
186 188
187LLLineEditor::~LLLineEditor() 189LLLineEditor::~LLLineEditor()
188{ 190{
189 mFocusLostCallback = NULL;
190 mCommitOnFocusLost = FALSE; 191 mCommitOnFocusLost = FALSE;
191 192
192 gFocusMgr.releaseFocusIfNeeded( this ); 193 gFocusMgr.releaseFocusIfNeeded( this );
@@ -211,11 +212,8 @@ LLString LLLineEditor::getWidgetTag() const
211 212
212void LLLineEditor::onFocusLost() 213void LLLineEditor::onFocusLost()
213{ 214{
214 if( mFocusLostCallback ) 215 LLUICtrl::onFocusLost();
215 { 216
216 mFocusLostCallback( this, mCallbackUserData );
217 }
218
219 if( mCommitOnFocusLost && mText.getString() != mPrevText) 217 if( mCommitOnFocusLost && mText.getString() != mPrevText)
220 { 218 {
221 onCommit(); 219 onCommit();
@@ -502,7 +500,7 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
502 startSelection(); 500 startSelection();
503 } 501 }
504 502
505 gFocusMgr.setMouseCapture( this, &LLLineEditor::onMouseCaptureLost ); 503 gFocusMgr.setMouseCapture( this );
506 } 504 }
507 505
508 // delay cursor flashing 506 // delay cursor flashing
@@ -515,14 +513,14 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
515BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask) 513BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask)
516{ 514{
517 BOOL handled = FALSE; 515 BOOL handled = FALSE;
518 if (gFocusMgr.getMouseCapture() != this && (x < mBorderLeft || x > (mRect.getWidth() - mBorderRight))) 516 if (!hasMouseCapture() && (x < mBorderLeft || x > (mRect.getWidth() - mBorderRight)))
519 { 517 {
520 return LLUICtrl::handleHover(x, y, mask); 518 return LLUICtrl::handleHover(x, y, mask);
521 } 519 }
522 520
523 if( getVisible() ) 521 if( getVisible() )
524 { 522 {
525 if( (gFocusMgr.getMouseCapture() == this) && mIsSelecting ) 523 if( (hasMouseCapture()) && mIsSelecting )
526 { 524 {
527 if (x != mLastSelectionX || y != mLastSelectionY) 525 if (x != mLastSelectionX || y != mLastSelectionY)
528 { 526 {
@@ -580,9 +578,9 @@ BOOL LLLineEditor::handleMouseUp(S32 x, S32 y, MASK mask)
580{ 578{
581 BOOL handled = FALSE; 579 BOOL handled = FALSE;
582 580
583 if( gFocusMgr.getMouseCapture() == this ) 581 if( hasMouseCapture() )
584 { 582 {
585 gFocusMgr.setMouseCapture( NULL, NULL ); 583 gFocusMgr.setMouseCapture( NULL );
586 handled = TRUE; 584 handled = TRUE;
587 } 585 }
588 586
@@ -1916,11 +1914,9 @@ BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
1916 return rv; 1914 return rv;
1917} 1915}
1918 1916
1919//static 1917void LLLineEditor::onMouseCaptureLost()
1920void LLLineEditor::onMouseCaptureLost( LLMouseHandler* old_captor )
1921{ 1918{
1922 LLLineEditor* self = (LLLineEditor*) old_captor; 1919 endSelection();
1923 self->endSelection();
1924} 1920}
1925 1921
1926 1922
@@ -1935,11 +1931,6 @@ void LLLineEditor::setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor*
1935 mKeystrokeCallback = keystroke_callback; 1931 mKeystrokeCallback = keystroke_callback;
1936} 1932}
1937 1933
1938void LLLineEditor::setFocusLostCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data))
1939{
1940 mFocusLostCallback = keystroke_callback;
1941}
1942
1943// virtual 1934// virtual
1944LLXMLNodePtr LLLineEditor::getXML(bool save_children) const 1935LLXMLNodePtr LLLineEditor::getXML(bool save_children) const
1945{ 1936{
diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h
index 427860d..65c75ab 100644
--- a/linden/indra/llui/lllineeditor.h
+++ b/linden/indra/llui/lllineeditor.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -70,7 +71,7 @@ public:
70 S32 max_length_bytes = 254, 71 S32 max_length_bytes = 254,
71 void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL, 72 void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL,
72 void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL, 73 void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL,
73 void (*focus_lost_callback)(LLLineEditor* caller, void* user_data) = NULL, 74 void (*focus_lost_callback)(LLUICtrl* caller, void* user_data) = NULL,
74 void* userdata = NULL, 75 void* userdata = NULL,
75 LLLinePrevalidateFunc prevalidate_func = NULL, 76 LLLinePrevalidateFunc prevalidate_func = NULL,
76 LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN, 77 LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN,
@@ -91,6 +92,7 @@ public:
91 /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask); 92 /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask);
92 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent ); 93 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent );
93 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent); 94 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent);
95 /*virtual*/ void onMouseCaptureLost();
94 96
95 // LLEditMenuHandler overrides 97 // LLEditMenuHandler overrides
96 virtual void cut(); 98 virtual void cut();
@@ -185,7 +187,6 @@ public:
185 void setSelectAllonFocusReceived(BOOL b); 187 void setSelectAllonFocusReceived(BOOL b);
186 188
187 void setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data)); 189 void setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data));
188 void setFocusLostCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data));
189 190
190 void setMaxTextLength(S32 max_text_length); 191 void setMaxTextLength(S32 max_text_length);
191 void setBorderWidth(S32 left, S32 right); 192 void setBorderWidth(S32 left, S32 right);
@@ -205,8 +206,6 @@ public:
205 206
206 static BOOL postvalidateFloat(const LLString &str); 207 static BOOL postvalidateFloat(const LLString &str);
207 208
208 static void onMouseCaptureLost( LLMouseHandler* old_captor );
209
210protected: 209protected:
211 void removeChar(); 210 void removeChar();
212 void addChar(const llwchar c); 211 void addChar(const llwchar c);
@@ -241,7 +240,6 @@ protected:
241 BOOL mRevertOnEsc; 240 BOOL mRevertOnEsc;
242 241
243 void (*mKeystrokeCallback)( LLLineEditor* caller, void* userdata ); 242 void (*mKeystrokeCallback)( LLLineEditor* caller, void* userdata );
244 void (*mFocusLostCallback)( LLLineEditor* caller, void* userdata );
245 243
246 BOOL mIsSelecting; // Selection for clipboard operations 244 BOOL mIsSelecting; // Selection for clipboard operations
247 S32 mSelectionStart; 245 S32 mSelectionStart;
diff --git a/linden/indra/llui/llmemberlistener.h b/linden/indra/llui/llmemberlistener.h
index 93bcff5..92e7278 100755
--- a/linden/indra/llui/llmemberlistener.h
+++ b/linden/indra/llui/llmemberlistener.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llmenugl.cpp b/linden/indra/llui/llmenugl.cpp
index 1748956..1920aac 100644
--- a/linden/indra/llui/llmenugl.cpp
+++ b/linden/indra/llui/llmenugl.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -3254,6 +3255,7 @@ LLPieMenu::LLPieMenu(const LLString& name, const LLString& label)
3254 mUseInfiniteRadius(FALSE), 3255 mUseInfiniteRadius(FALSE),
3255 mHoverItem(NULL), 3256 mHoverItem(NULL),
3256 mHoverThisFrame(FALSE), 3257 mHoverThisFrame(FALSE),
3258 mHoveredAnyItem(FALSE),
3257 mOuterRingAlpha(1.f), 3259 mOuterRingAlpha(1.f),
3258 mCurRadius(0.f), 3260 mCurRadius(0.f),
3259 mRightMouseDown(FALSE) 3261 mRightMouseDown(FALSE)
@@ -3268,6 +3270,7 @@ LLPieMenu::LLPieMenu(const LLString& name)
3268 mUseInfiniteRadius(FALSE), 3270 mUseInfiniteRadius(FALSE),
3269 mHoverItem(NULL), 3271 mHoverItem(NULL),
3270 mHoverThisFrame(FALSE), 3272 mHoverThisFrame(FALSE),
3273 mHoveredAnyItem(FALSE),
3271 mOuterRingAlpha(1.f), 3274 mOuterRingAlpha(1.f),
3272 mCurRadius(0.f), 3275 mCurRadius(0.f),
3273 mRightMouseDown(FALSE) 3276 mRightMouseDown(FALSE)
@@ -3338,12 +3341,12 @@ BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask )
3338 3341
3339 // release mouse capture after short period of visibility if we're using a finite boundary 3342 // release mouse capture after short period of visibility if we're using a finite boundary
3340 // so that right click outside of boundary will trigger new pie menu 3343 // so that right click outside of boundary will trigger new pie menu
3341 if (gFocusMgr.getMouseCapture() == this && 3344 if (hasMouseCapture() &&
3342 !mRightMouseDown && 3345 !mRightMouseDown &&
3343 mShrinkBorderTimer.getStarted() && 3346 mShrinkBorderTimer.getStarted() &&
3344 mShrinkBorderTimer.getElapsedTimeF32() >= PIE_SHRINK_TIME) 3347 mShrinkBorderTimer.getElapsedTimeF32() >= PIE_SHRINK_TIME)
3345 { 3348 {
3346 gFocusMgr.setMouseCapture(NULL, NULL); 3349 gFocusMgr.setMouseCapture(NULL);
3347 mUseInfiniteRadius = FALSE; 3350 mUseInfiniteRadius = FALSE;
3348 } 3351 }
3349 3352
@@ -3395,6 +3398,7 @@ BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask )
3395 break; 3398 break;
3396 } 3399 }
3397 } 3400 }
3401 mHoveredAnyItem = TRUE;
3398 } 3402 }
3399 else 3403 else
3400 { 3404 {
@@ -3456,7 +3460,7 @@ BOOL LLPieMenu::handleRightMouseDown(S32 x, S32 y, MASK mask)
3456 if (clicked_in_pie) 3460 if (clicked_in_pie)
3457 { 3461 {
3458 // capture mouse cursor as if on initial menu show 3462 // capture mouse cursor as if on initial menu show
3459 gFocusMgr.setMouseCapture(this, NULL); 3463 gFocusMgr.setMouseCapture(this);
3460 mShrinkBorderTimer.stop(); 3464 mShrinkBorderTimer.stop();
3461 mUseInfiniteRadius = TRUE; 3465 mUseInfiniteRadius = TRUE;
3462 handled = TRUE; 3466 handled = TRUE;
@@ -3482,11 +3486,22 @@ BOOL LLPieMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )
3482 mShrinkBorderTimer.getElapsedTimeF32() > PIE_SHRINK_TIME) 3486 mShrinkBorderTimer.getElapsedTimeF32() > PIE_SHRINK_TIME)
3483 { 3487 {
3484 mUseInfiniteRadius = FALSE; 3488 mUseInfiniteRadius = FALSE;
3485 gFocusMgr.setMouseCapture(NULL, NULL); 3489 gFocusMgr.setMouseCapture(NULL);
3486 } 3490 }
3487 3491
3492 S32 delta_x = x /*+ mShiftHoriz*/ - getLocalRect().getCenterX();
3493 S32 delta_y = y /*+ mShiftVert*/ - getLocalRect().getCenterY();
3494 if (!mHoveredAnyItem && !mFirstMouseDown && (delta_x * delta_x) + (delta_y * delta_y) < PIE_CENTER_SIZE * PIE_CENTER_SIZE)
3495 {
3496 // user released right mouse button in middle of pie, interpret this as closing the menu
3497 sMenuContainer->hideMenus();
3498 return TRUE;
3499 }
3500
3501
3488 BOOL result = handleMouseUp( x, y, mask ); 3502 BOOL result = handleMouseUp( x, y, mask );
3489 mRightMouseDown = FALSE; 3503 mRightMouseDown = FALSE;
3504 mHoveredAnyItem = FALSE;
3490 3505
3491 return result; 3506 return result;
3492} 3507}
@@ -3893,6 +3908,8 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down)
3893 mRightMouseDown = mouse_down; 3908 mRightMouseDown = mouse_down;
3894 mFirstMouseDown = mouse_down; 3909 mFirstMouseDown = mouse_down;
3895 mUseInfiniteRadius = TRUE; 3910 mUseInfiniteRadius = TRUE;
3911 mHoveredAnyItem = FALSE;
3912
3896 if (!mFirstMouseDown) 3913 if (!mFirstMouseDown)
3897 { 3914 {
3898 make_ui_sound("UISndPieMenuAppear"); 3915 make_ui_sound("UISndPieMenuAppear");
@@ -3902,7 +3919,7 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down)
3902 3919
3903 // we want all mouse events in case user does quick right click again off of pie menu 3920 // we want all mouse events in case user does quick right click again off of pie menu
3904 // rectangle, to support gestural menu traversal 3921 // rectangle, to support gestural menu traversal
3905 gFocusMgr.setMouseCapture(this, NULL); 3922 gFocusMgr.setMouseCapture(this);
3906 3923
3907 if (mouse_down) 3924 if (mouse_down)
3908 { 3925 {
@@ -3929,10 +3946,11 @@ void LLPieMenu::hide(BOOL item_selected)
3929 mFirstMouseDown = FALSE; 3946 mFirstMouseDown = FALSE;
3930 mRightMouseDown = FALSE; 3947 mRightMouseDown = FALSE;
3931 mUseInfiniteRadius = FALSE; 3948 mUseInfiniteRadius = FALSE;
3949 mHoveredAnyItem = FALSE;
3932 3950
3933 LLView::setVisible(FALSE); 3951 LLView::setVisible(FALSE);
3934 3952
3935 gFocusMgr.setMouseCapture(NULL, NULL); 3953 gFocusMgr.setMouseCapture(NULL);
3936} 3954}
3937 3955
3938///============================================================================ 3956///============================================================================
@@ -4529,6 +4547,7 @@ void LLTearOffMenu::onFocusLost()
4529{ 4547{
4530 // remove highlight from parent item and our own menu 4548 // remove highlight from parent item and our own menu
4531 mMenu->clearHoverItem(); 4549 mMenu->clearHoverItem();
4550 LLFloater::onFocusLost();
4532} 4551}
4533 4552
4534BOOL LLTearOffMenu::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) 4553BOOL LLTearOffMenu::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
diff --git a/linden/indra/llui/llmenugl.h b/linden/indra/llui/llmenugl.h
index c4a0043..6051a26 100644
--- a/linden/indra/llui/llmenugl.h
+++ b/linden/indra/llui/llmenugl.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -691,6 +692,7 @@ private:
691 BOOL mUseInfiniteRadius; // allow picking pie menu items anywhere outside of center circle 692 BOOL mUseInfiniteRadius; // allow picking pie menu items anywhere outside of center circle
692 LLMenuItemGL* mHoverItem; 693 LLMenuItemGL* mHoverItem;
693 BOOL mHoverThisFrame; 694 BOOL mHoverThisFrame;
695 BOOL mHoveredAnyItem;
694 LLFrameTimer mShrinkBorderTimer; 696 LLFrameTimer mShrinkBorderTimer;
695 F32 mOuterRingAlpha; // for rendering pie menus as both bounded and unbounded 697 F32 mOuterRingAlpha; // for rendering pie menus as both bounded and unbounded
696 F32 mCurRadius; 698 F32 mCurRadius;
diff --git a/linden/indra/llui/llmodaldialog.cpp b/linden/indra/llui/llmodaldialog.cpp
index c875e7c..788dead 100644
--- a/linden/indra/llui/llmodaldialog.cpp
+++ b/linden/indra/llui/llmodaldialog.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -84,8 +85,8 @@ void LLModalDialog::startModal()
84 } 85 }
85 86
86 // This is a modal dialog. It sucks up all mouse and keyboard operations. 87 // This is a modal dialog. It sucks up all mouse and keyboard operations.
87 gFocusMgr.setMouseCapture( this, NULL ); 88 gFocusMgr.setMouseCapture( this );
88 gFocusMgr.setTopView( this, NULL ); 89 gFocusMgr.setTopCtrl( this );
89 setFocus(TRUE); 90 setFocus(TRUE);
90 91
91 sModalStack.push_front( this ); 92 sModalStack.push_front( this );
@@ -126,10 +127,10 @@ void LLModalDialog::setVisible( BOOL visible )
126 if( visible ) 127 if( visible )
127 { 128 {
128 // This is a modal dialog. It sucks up all mouse and keyboard operations. 129 // This is a modal dialog. It sucks up all mouse and keyboard operations.
129 gFocusMgr.setMouseCapture( this, NULL ); 130 gFocusMgr.setMouseCapture( this );
130 131
131 // The dialog view is a root view 132 // The dialog view is a root view
132 gFocusMgr.setTopView( this, NULL ); 133 gFocusMgr.setTopCtrl( this );
133 setFocus( TRUE ); 134 setFocus( TRUE );
134 } 135 }
135 else 136 else
@@ -241,9 +242,9 @@ void LLModalDialog::draw()
241 if (mModal) 242 if (mModal)
242 { 243 {
243 // If we've lost focus to a non-child, get it back ASAP. 244 // If we've lost focus to a non-child, get it back ASAP.
244 if( gFocusMgr.getTopView() != this ) 245 if( gFocusMgr.getTopCtrl() != this )
245 { 246 {
246 gFocusMgr.setTopView( this, NULL); 247 gFocusMgr.setTopCtrl( this );
247 } 248 }
248 249
249 if( !gFocusMgr.childHasKeyboardFocus( this ) ) 250 if( !gFocusMgr.childHasKeyboardFocus( this ) )
@@ -253,7 +254,7 @@ void LLModalDialog::draw()
253 254
254 if( !gFocusMgr.childHasMouseCapture( this ) ) 255 if( !gFocusMgr.childHasMouseCapture( this ) )
255 { 256 {
256 gFocusMgr.setMouseCapture( this, NULL ); 257 gFocusMgr.setMouseCapture( this );
257 } 258 }
258 } 259 }
259 } 260 }
@@ -278,7 +279,7 @@ void LLModalDialog::onAppFocusLost()
278 LLModalDialog* instance = LLModalDialog::sModalStack.front(); 279 LLModalDialog* instance = LLModalDialog::sModalStack.front();
279 if( gFocusMgr.childHasMouseCapture( instance ) ) 280 if( gFocusMgr.childHasMouseCapture( instance ) )
280 { 281 {
281 gFocusMgr.setMouseCapture( NULL, NULL ); 282 gFocusMgr.setMouseCapture( NULL );
282 } 283 }
283 284
284 if( gFocusMgr.childHasKeyboardFocus( instance ) ) 285 if( gFocusMgr.childHasKeyboardFocus( instance ) )
@@ -296,9 +297,9 @@ void LLModalDialog::onAppFocusGained()
296 LLModalDialog* instance = LLModalDialog::sModalStack.front(); 297 LLModalDialog* instance = LLModalDialog::sModalStack.front();
297 298
298 // This is a modal dialog. It sucks up all mouse and keyboard operations. 299 // This is a modal dialog. It sucks up all mouse and keyboard operations.
299 gFocusMgr.setMouseCapture( instance, NULL ); 300 gFocusMgr.setMouseCapture( instance );
300 instance->setFocus(TRUE); 301 instance->setFocus(TRUE);
301 gFocusMgr.setTopView( instance, NULL ); 302 gFocusMgr.setTopCtrl( instance );
302 303
303 instance->centerOnScreen(); 304 instance->centerOnScreen();
304 } 305 }
diff --git a/linden/indra/llui/llmodaldialog.h b/linden/indra/llui/llmodaldialog.h
index 2fc101c..c2564af 100644
--- a/linden/indra/llui/llmodaldialog.h
+++ b/linden/indra/llui/llmodaldialog.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp
index 8d3fba6..9e444c1 100644
--- a/linden/indra/llui/llpanel.cpp
+++ b/linden/indra/llui/llpanel.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h
index d9bd19c..9da942e 100644
--- a/linden/indra/llui/llpanel.h
+++ b/linden/indra/llui/llpanel.h
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2001-2007, Linden Research, Inc. 6 * Copyright (c) 2001-2007, Linden Research, Inc.
7 * 7 *
8 * Second Life Viewer Source Code
8 * The source code in this file ("Source Code") is provided by Linden Lab 9 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0 10 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llradiogroup.cpp b/linden/indra/llui/llradiogroup.cpp
index f52faf9..eda54b1 100644
--- a/linden/indra/llui/llradiogroup.cpp
+++ b/linden/indra/llui/llradiogroup.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llradiogroup.h b/linden/indra/llui/llradiogroup.h
index 9324113..0cd5901 100644
--- a/linden/indra/llui/llradiogroup.h
+++ b/linden/indra/llui/llradiogroup.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llresizebar.cpp b/linden/indra/llui/llresizebar.cpp
index 1298b75..79127a8 100644
--- a/linden/indra/llui/llresizebar.cpp
+++ b/linden/indra/llui/llresizebar.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -40,8 +41,8 @@
40LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side ) 41LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side )
41 : 42 :
42 LLView( name, rect, TRUE ), 43 LLView( name, rect, TRUE ),
43 mDragStartScreenX( 0 ), 44 mDragLastScreenX( 0 ),
44 mDragStartScreenY( 0 ), 45 mDragLastScreenY( 0 ),
45 mLastMouseScreenX( 0 ), 46 mLastMouseScreenX( 0 ),
46 mLastMouseScreenY( 0 ), 47 mLastMouseScreenY( 0 ),
47 mMinWidth( min_width ), 48 mMinWidth( min_width ),
@@ -74,6 +75,8 @@ LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_widt
74 default: 75 default:
75 break; 76 break;
76 } 77 }
78 // this is just a decorator
79 setSaveToXML(FALSE);
77} 80}
78 81
79 82
@@ -83,12 +86,11 @@ BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)
83 { 86 {
84 // Route future Mouse messages here preemptively. (Release on mouse up.) 87 // Route future Mouse messages here preemptively. (Release on mouse up.)
85 // No handler needed for focus lost since this clas has no state that depends on it. 88 // No handler needed for focus lost since this clas has no state that depends on it.
86 gFocusMgr.setMouseCapture( this, NULL ); 89 gFocusMgr.setMouseCapture( this );
87 90
88 //localPointToScreen(x, y, &mDragStartScreenX, &mDragStartScreenX); 91 localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
89 localPointToOtherView(x, y, &mDragStartScreenX, &mDragStartScreenY, getParent()->getParent()); 92 mLastMouseScreenX = mDragLastScreenX;
90 mLastMouseScreenX = mDragStartScreenX; 93 mLastMouseScreenY = mDragLastScreenY;
91 mLastMouseScreenY = mDragStartScreenY;
92 } 94 }
93 95
94 return TRUE; 96 return TRUE;
@@ -99,10 +101,10 @@ BOOL LLResizeBar::handleMouseUp(S32 x, S32 y, MASK mask)
99{ 101{
100 BOOL handled = FALSE; 102 BOOL handled = FALSE;
101 103
102 if( gFocusMgr.getMouseCapture() == this ) 104 if( hasMouseCapture() )
103 { 105 {
104 // Release the mouse 106 // Release the mouse
105 gFocusMgr.setMouseCapture( NULL, NULL ); 107 gFocusMgr.setMouseCapture( NULL );
106 handled = TRUE; 108 handled = TRUE;
107 } 109 }
108 else 110 else
@@ -127,74 +129,73 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
127 BOOL handled = FALSE; 129 BOOL handled = FALSE;
128 130
129 // We only handle the click if the click both started and ended within us 131 // We only handle the click if the click both started and ended within us
130 if( gFocusMgr.getMouseCapture() == this ) 132 if( hasMouseCapture() )
131 { 133 {
132 // *NOTE: this, of course, is fragile 134 S32 screen_x;
133 LLView* floater_view = getParent()->getParent(); 135 S32 screen_y;
134 S32 floater_view_x; 136 localPointToScreen(x, y, &screen_x, &screen_y);
135 S32 floater_view_y;
136 localPointToOtherView(x, y, &floater_view_x, &floater_view_y, floater_view);
137 137
138 S32 delta_x = floater_view_x - mDragStartScreenX; 138 S32 delta_x = screen_x - mDragLastScreenX;
139 S32 delta_y = floater_view_y - mDragStartScreenY; 139 S32 delta_y = screen_y - mDragLastScreenY;
140 140
141 LLCoordGL mouse_dir; 141 LLCoordGL mouse_dir;
142 // use hysteresis on mouse motion to preserve user intent when mouse stops moving 142 // use hysteresis on mouse motion to preserve user intent when mouse stops moving
143 mouse_dir.mX = (floater_view_x == mLastMouseScreenX) ? mLastMouseDir.mX : floater_view_x - mLastMouseScreenX; 143 mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
144 mouse_dir.mY = (floater_view_y == mLastMouseScreenY) ? mLastMouseDir.mY : floater_view_y - mLastMouseScreenY; 144 mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
145 mLastMouseDir = mouse_dir; 145 mLastMouseDir = mouse_dir;
146 mLastMouseScreenX = floater_view_x; 146 mLastMouseScreenX = screen_x;
147 mLastMouseScreenY = floater_view_y; 147 mLastMouseScreenY = screen_y;
148 148
149 // Make sure the mouse in still over the application. We don't want to make the parent 149 // Make sure the mouse in still over the application. We don't want to make the parent
150 // so big that we can't see the resize handle any more. 150 // so big that we can't see the resize handle any more.
151 LLRect valid_rect = floater_view->getRect(); 151 LLRect valid_rect = getRootView()->getRect();
152 LLView* parentView = getParent(); 152 LLView* resizing_view = getParent();
153 if( valid_rect.localPointInRect( floater_view_x, floater_view_y ) && parentView ) 153
154 if( valid_rect.localPointInRect( screen_x, screen_y ) && resizing_view )
154 { 155 {
155 // Resize the parent 156 // Resize the parent
156 LLRect parent_rect = parentView->getRect(); 157 LLRect orig_rect = resizing_view->getRect();
157 LLRect scaled_rect = parent_rect; 158 LLRect scaled_rect = orig_rect;
158 159
159 S32 new_width = parent_rect.getWidth(); 160 S32 new_width = orig_rect.getWidth();
160 S32 new_height = parent_rect.getHeight(); 161 S32 new_height = orig_rect.getHeight();
161 162
162 switch( mSide ) 163 switch( mSide )
163 { 164 {
164 case LEFT: 165 case LEFT:
165 new_width = parent_rect.getWidth() - delta_x; 166 new_width = orig_rect.getWidth() - delta_x;
166 if( new_width < mMinWidth ) 167 if( new_width < mMinWidth )
167 { 168 {
168 new_width = mMinWidth; 169 new_width = mMinWidth;
169 delta_x = parent_rect.getWidth() - mMinWidth; 170 delta_x = orig_rect.getWidth() - mMinWidth;
170 } 171 }
171 scaled_rect.translate(delta_x, 0); 172 scaled_rect.translate(delta_x, 0);
172 break; 173 break;
173 174
174 case TOP: 175 case TOP:
175 new_height = parent_rect.getHeight() + delta_y; 176 new_height = orig_rect.getHeight() + delta_y;
176 if( new_height < mMinHeight ) 177 if( new_height < mMinHeight )
177 { 178 {
178 new_height = mMinHeight; 179 new_height = mMinHeight;
179 delta_y = mMinHeight - parent_rect.getHeight(); 180 delta_y = mMinHeight - orig_rect.getHeight();
180 } 181 }
181 break; 182 break;
182 183
183 case RIGHT: 184 case RIGHT:
184 new_width = parent_rect.getWidth() + delta_x; 185 new_width = orig_rect.getWidth() + delta_x;
185 if( new_width < mMinWidth ) 186 if( new_width < mMinWidth )
186 { 187 {
187 new_width = mMinWidth; 188 new_width = mMinWidth;
188 delta_x = mMinWidth - parent_rect.getWidth(); 189 delta_x = mMinWidth - orig_rect.getWidth();
189 } 190 }
190 break; 191 break;
191 192
192 case BOTTOM: 193 case BOTTOM:
193 new_height = parent_rect.getHeight() - delta_y; 194 new_height = orig_rect.getHeight() - delta_y;
194 if( new_height < mMinHeight ) 195 if( new_height < mMinHeight )
195 { 196 {
196 new_height = mMinHeight; 197 new_height = mMinHeight;
197 delta_y = parent_rect.getHeight() - mMinHeight; 198 delta_y = orig_rect.getHeight() - mMinHeight;
198 } 199 }
199 scaled_rect.translate(0, delta_y); 200 scaled_rect.translate(0, delta_y);
200 break; 201 break;
@@ -202,56 +203,59 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
202 203
203 scaled_rect.mTop = scaled_rect.mBottom + new_height; 204 scaled_rect.mTop = scaled_rect.mBottom + new_height;
204 scaled_rect.mRight = scaled_rect.mLeft + new_width; 205 scaled_rect.mRight = scaled_rect.mLeft + new_width;
205 parentView->setRect(scaled_rect); 206 resizing_view->setRect(scaled_rect);
206
207 S32 snap_delta_x = 0;
208 S32 snap_delta_y = 0;
209 207
210 LLView* snap_view = NULL; 208 LLView* snap_view = NULL;
211 209
212 switch( mSide ) 210 switch( mSide )
213 { 211 {
214 case LEFT: 212 case LEFT:
215 snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 213 snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
216 snap_delta_x -= scaled_rect.mLeft;
217 scaled_rect.mLeft += snap_delta_x;
218 break; 214 break;
219 case TOP: 215 case TOP:
220 snap_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 216 snap_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
221 snap_delta_y -= scaled_rect.mTop;
222 scaled_rect.mTop += snap_delta_y;
223 break; 217 break;
224 case RIGHT: 218 case RIGHT:
225 snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 219 snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
226 snap_delta_x -= scaled_rect.mRight;
227 scaled_rect.mRight += snap_delta_x;
228 break; 220 break;
229 case BOTTOM: 221 case BOTTOM:
230 snap_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 222 snap_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
231 snap_delta_y -= scaled_rect.mBottom;
232 scaled_rect.mBottom += snap_delta_y;
233 break; 223 break;
234 } 224 }
235 225
236 parentView->snappedTo(snap_view); 226 // register "snap" behavior with snapped view
227 resizing_view->snappedTo(snap_view);
237 228
238 parentView->setRect(parent_rect); 229 // restore original rectangle so the appropriate changes are detected
230 resizing_view->setRect(orig_rect);
231 // change view shape as user operation
232 resizing_view->userSetShape(scaled_rect);
239 233
240 parentView->reshape(scaled_rect.getWidth(), scaled_rect.getHeight(), FALSE); 234 // update last valid mouse cursor position based on resized view's actual size
241 parentView->translate(scaled_rect.mLeft - parentView->getRect().mLeft, scaled_rect.mBottom - parentView->getRect().mBottom); 235 LLRect new_rect = resizing_view->getRect();
242 236 switch(mSide)
243 floater_view_x = mDragStartScreenX + delta_x; 237 {
244 floater_view_y = mDragStartScreenY + delta_y; 238 case LEFT:
245 mDragStartScreenX = floater_view_x + snap_delta_x; 239 mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
246 mDragStartScreenY = floater_view_y + snap_delta_y; 240 break;
241 case RIGHT:
242 mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
243 break;
244 case TOP:
245 mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
246 break;
247 case BOTTOM:
248 mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
249 break;
250 default:
251 break;
252 }
247 } 253 }
248 254
249 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
250 handled = TRUE; 255 handled = TRUE;
251 } 256 }
252 else 257 else
253 { 258 {
254 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
255 handled = TRUE; 259 handled = TRUE;
256 } 260 }
257 261
diff --git a/linden/indra/llui/llresizebar.h b/linden/indra/llui/llresizebar.h
index 5862ffc..e1fc0f9 100644
--- a/linden/indra/llui/llresizebar.h
+++ b/linden/indra/llui/llresizebar.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -49,8 +50,8 @@ public:
49 void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; } 50 void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; }
50 51
51protected: 52protected:
52 S32 mDragStartScreenX; 53 S32 mDragLastScreenX;
53 S32 mDragStartScreenY; 54 S32 mDragLastScreenY;
54 S32 mLastMouseScreenX; 55 S32 mLastMouseScreenX;
55 S32 mLastMouseScreenY; 56 S32 mLastMouseScreenY;
56 LLCoordGL mLastMouseDir; 57 LLCoordGL mLastMouseDir;
diff --git a/linden/indra/llui/llresizehandle.cpp b/linden/indra/llui/llresizehandle.cpp
index fc15bcc..d9b8fac 100644
--- a/linden/indra/llui/llresizehandle.cpp
+++ b/linden/indra/llui/llresizehandle.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -42,8 +43,8 @@ const S32 RESIZE_BORDER_WIDTH = 3;
42LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner ) 43LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner )
43 : 44 :
44 LLView( name, rect, TRUE ), 45 LLView( name, rect, TRUE ),
45 mDragStartScreenX( 0 ), 46 mDragLastScreenX( 0 ),
46 mDragStartScreenY( 0 ), 47 mDragLastScreenY( 0 ),
47 mLastMouseScreenX( 0 ), 48 mLastMouseScreenX( 0 ),
48 mLastMouseScreenY( 0 ), 49 mLastMouseScreenY( 0 ),
49 mImage( NULL ), 50 mImage( NULL ),
@@ -66,6 +67,9 @@ LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 mi
66 case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break; 67 case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break;
67 case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break; 68 case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break;
68 } 69 }
70
71 // decorator object, don't serialize
72 setSaveToXML(FALSE);
69} 73}
70 74
71EWidgetType LLResizeHandle::getWidgetType() const 75EWidgetType LLResizeHandle::getWidgetType() const
@@ -88,11 +92,11 @@ BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask)
88 { 92 {
89 // Route future Mouse messages here preemptively. (Release on mouse up.) 93 // Route future Mouse messages here preemptively. (Release on mouse up.)
90 // No handler needed for focus lost since this clas has no state that depends on it. 94 // No handler needed for focus lost since this clas has no state that depends on it.
91 gFocusMgr.setMouseCapture( this, NULL ); 95 gFocusMgr.setMouseCapture( this );
92 96
93 localPointToScreen(x, y, &mDragStartScreenX, &mDragStartScreenY); 97 localPointToScreen(x, y, &mDragLastScreenX, &mDragLastScreenY);
94 mLastMouseScreenX = mDragStartScreenX; 98 mLastMouseScreenX = mDragLastScreenX;
95 mLastMouseScreenY = mDragStartScreenY; 99 mLastMouseScreenY = mDragLastScreenY;
96 } 100 }
97 } 101 }
98 102
@@ -104,10 +108,10 @@ BOOL LLResizeHandle::handleMouseUp(S32 x, S32 y, MASK mask)
104{ 108{
105 BOOL handled = FALSE; 109 BOOL handled = FALSE;
106 110
107 if( gFocusMgr.getMouseCapture() == this ) 111 if( hasMouseCapture() )
108 { 112 {
109 // Release the mouse 113 // Release the mouse
110 gFocusMgr.setMouseCapture( NULL, NULL ); 114 gFocusMgr.setMouseCapture( NULL );
111 handled = TRUE; 115 handled = TRUE;
112 } 116 }
113 else 117 else
@@ -125,7 +129,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
125 BOOL handled = FALSE; 129 BOOL handled = FALSE;
126 130
127 // We only handle the click if the click both started and ended within us 131 // We only handle the click if the click both started and ended within us
128 if( gFocusMgr.getMouseCapture() == this ) 132 if( hasMouseCapture() )
129 { 133 {
130 // Make sure the mouse in still over the application. We don't want to make the parent 134 // Make sure the mouse in still over the application. We don't want to make the parent
131 // so big that we can't see the resize handle any more. 135 // so big that we can't see the resize handle any more.
@@ -133,18 +137,18 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
133 S32 screen_x; 137 S32 screen_x;
134 S32 screen_y; 138 S32 screen_y;
135 localPointToScreen(x, y, &screen_x, &screen_y); 139 localPointToScreen(x, y, &screen_x, &screen_y);
136 const LLRect& valid_rect = gFloaterView->getRect(); // Assumes that the parent is a floater. 140 const LLRect valid_rect = getRootView()->getRect();
137 screen_x = llclamp( screen_x, valid_rect.mLeft, valid_rect.mRight ); 141 screen_x = llclamp( screen_x, valid_rect.mLeft, valid_rect.mRight );
138 screen_y = llclamp( screen_y, valid_rect.mBottom, valid_rect.mTop ); 142 screen_y = llclamp( screen_y, valid_rect.mBottom, valid_rect.mTop );
139 143
140 LLView* parentView = getParent(); 144 LLView* resizing_view = getParent();
141 if( parentView ) 145 if( resizing_view )
142 { 146 {
143 // Resize the parent 147 // Resize the parent
144 LLRect parent_rect = parentView->getRect(); 148 LLRect orig_rect = resizing_view->getRect();
145 LLRect scaled_rect = parent_rect; 149 LLRect scaled_rect = orig_rect;
146 S32 delta_x = screen_x - mDragStartScreenX; 150 S32 delta_x = screen_x - mDragLastScreenX;
147 S32 delta_y = screen_y - mDragStartScreenY; 151 S32 delta_y = screen_y - mDragLastScreenY;
148 LLCoordGL mouse_dir; 152 LLCoordGL mouse_dir;
149 // use hysteresis on mouse motion to preserve user intent when mouse stops moving 153 // use hysteresis on mouse motion to preserve user intent when mouse stops moving
150 mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX; 154 mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
@@ -175,18 +179,18 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
175 break; 179 break;
176 } 180 }
177 181
178 S32 new_width = parent_rect.getWidth() + x_multiple * delta_x; 182 S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
179 if( new_width < mMinWidth ) 183 if( new_width < mMinWidth )
180 { 184 {
181 new_width = mMinWidth; 185 new_width = mMinWidth;
182 delta_x = x_multiple * (mMinWidth - parent_rect.getWidth()); 186 delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
183 } 187 }
184 188
185 S32 new_height = parent_rect.getHeight() + y_multiple * delta_y; 189 S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
186 if( new_height < mMinHeight ) 190 if( new_height < mMinHeight )
187 { 191 {
188 new_height = mMinHeight; 192 new_height = mMinHeight;
189 delta_y = y_multiple * (mMinHeight - parent_rect.getHeight()); 193 delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
190 } 194 }
191 195
192 switch( mCorner ) 196 switch( mCorner )
@@ -207,10 +211,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
207 // temporarily set new parent rect 211 // temporarily set new parent rect
208 scaled_rect.mRight = scaled_rect.mLeft + new_width; 212 scaled_rect.mRight = scaled_rect.mLeft + new_width;
209 scaled_rect.mTop = scaled_rect.mBottom + new_height; 213 scaled_rect.mTop = scaled_rect.mBottom + new_height;
210 parentView->setRect(scaled_rect); 214 resizing_view->setRect(scaled_rect);
211
212 S32 snap_delta_x = 0;
213 S32 snap_delta_y = 0;
214 215
215 LLView* snap_view = NULL; 216 LLView* snap_view = NULL;
216 LLView* test_view = NULL; 217 LLView* test_view = NULL;
@@ -219,77 +220,78 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
219 switch(mCorner) 220 switch(mCorner)
220 { 221 {
221 case LEFT_TOP: 222 case LEFT_TOP:
222 snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 223 snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
223 snap_delta_x -= scaled_rect.mLeft; 224 test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
224 test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
225 snap_delta_y -= scaled_rect.mTop;
226 if (!snap_view) 225 if (!snap_view)
227 { 226 {
228 snap_view = test_view; 227 snap_view = test_view;
229 } 228 }
230 scaled_rect.mLeft += snap_delta_x;
231 scaled_rect.mTop += snap_delta_y;
232 break; 229 break;
233 case LEFT_BOTTOM: 230 case LEFT_BOTTOM:
234 snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 231 snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
235 snap_delta_x -= scaled_rect.mLeft; 232 test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
236 test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
237 snap_delta_y -= scaled_rect.mBottom;
238 if (!snap_view) 233 if (!snap_view)
239 { 234 {
240 snap_view = test_view; 235 snap_view = test_view;
241 } 236 }
242 scaled_rect.mLeft += snap_delta_x;
243 scaled_rect.mBottom += snap_delta_y;
244 break; 237 break;
245 case RIGHT_TOP: 238 case RIGHT_TOP:
246 snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 239 snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
247 snap_delta_x -= scaled_rect.mRight; 240 test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
248 test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
249 snap_delta_y -= scaled_rect.mTop;
250 if (!snap_view) 241 if (!snap_view)
251 { 242 {
252 snap_view = test_view; 243 snap_view = test_view;
253 } 244 }
254 scaled_rect.mRight += snap_delta_x;
255 scaled_rect.mTop += snap_delta_y;
256 break; 245 break;
257 case RIGHT_BOTTOM: 246 case RIGHT_BOTTOM:
258 snap_view = parentView->findSnapEdge(snap_delta_x, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin")); 247 snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
259 snap_delta_x -= scaled_rect.mRight; 248 test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
260 test_view = parentView->findSnapEdge(snap_delta_y, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
261 snap_delta_y -= scaled_rect.mBottom;
262 if (!snap_view) 249 if (!snap_view)
263 { 250 {
264 snap_view = test_view; 251 snap_view = test_view;
265 } 252 }
266 scaled_rect.mRight += snap_delta_x;
267 scaled_rect.mBottom += snap_delta_y;
268 break; 253 break;
269 } 254 }
270 255
271 parentView->snappedTo(snap_view); 256 // register "snap" behavior with snapped view
257 resizing_view->snappedTo(snap_view);
272 258
273 // reset parent rect 259 // reset parent rect
274 parentView->setRect(parent_rect); 260 resizing_view->setRect(orig_rect);
275 261
276 // translate and scale to new shape 262 // translate and scale to new shape
277 parentView->reshape(scaled_rect.getWidth(), scaled_rect.getHeight(), FALSE); 263 resizing_view->userSetShape(scaled_rect);
278 parentView->translate(scaled_rect.mLeft - parentView->getRect().mLeft, scaled_rect.mBottom - parentView->getRect().mBottom);
279 264
280 screen_x = mDragStartScreenX + delta_x + snap_delta_x; 265 // update last valid mouse cursor position based on resized view's actual size
281 screen_y = mDragStartScreenY + delta_y + snap_delta_y; 266 LLRect new_rect = resizing_view->getRect();
282 mDragStartScreenX = screen_x; 267 switch(mCorner)
283 mDragStartScreenY = screen_y; 268 {
269 case LEFT_TOP:
270 mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
271 mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
272 break;
273 case LEFT_BOTTOM:
274 mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
275 mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
276 break;
277 case RIGHT_TOP:
278 mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
279 mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
280 break;
281 case RIGHT_BOTTOM:
282 mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
283 mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
284 break;
285 default:
286 break;
287 }
284 } 288 }
285 289
286 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active) " << llendl;
287 handled = TRUE; 290 handled = TRUE;
288 } 291 }
289 else 292 else
290 if( getVisible() && pointInHandle( x, y ) ) 293 if( getVisible() && pointInHandle( x, y ) )
291 { 294 {
292 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive) " << llendl;
293 handled = TRUE; 295 handled = TRUE;
294 } 296 }
295 297
diff --git a/linden/indra/llui/llresizehandle.h b/linden/indra/llui/llresizehandle.h
index dcde8e6..b091f1f 100644
--- a/linden/indra/llui/llresizehandle.h
+++ b/linden/indra/llui/llresizehandle.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -56,8 +57,8 @@ protected:
56 BOOL pointInHandle( S32 x, S32 y ); 57 BOOL pointInHandle( S32 x, S32 y );
57 58
58protected: 59protected:
59 S32 mDragStartScreenX; 60 S32 mDragLastScreenX;
60 S32 mDragStartScreenY; 61 S32 mDragLastScreenY;
61 S32 mLastMouseScreenX; 62 S32 mLastMouseScreenX;
62 S32 mLastMouseScreenY; 63 S32 mLastMouseScreenY;
63 LLCoordGL mLastMouseDir; 64 LLCoordGL mLastMouseDir;
diff --git a/linden/indra/llui/llresmgr.cpp b/linden/indra/llui/llresmgr.cpp
index a73b487..2350093 100644
--- a/linden/indra/llui/llresmgr.cpp
+++ b/linden/indra/llui/llresmgr.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -440,8 +441,8 @@ const LLString LLLocale::SYSTEM_LOCALE("English_United States.1252");
440const LLString LLLocale::USER_LOCALE("en_US.iso8859-1");// = LLString::null; 441const LLString LLLocale::USER_LOCALE("en_US.iso8859-1");// = LLString::null;
441const LLString LLLocale::SYSTEM_LOCALE("en_US.iso8859-1"); 442const LLString LLLocale::SYSTEM_LOCALE("en_US.iso8859-1");
442#else // LL_LINUX likes this 443#else // LL_LINUX likes this
443const LLString LLLocale::USER_LOCALE("en_US.utf8");// = LLString::null; 444const LLString LLLocale::USER_LOCALE("en_US.utf8");
444const LLString LLLocale::SYSTEM_LOCALE("en_US.utf8"); 445const LLString LLLocale::SYSTEM_LOCALE("C");
445#endif 446#endif
446 447
447 448
diff --git a/linden/indra/llui/llresmgr.h b/linden/indra/llui/llresmgr.h
index 0bb4e0d..836d352 100644
--- a/linden/indra/llui/llresmgr.h
+++ b/linden/indra/llui/llresmgr.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llrootview.cpp b/linden/indra/llui/llrootview.cpp
index 49e512c..d78244d 100644
--- a/linden/indra/llui/llrootview.cpp
+++ b/linden/indra/llui/llrootview.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llrootview.h b/linden/indra/llui/llrootview.h
index 84a989b..ce98006 100644
--- a/linden/indra/llui/llrootview.h
+++ b/linden/indra/llui/llrootview.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llscrollbar.cpp b/linden/indra/llui/llscrollbar.cpp
index 578fdb1..4edf81e 100644
--- a/linden/indra/llui/llscrollbar.cpp
+++ b/linden/indra/llui/llscrollbar.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -233,7 +234,7 @@ BOOL LLScrollbar::handleMouseDown(S32 x, S32 y, MASK mask)
233 { 234 {
234 // Start dragging the thumb 235 // Start dragging the thumb
235 // No handler needed for focus lost since this clas has no state that depends on it. 236 // No handler needed for focus lost since this clas has no state that depends on it.
236 gFocusMgr.setMouseCapture( this, NULL ); 237 gFocusMgr.setMouseCapture( this );
237 mDragStartX = x; 238 mDragStartX = x;
238 mDragStartY = y; 239 mDragStartY = y;
239 mOrigRect.mTop = mThumbRect.mTop; 240 mOrigRect.mTop = mThumbRect.mTop;
@@ -274,7 +275,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
274 // because they'll capture the mouse whenever they need hover events. 275 // because they'll capture the mouse whenever they need hover events.
275 276
276 BOOL handled = FALSE; 277 BOOL handled = FALSE;
277 if( gFocusMgr.getMouseCapture() == this ) 278 if( hasMouseCapture() )
278 { 279 {
279 S32 height = mRect.getHeight(); 280 S32 height = mRect.getHeight();
280 S32 width = mRect.getWidth(); 281 S32 width = mRect.getWidth();
@@ -427,9 +428,9 @@ BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
427BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask) 428BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask)
428{ 429{
429 BOOL handled = FALSE; 430 BOOL handled = FALSE;
430 if( gFocusMgr.getMouseCapture() == this ) 431 if( hasMouseCapture() )
431 { 432 {
432 gFocusMgr.setMouseCapture( NULL, NULL ); 433 gFocusMgr.setMouseCapture( NULL );
433 handled = TRUE; 434 handled = TRUE;
434 } 435 }
435 else 436 else
@@ -461,7 +462,7 @@ void LLScrollbar::draw()
461 462
462 screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); 463 screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
463 BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; 464 BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this;
464 BOOL hovered = mEnabled && !other_captor && (gFocusMgr.getMouseCapture() == this || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); 465 BOOL hovered = mEnabled && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y));
465 if (hovered) 466 if (hovered)
466 { 467 {
467 mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); 468 mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f));
diff --git a/linden/indra/llui/llscrollbar.h b/linden/indra/llui/llscrollbar.h
index b7689ea..f6ac17d 100644
--- a/linden/indra/llui/llscrollbar.h
+++ b/linden/indra/llui/llscrollbar.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llscrollcontainer.cpp b/linden/indra/llui/llscrollcontainer.cpp
index 73be607..cf43ee1 100644
--- a/linden/indra/llui/llscrollcontainer.cpp
+++ b/linden/indra/llui/llscrollcontainer.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -456,7 +457,7 @@ void LLScrollableContainerView::draw()
456 // auto-focus when scrollbar active 457 // auto-focus when scrollbar active
457 // this allows us to capture user intent (i.e. stop automatically scrolling the view/etc) 458 // this allows us to capture user intent (i.e. stop automatically scrolling the view/etc)
458 if (!gFocusMgr.childHasKeyboardFocus(this) && 459 if (!gFocusMgr.childHasKeyboardFocus(this) &&
459 (gFocusMgr.getMouseCapture() == mScrollbar[VERTICAL] || gFocusMgr.getMouseCapture() == mScrollbar[HORIZONTAL])) 460 (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture()))
460 { 461 {
461 focusFirstItem(); 462 focusFirstItem();
462 } 463 }
diff --git a/linden/indra/llui/llscrollcontainer.h b/linden/indra/llui/llscrollcontainer.h
index f6bacda..3b3bbef 100644
--- a/linden/indra/llui/llscrollcontainer.h
+++ b/linden/indra/llui/llscrollcontainer.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llscrollingpanellist.cpp b/linden/indra/llui/llscrollingpanellist.cpp
index 209785e..eb806e4 100644
--- a/linden/indra/llui/llscrollingpanellist.cpp
+++ b/linden/indra/llui/llscrollingpanellist.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llscrollingpanellist.h b/linden/indra/llui/llscrollingpanellist.h
index 94e34e6..29e3d41 100644
--- a/linden/indra/llui/llscrollingpanellist.h
+++ b/linden/indra/llui/llscrollingpanellist.h
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (c) 2006-2007, Linden Research, Inc. 4 * Copyright (c) 2006-2007, Linden Research, Inc.
5 * 5 *
6 * Second Life Viewer Source Code
6 * The source code in this file ("Source Code") is provided by Linden Lab 7 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0 8 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement 9 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp
index 4d5c49f..22987dc 100644
--- a/linden/indra/llui/llscrolllistctrl.cpp
+++ b/linden/indra/llui/llscrolllistctrl.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -48,8 +49,11 @@
48#include "llwindow.h" 49#include "llwindow.h"
49#include "llcontrol.h" 50#include "llcontrol.h"
50#include "llkeyboard.h" 51#include "llkeyboard.h"
52#include "llresizebar.h"
51 53
52const S32 LIST_BORDER_PAD = 2; // white space inside the border and to the left of the scrollbar 54const S32 LIST_BORDER_PAD = 2; // white space inside the border and to the left of the scrollbar
55const S32 MIN_COLUMN_WIDTH = 20;
56const S32 LIST_SNAP_PADDING = 5;
53 57
54// local structures & classes. 58// local structures & classes.
55struct SortScrollListItem 59struct SortScrollListItem
@@ -152,6 +156,19 @@ BOOL LLScrollListCheck::handleClick()
152} 156}
153 157
154// 158//
159// LLScrollListSeparator
160//
161LLScrollListSeparator::LLScrollListSeparator(S32 width) : mWidth(width)
162{
163}
164
165void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
166{
167 //*FIXME: use dynamic item heights and make separators narrow, and inactive
168 gl_line_2d(5, 8, llmax(5, width - 5), 8, color);
169}
170
171//
155// LLScrollListText 172// LLScrollListText
156// 173//
157U32 LLScrollListText::sCount = 0; 174U32 LLScrollListText::sCount = 0;
@@ -273,7 +290,7 @@ LLScrollListItem::~LLScrollListItem()
273 std::for_each(mColumns.begin(), mColumns.end(), DeletePointer()); 290 std::for_each(mColumns.begin(), mColumns.end(), DeletePointer());
274} 291}
275 292
276BOOL LLScrollListItem::handleMouseDown(S32 x, S32 y, MASK mask) 293BOOL LLScrollListItem::handleClick(S32 x, S32 y, MASK mask)
277{ 294{
278 BOOL handled = FALSE; 295 BOOL handled = FALSE;
279 296
@@ -374,14 +391,13 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
374 mPageLines(0), 391 mPageLines(0),
375 mHeadingHeight(20), 392 mHeadingHeight(20),
376 mMaxSelectable(0), 393 mMaxSelectable(0),
377 mHeadingFont(NULL),
378 mAllowMultipleSelection( allow_multiple_selection ), 394 mAllowMultipleSelection( allow_multiple_selection ),
379 mAllowKeyboardMovement(TRUE), 395 mAllowKeyboardMovement(TRUE),
380 mCommitOnKeyboardMovement(TRUE), 396 mCommitOnKeyboardMovement(TRUE),
381 mCommitOnSelectionChange(FALSE), 397 mCommitOnSelectionChange(FALSE),
382 mSelectionChanged(FALSE), 398 mSelectionChanged(FALSE),
383 mCanSelect(TRUE), 399 mCanSelect(TRUE),
384 mDisplayColumnButtons(FALSE), 400 mDisplayColumnHeaders(FALSE),
385 mCollapseEmptyColumns(FALSE), 401 mCollapseEmptyColumns(FALSE),
386 mIsPopup(FALSE), 402 mIsPopup(FALSE),
387 mMaxItemCount(INT_MAX), 403 mMaxItemCount(INT_MAX),
@@ -396,21 +412,21 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
396 mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ), 412 mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ),
397 mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ), 413 mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ),
398 mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ), 414 mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ),
415 mHighlightedItem(-1),
399 mBorderThickness( 2 ), 416 mBorderThickness( 2 ),
400 mOnDoubleClickCallback( NULL ), 417 mOnDoubleClickCallback( NULL ),
401 mOnMaximumSelectCallback( NULL ), 418 mOnMaximumSelectCallback( NULL ),
402 mOnSortChangedCallback( NULL ), 419 mOnSortChangedCallback( NULL ),
403 mHighlightedItem(-1), 420 mDrewSelected(FALSE),
404 mBorder(NULL), 421 mBorder(NULL),
405 mDefaultColumn("SIMPLE"),
406 mSearchColumn(0), 422 mSearchColumn(0),
423 mDefaultColumn("SIMPLE"),
407 424
408 mNumDynamicWidthColumns(0), 425 mNumDynamicWidthColumns(0),
409 mTotalStaticColumnWidth(0), 426 mTotalStaticColumnWidth(0),
410 mSortColumn(0), 427 mSortColumn(-1),
411 mSortAscending(TRUE), 428 mSorted(TRUE),
412 429 mSortAscending(TRUE)
413 mDrewSelected(FALSE)
414{ 430{
415 mItemListRect.setOriginAndSize( 431 mItemListRect.setOriginAndSize(
416 mBorderThickness + LIST_BORDER_PAD, 432 mBorderThickness + LIST_BORDER_PAD,
@@ -497,6 +513,7 @@ void LLScrollListCtrl::clearRows()
497 513
498 mScrollLines = 0; 514 mScrollLines = 0;
499 mLastSelected = NULL; 515 mLastSelected = NULL;
516 updateMaxContentWidth(NULL);
500} 517}
501 518
502 519
@@ -546,7 +563,6 @@ S32 LLScrollListCtrl::getFirstSelectedIndex()
546 return -1; 563 return -1;
547} 564}
548 565
549
550LLScrollListItem* LLScrollListCtrl::getFirstData() const 566LLScrollListItem* LLScrollListCtrl::getFirstData() const
551{ 567{
552 if (mItemList.size() == 0) 568 if (mItemList.size() == 0)
@@ -556,6 +572,15 @@ LLScrollListItem* LLScrollListCtrl::getFirstData() const
556 return mItemList[0]; 572 return mItemList[0];
557} 573}
558 574
575LLScrollListItem* LLScrollListCtrl::getLastData() const
576{
577 if (mItemList.size() == 0)
578 {
579 return NULL;
580 }
581 return mItemList[mItemList.size() - 1];
582}
583
559std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const 584std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const
560{ 585{
561 std::vector<LLScrollListItem*> ret; 586 std::vector<LLScrollListItem*> ret;
@@ -573,7 +598,7 @@ void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
573{ 598{
574 LLUICtrl::reshape( width, height, called_from_parent ); 599 LLUICtrl::reshape( width, height, called_from_parent );
575 600
576 S32 heading_size = (mDisplayColumnButtons ? mHeadingHeight : 0); 601 S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
577 602
578 mItemListRect.setOriginAndSize( 603 mItemListRect.setOriginAndSize(
579 mBorderThickness + LIST_BORDER_PAD, 604 mBorderThickness + LIST_BORDER_PAD,
@@ -586,10 +611,8 @@ void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
586 mScrollbar->setPageSize( mPageLines ); 611 mScrollbar->setPageSize( mPageLines );
587 612
588 updateColumns(); 613 updateColumns();
589 updateColumnButtons();
590} 614}
591 615
592
593// Attempt to size the control to show all items. 616// Attempt to size the control to show all items.
594// Do not make larger than width or height. 617// Do not make larger than width or height.
595void LLScrollListCtrl::arrange(S32 max_width, S32 max_height) 618void LLScrollListCtrl::arrange(S32 max_width, S32 max_height)
@@ -621,35 +644,83 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
621 { 644 {
622 case ADD_TOP: 645 case ADD_TOP:
623 mItemList.push_front(item); 646 mItemList.push_front(item);
647 setSorted(FALSE);
624 break; 648 break;
625 649
626 case ADD_SORTED: 650 case ADD_SORTED:
627 mSortColumn = 0; 651 if (mSortColumn == -1)
628 mSortAscending = TRUE; 652 {
653 mSortColumn = 0;
654 mSortAscending = TRUE;
655 }
629 mItemList.push_back(item); 656 mItemList.push_back(item);
630 std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); 657 std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending));
631 break; 658 break;
632 659
633 case ADD_BOTTOM: 660 case ADD_BOTTOM:
634 mItemList.push_back(item); 661 mItemList.push_back(item);
662 setSorted(FALSE);
635 break; 663 break;
636 664
637 default: 665 default:
638 llassert(0); 666 llassert(0);
639 mItemList.push_back(item); 667 mItemList.push_back(item);
668 setSorted(FALSE);
640 break; 669 break;
641 } 670 }
642 671
643 updateLineHeight(); 672 updateLineHeight();
644 mPageLines = mLineHeight ? mItemListRect.getHeight() / mLineHeight : 0; 673 mPageLines = mLineHeight ? mItemListRect.getHeight() / mLineHeight : 0;
645 mScrollbar->setVisible(mPageLines < getItemCount()); 674 BOOL scrollbar_visible = mPageLines < getItemCount();
675
676 if (scrollbar_visible != mScrollbar->getVisible())
677 {
678 mScrollbar->setVisible(mPageLines < getItemCount());
679 updateColumns();
680 }
646 mScrollbar->setPageSize( mPageLines ); 681 mScrollbar->setPageSize( mPageLines );
647 682
648 mScrollbar->setDocSize( getItemCount() ); 683 mScrollbar->setDocSize( getItemCount() );
684
685 updateMaxContentWidth(item);
649 } 686 }
687
650 return not_too_big; 688 return not_too_big;
651} 689}
652 690
691void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item)
692{
693 const S32 HEADING_TEXT_PADDING = 30;
694 const S32 COLUMN_TEXT_PADDING = 20;
695
696 std::map<LLString, LLScrollListColumn>::iterator column_itor;
697 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
698 {
699 LLScrollListColumn* column = &column_itor->second;
700
701 if (!added_item)
702 {
703 // update on all items
704 column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
705 item_list::iterator iter;
706 for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
707 {
708 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
709 if (!cellp) continue;
710
711 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
712 }
713 }
714 else
715 {
716 LLScrollListCell* cellp = added_item->getColumn(column->mIndex);
717 if (!cellp) continue;
718
719 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
720 }
721 }
722}
723
653 724
654// Line height is the max height of all the cells in all the items. 725// Line height is the max height of all the cells in all the items.
655void LLScrollListCtrl::updateLineHeight() 726void LLScrollListCtrl::updateLineHeight()
@@ -678,60 +749,82 @@ void LLScrollListCtrl::updateColumns()
678 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) 749 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
679 { 750 {
680 LLScrollListColumn *column = &column_itor->second; 751 LLScrollListColumn *column = &column_itor->second;
752 S32 new_width = column->mWidth;
681 if (column->mRelWidth >= 0) 753 if (column->mRelWidth >= 0)
682 { 754 {
683 column->mWidth = (S32)llround(column->mRelWidth*mItemListRect.getWidth()); 755 new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
684 } 756 }
685 else if (column->mDynamicWidth) 757 else if (column->mDynamicWidth)
686 { 758 {
687 column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; 759 new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
688 760 }
761
762 if (new_width != column->mWidth)
763 {
764 column->mWidth = new_width;
689 } 765 }
690 mColumnsIndexed[column_itor->second.mIndex] = column; 766 mColumnsIndexed[column_itor->second.mIndex] = column;
691 } 767 }
692}
693 768
694void LLScrollListCtrl::updateColumnButtons() 769 item_list::iterator iter;
695{ 770 for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
696 std::map<LLString, LLScrollListColumn>::iterator column_itor;
697 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
698 { 771 {
699 LLScrollListColumn* column = &column_itor->second; 772 LLScrollListItem *itemp = *iter;
700 LLButton *button = column->mButton; 773 S32 num_cols = itemp->getNumColumns();
701 774 S32 i = 0;
702 if (button) 775 for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i))
703 { 776 {
704 mColumnsIndexed[column->mIndex] = column; 777 if (i >= (S32)mColumnsIndexed.size()) break;
778
779 cell->setWidth(mColumnsIndexed[i]->mWidth);
780 }
781 }
705 782
783 // update headers
784 std::vector<LLScrollListColumn*>::iterator column_ordered_it;
785 S32 left = mItemListRect.mLeft;
786 LLColumnHeader* last_header = NULL;
787 for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it)
788 {
789 if ((*column_ordered_it)->mWidth <= 0)
790 {
791 // skip hidden columns
792 }
793 LLScrollListColumn* column = *column_ordered_it;
794
795 if (column->mHeader)
796 {
797 last_header = column->mHeader;
706 S32 top = mItemListRect.mTop; 798 S32 top = mItemListRect.mTop;
707 S32 left = mItemListRect.mLeft; 799 S32 right = left + column->mWidth;
708 { 800
709 std::map<LLString, LLScrollListColumn>::iterator itor; 801 if (column->mIndex != (S32)mColumnsIndexed.size()-1)
710 for (itor = mColumns.begin(); itor != mColumns.end(); ++itor)
711 {
712 if (itor->second.mIndex < column->mIndex &&
713 itor->second.mWidth > 0)
714 {
715 left += itor->second.mWidth + mColumnPadding;
716 }
717 }
718 }
719 S32 right = left+column->mWidth;
720 if (column->mIndex != (S32)mColumns.size()-1)
721 { 802 {
722 right += mColumnPadding; 803 right += mColumnPadding;
723 } 804 }
724 LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); 805 right = llmax(left, llmin(mItemListRect.getWidth(), right));
725 button->setRect(temp_rect); 806
726 button->setFont(mHeadingFont); 807 S32 header_width = right - left;
727 button->setVisible(mDisplayColumnButtons); 808
809 last_header->reshape(header_width, mHeadingHeight);
810 last_header->translate(left - last_header->getRect().mLeft, top - last_header->getRect().mBottom);
811 last_header->setVisible(mDisplayColumnHeaders && header_width > 0);
812 left = right;
728 } 813 }
729 } 814 }
815
816 // expand last column header we encountered to full list width
817 if (last_header)
818 {
819 S32 header_strip_width = mItemListRect.getWidth() + (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE);
820 S32 new_width = llmax(0, mItemListRect.mLeft + header_strip_width - last_header->getRect().mLeft);
821 last_header->reshape(new_width, last_header->getRect().getHeight());
822 }
730} 823}
731 824
732void LLScrollListCtrl::setDisplayHeading(BOOL display) 825void LLScrollListCtrl::setDisplayHeading(BOOL display)
733{ 826{
734 mDisplayColumnButtons = display; 827 mDisplayColumnHeaders = display;
735 828
736 updateColumns(); 829 updateColumns();
737 830
@@ -745,15 +838,7 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
745 reshape(mRect.getWidth(), mRect.getHeight()); 838 reshape(mRect.getWidth(), mRect.getHeight());
746 839
747 // Resize 840 // Resize
748 mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight()); 841 mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
749
750 updateColumnButtons();
751}
752
753void LLScrollListCtrl::setHeadingFont(const LLFontGL* heading_font)
754{
755 mHeadingFont = heading_font;
756 updateColumnButtons();
757} 842}
758 843
759void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse) 844void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse)
@@ -873,6 +958,7 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index)
873 } 958 }
874 delete itemp; 959 delete itemp;
875 mItemList.erase(mItemList.begin() + target_index); 960 mItemList.erase(mItemList.begin() + target_index);
961 updateMaxContentWidth(NULL);
876} 962}
877 963
878void LLScrollListCtrl::deleteSelectedItems() 964void LLScrollListCtrl::deleteSelectedItems()
@@ -892,6 +978,7 @@ void LLScrollListCtrl::deleteSelectedItems()
892 } 978 }
893 } 979 }
894 mLastSelected = NULL; 980 mLastSelected = NULL;
981 updateMaxContentWidth(NULL);
895} 982}
896 983
897void LLScrollListCtrl::highlightNthItem(S32 target_index) 984void LLScrollListCtrl::highlightNthItem(S32 target_index)
@@ -1033,7 +1120,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
1033 } 1120 }
1034 } 1121 }
1035 1122
1036 if ((mCommitOnSelectionChange || mCommitOnKeyboardMovement)) 1123 if (mCommitOnKeyboardMovement)
1037 { 1124 {
1038 onCommit(); 1125 onCommit();
1039 } 1126 }
@@ -1486,109 +1573,153 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
1486 return handled; 1573 return handled;
1487} 1574}
1488 1575
1489 1576BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
1490BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
1491{ 1577{
1492 BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; 1578 if (!mCanSelect) return FALSE;
1493 1579
1494 // set keyboard focus first, in case click action wants to move focus elsewhere 1580 BOOL selection_changed = FALSE;
1495 setFocus(TRUE);
1496 1581
1497 if( !handled && mCanSelect) 1582 LLScrollListItem* hit_item = hitItem(x, y);
1583 if( hit_item )
1498 { 1584 {
1499 LLScrollListItem* hit_item = hitItem(x, y); 1585 if( mAllowMultipleSelection )
1500 if( hit_item )
1501 { 1586 {
1502 if( mAllowMultipleSelection ) 1587 if (mask & MASK_SHIFT)
1503 { 1588 {
1504 if (mask & MASK_SHIFT) 1589 if (mLastSelected == NULL)
1505 { 1590 {
1506 if (mLastSelected == NULL) 1591 selectItem(hit_item);
1507 { 1592 }
1508 selectItem(hit_item); 1593 else
1509 } 1594 {
1510 else 1595 // Select everthing between mLastSelected and hit_item
1596 bool selecting = false;
1597 item_list::iterator itor;
1598 // If we multiselect backwards, we'll stomp on mLastSelected,
1599 // meaning that we never stop selecting until hitting max or
1600 // the end of the list.
1601 LLScrollListItem* lastSelected = mLastSelected;
1602 for (itor = mItemList.begin(); itor != mItemList.end(); ++itor)
1511 { 1603 {
1512 // Select everthing between mLastSelected and hit_item 1604 if(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable)
1513 bool selecting = false;
1514 item_list::iterator itor;
1515 // If we multiselect backwards, we'll stomp on mLastSelected,
1516 // meaning that we never stop selecting until hitting max or
1517 // the end of the list.
1518 LLScrollListItem* lastSelected = mLastSelected;
1519 for (itor = mItemList.begin(); itor != mItemList.end(); ++itor)
1520 { 1605 {
1521 if(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable) 1606 if(mOnMaximumSelectCallback)
1522 {
1523 if(mOnMaximumSelectCallback)
1524 {
1525 mOnMaximumSelectCallback(mCallbackUserData);
1526 }
1527 break;
1528 }
1529 LLScrollListItem *item = *itor;
1530 if (item == hit_item || item == lastSelected)
1531 {
1532 selectItem(item, FALSE);
1533 selecting = !selecting;
1534 }
1535 if (selecting)
1536 { 1607 {
1537 selectItem(item, FALSE); 1608 mOnMaximumSelectCallback(mCallbackUserData);
1538 } 1609 }
1610 break;
1611 }
1612 LLScrollListItem *item = *itor;
1613 if (item == hit_item || item == lastSelected)
1614 {
1615 selectItem(item, FALSE);
1616 selecting = !selecting;
1617 }
1618 if (selecting)
1619 {
1620 selectItem(item, FALSE);
1539 } 1621 }
1540 } 1622 }
1541 } 1623 }
1542 else if (mask & MASK_CONTROL) 1624 }
1625 else if (mask & MASK_CONTROL)
1626 {
1627 if (hit_item->getSelected())
1628 {
1629 deselectItem(hit_item);
1630 }
1631 else
1543 { 1632 {
1544 if (hit_item->getSelected()) 1633 if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable))
1545 { 1634 {
1546 deselectItem(hit_item); 1635 selectItem(hit_item, FALSE);
1547 } 1636 }
1548 else 1637 else
1549 { 1638 {
1550 if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable)) 1639 if(mOnMaximumSelectCallback)
1551 { 1640 {
1552 selectItem(hit_item, FALSE); 1641 mOnMaximumSelectCallback(mCallbackUserData);
1553 }
1554 else
1555 {
1556 if(mOnMaximumSelectCallback)
1557 {
1558 mOnMaximumSelectCallback(mCallbackUserData);
1559 }
1560 } 1642 }
1561 } 1643 }
1562 } 1644 }
1563 else
1564 {
1565 deselectAllItems(TRUE);
1566 selectItem(hit_item);
1567 }
1568 } 1645 }
1569 else 1646 else
1570 { 1647 {
1648 deselectAllItems(TRUE);
1571 selectItem(hit_item); 1649 selectItem(hit_item);
1572 } 1650 }
1573
1574 hit_item->handleMouseDown(x - mBorderThickness - LIST_BORDER_PAD,
1575 1, mask);
1576 // always commit on mousedown
1577 onCommit();
1578 mSelectionChanged = FALSE;
1579
1580 // clear search string on mouse operations
1581 mSearchString.clear();
1582 } 1651 }
1583 else 1652 else
1584 { 1653 {
1585 mLastSelected = NULL; 1654 selectItem(hit_item);
1586 } 1655 }
1656
1657 hit_item->handleClick(x - mBorderThickness - LIST_BORDER_PAD,
1658 1, mask);
1659
1660 selection_changed = mSelectionChanged;
1661 if (mCommitOnSelectionChange)
1662 {
1663 commitIfChanged();
1664 }
1665
1666 // clear search string on mouse operations
1667 mSearchString.clear();
1668 }
1669 else
1670 {
1671 //mLastSelected = NULL;
1672 //deselectAllItems(TRUE);
1673 }
1674
1675 return selection_changed;
1676}
1677
1678
1679BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
1680{
1681 BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
1682
1683 if( !handled )
1684 {
1685 // set keyboard focus first, in case click action wants to move focus elsewhere
1686 setFocus(TRUE);
1687
1688 // clear selection changed flag so because user is starting a selection operation
1689 mSelectionChanged = FALSE;
1690
1691 gFocusMgr.setMouseCapture(this);
1692 selectItemAt(x, y, mask);
1587 } 1693 }
1588 1694
1589 return TRUE; 1695 return TRUE;
1590} 1696}
1591 1697
1698BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
1699{
1700 if (hasMouseCapture())
1701 {
1702 if(mask == MASK_NONE)
1703 {
1704 selectItemAt(x, y, mask);
1705 }
1706 }
1707
1708 if (hasMouseCapture())
1709 {
1710 gFocusMgr.setMouseCapture(NULL);
1711 }
1712
1713 // always commit when mouse operation is completed inside list
1714 if (mItemListRect.pointInRect(x,y))
1715 {
1716 mSelectionChanged = FALSE;
1717 onCommit();
1718 }
1719
1720 return LLUICtrl::handleMouseUp(x, y, mask);
1721}
1722
1592BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) 1723BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
1593{ 1724{
1594 //BOOL handled = FALSE; 1725 //BOOL handled = FALSE;
@@ -1647,31 +1778,35 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
1647{ 1778{
1648 BOOL handled = FALSE; 1779 BOOL handled = FALSE;
1649 1780
1650 if(getVisible()) 1781 if (hasMouseCapture())
1651 { 1782 {
1652 if (mCanSelect) 1783 if(mask == MASK_NONE)
1653 { 1784 {
1654 LLScrollListItem* item = hitItem(x, y); 1785 selectItemAt(x, y, mask);
1655 if (item)
1656 {
1657 highlightNthItem(getItemIndex(item));
1658 }
1659 else
1660 {
1661 highlightNthItem(-1);
1662 }
1663 } 1786 }
1664 1787 }
1665 handled = LLView::handleHover( x, y, mask ); 1788 else if (mCanSelect)
1666 1789 {
1667 if( !handled ) 1790 LLScrollListItem* item = hitItem(x, y);
1791 if (item)
1792 {
1793 highlightNthItem(getItemIndex(item));
1794 }
1795 else
1668 { 1796 {
1669 // Opaque 1797 highlightNthItem(-1);
1670 getWindow()->setCursor(UI_CURSOR_ARROW);
1671 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
1672 handled = TRUE;
1673 } 1798 }
1674 } 1799 }
1800
1801 handled = LLUICtrl::handleHover( x, y, mask );
1802
1803 //if( !handled )
1804 //{
1805 // // Opaque
1806 // getWindow()->setCursor(UI_CURSOR_ARROW);
1807 // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
1808 // handled = TRUE;
1809 //}
1675 return handled; 1810 return handled;
1676} 1811}
1677 1812
@@ -1980,6 +2115,16 @@ void LLScrollListCtrl::commitIfChanged()
1980 } 2115 }
1981} 2116}
1982 2117
2118void LLScrollListCtrl::setSorted(BOOL sorted)
2119{
2120 mSorted = sorted;
2121}
2122
2123BOOL LLScrollListCtrl::isSorted()
2124{
2125 return mSorted;
2126}
2127
1983// Called by scrollbar 2128// Called by scrollbar
1984//static 2129//static
1985void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata ) 2130void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
@@ -1992,9 +2137,19 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void
1992// First column is column 0 2137// First column is column 0
1993void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending) 2138void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending)
1994{ 2139{
1995 mSortColumn = column; 2140 if (!mSorted || mSortColumn != column)
1996 mSortAscending = ascending; 2141 {
1997 std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); 2142 mSortColumn = column;
2143 std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending));
2144 setSorted(TRUE);
2145 }
2146
2147 // just reverse the list if changing sort order
2148 if(mSortAscending != ascending)
2149 {
2150 std::reverse(mItemList.begin(), mItemList.end());
2151 mSortAscending = ascending;
2152 }
1998} 2153}
1999 2154
2000void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending) 2155void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending)
@@ -2066,7 +2221,7 @@ LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const
2066 2221
2067 node->createChild("draw_border", TRUE)->setBoolValue((mBorder != NULL)); 2222 node->createChild("draw_border", TRUE)->setBoolValue((mBorder != NULL));
2068 2223
2069 node->createChild("draw_heading", TRUE)->setBoolValue(mDisplayColumnButtons); 2224 node->createChild("draw_heading", TRUE)->setBoolValue(mDisplayColumnHeaders);
2070 2225
2071 node->createChild("background_visible", TRUE)->setBoolValue(mBackgroundVisible); 2226 node->createChild("background_visible", TRUE)->setBoolValue(mBackgroundVisible);
2072 2227
@@ -2215,13 +2370,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2215 node->getAttributeS32("heading_height", heading_height); 2370 node->getAttributeS32("heading_height", heading_height);
2216 scroll_list->setHeadingHeight(heading_height); 2371 scroll_list->setHeadingHeight(heading_height);
2217 } 2372 }
2218 if (node->hasAttribute("heading_font"))
2219 {
2220 LLString heading_font("");
2221 node->getAttributeString("heading_font", heading_font);
2222 LLFontGL* gl_font = LLFontGL::fontFromName(heading_font.c_str());
2223 scroll_list->setHeadingFont(gl_font);
2224 }
2225 scroll_list->setCollapseEmptyColumns(collapse_empty_columns); 2373 scroll_list->setCollapseEmptyColumns(collapse_empty_columns);
2226 2374
2227 scroll_list->setScrollListParameters(node); 2375 scroll_list->setScrollListParameters(node);
@@ -2246,6 +2394,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2246 2394
2247 LLString sortname(columnname); 2395 LLString sortname(columnname);
2248 child->getAttributeString("sort", sortname); 2396 child->getAttributeString("sort", sortname);
2397
2398 BOOL sort_ascending = TRUE;
2399 child->getAttributeBOOL("sort_ascending", sort_ascending);
2249 2400
2250 LLString imagename; 2401 LLString imagename;
2251 child->getAttributeString("image", imagename); 2402 child->getAttributeString("image", imagename);
@@ -2267,6 +2418,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2267 2418
2268 columns[index]["name"] = columnname; 2419 columns[index]["name"] = columnname;
2269 columns[index]["sort"] = sortname; 2420 columns[index]["sort"] = sortname;
2421 columns[index]["sort_ascending"] = sort_ascending;
2270 columns[index]["image"] = imagename; 2422 columns[index]["image"] = imagename;
2271 columns[index]["label"] = labelname; 2423 columns[index]["label"] = labelname;
2272 columns[index]["width"] = columnwidth; 2424 columns[index]["width"] = columnwidth;
@@ -2427,10 +2579,17 @@ BOOL LLScrollListCtrl::canDeselect()
2427void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) 2579void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
2428{ 2580{
2429 LLString name = column["name"].asString(); 2581 LLString name = column["name"].asString();
2430 if (mColumns.size() == 0) 2582 if (mColumns.empty())
2431 { 2583 {
2432 mDefaultColumn = 0; 2584 mDefaultColumn = 0;
2433 } 2585 }
2586 // if no column name provided, just use ordinal as name
2587 if (name.empty())
2588 {
2589 std::ostringstream new_name;
2590 new_name << mColumnsIndexed.size();
2591 name = new_name.str();
2592 }
2434 if (mColumns.find(name) == mColumns.end()) 2593 if (mColumns.find(name) == mColumns.end())
2435 { 2594 {
2436 // Add column 2595 // Add column
@@ -2470,30 +2629,28 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
2470 right += mColumnPadding; 2629 right += mColumnPadding;
2471 } 2630 }
2472 LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); 2631 LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top);
2473 new_column->mButton = new LLSquareButton(button_name, temp_rect, "", mHeadingFont, "", onClickColumn, NULL); 2632 new_column->mHeader = new LLColumnHeader(button_name, temp_rect, new_column);
2474 if(column["image"].asString() != "") 2633 if(column["image"].asString() != "")
2475 { 2634 {
2476 //new_column->mButton->setScaleImage(false); 2635 //new_column->mHeader->setScaleImage(false);
2477 new_column->mButton->setImageSelected(column["image"].asString()); 2636 new_column->mHeader->setImage(column["image"].asString());
2478 new_column->mButton->setImageUnselected(column["image"].asString());
2479 } 2637 }
2480 else 2638 else
2481 { 2639 {
2482 new_column->mButton->setLabelSelected(new_column->mLabel); 2640 new_column->mHeader->setLabel(new_column->mLabel);
2483 new_column->mButton->setLabelUnselected(new_column->mLabel); 2641 //new_column->mHeader->setLabel(new_column->mLabel);
2484 } 2642 }
2485 //RN: although it might be useful to change sort order with the keyboard, 2643 //RN: although it might be useful to change sort order with the keyboard,
2486 // mixing tab stops on child items along with the parent item is not supported yet 2644 // mixing tab stops on child items along with the parent item is not supported yet
2487 new_column->mButton->setTabStop(FALSE); 2645 new_column->mHeader->setTabStop(FALSE);
2488 addChild(new_column->mButton); 2646 addChild(new_column->mHeader);
2489 new_column->mButton->setVisible(mDisplayColumnButtons); 2647 new_column->mHeader->setVisible(mDisplayColumnHeaders);
2490 2648
2491 2649
2492 // Move scroll to front 2650 // Move scroll to front
2493 removeChild(mScrollbar); 2651 removeChild(mScrollbar);
2494 addChild(mScrollbar); 2652 addChild(mScrollbar);
2495 2653
2496 new_column->mButton->setCallbackUserData(new_column);
2497 } 2654 }
2498 } 2655 }
2499 updateColumns(); 2656 updateColumns();
@@ -2511,6 +2668,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
2511 U32 column_index = info->mIndex; 2668 U32 column_index = info->mIndex;
2512 2669
2513 LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; 2670 LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
2671 bool ascending = column->mSortAscending;
2514 if (column->mSortingColumn != column->mName) 2672 if (column->mSortingColumn != column->mName)
2515 { 2673 {
2516 if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) 2674 if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end())
@@ -2520,7 +2678,6 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
2520 } 2678 }
2521 } 2679 }
2522 2680
2523 bool ascending = true;
2524 if (column_index == parent->mSortColumn) 2681 if (column_index == parent->mSortColumn)
2525 { 2682 {
2526 ascending = !parent->mSortAscending; 2683 ascending = !parent->mSortAscending;
@@ -2536,7 +2693,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
2536 2693
2537std::string LLScrollListCtrl::getSortColumnName() 2694std::string LLScrollListCtrl::getSortColumnName()
2538{ 2695{
2539 LLScrollListColumn* column = mColumnsIndexed[mSortColumn]; 2696 LLScrollListColumn* column = mSortColumn >= 0 ? mColumnsIndexed[mSortColumn] : NULL;
2540 2697
2541 if (column) return column->mName; 2698 if (column) return column->mName;
2542 else return ""; 2699 else return "";
@@ -2547,11 +2704,11 @@ void LLScrollListCtrl::clearColumns()
2547 std::map<LLString, LLScrollListColumn>::iterator itor; 2704 std::map<LLString, LLScrollListColumn>::iterator itor;
2548 for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) 2705 for (itor = mColumns.begin(); itor != mColumns.end(); ++itor)
2549 { 2706 {
2550 LLButton *button = itor->second.mButton; 2707 LLColumnHeader *header = itor->second.mHeader;
2551 if (button) 2708 if (header)
2552 { 2709 {
2553 removeChild(button); 2710 removeChild(header);
2554 delete button; 2711 delete header;
2555 } 2712 }
2556 } 2713 }
2557 mColumns.clear(); 2714 mColumns.clear();
@@ -2563,14 +2720,22 @@ void LLScrollListCtrl::setColumnLabel(const LLString& column, const LLString& la
2563 if (itor != mColumns.end()) 2720 if (itor != mColumns.end())
2564 { 2721 {
2565 itor->second.mLabel = label; 2722 itor->second.mLabel = label;
2566 if (itor->second.mButton) 2723 if (itor->second.mHeader)
2567 { 2724 {
2568 itor->second.mButton->setLabelSelected(label); 2725 itor->second.mHeader->setLabel(label);
2569 itor->second.mButton->setLabelUnselected(label);
2570 } 2726 }
2571 } 2727 }
2572} 2728}
2573 2729
2730LLScrollListColumn* LLScrollListCtrl::getColumn(S32 index)
2731{
2732 if (index < 0 || index >= (S32)mColumnsIndexed.size())
2733 {
2734 return NULL;
2735 }
2736 return mColumnsIndexed[index];
2737}
2738
2574void LLScrollListCtrl::setColumnHeadings(LLSD headings) 2739void LLScrollListCtrl::setColumnHeadings(LLSD headings)
2575{ 2740{
2576 mColumns.clear(); 2741 mColumns.clear();
@@ -2597,6 +2762,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2597 // Add any columns we don't already have 2762 // Add any columns we don't already have
2598 LLSD columns = value["columns"]; 2763 LLSD columns = value["columns"];
2599 LLSD::array_const_iterator itor; 2764 LLSD::array_const_iterator itor;
2765 S32 col_index = 0 ;
2600 for (itor = columns.beginArray(); itor != columns.endArray(); ++itor) 2766 for (itor = columns.beginArray(); itor != columns.endArray(); ++itor)
2601 { 2767 {
2602 LLString column = (*itor)["column"].asString(); 2768 LLString column = (*itor)["column"].asString();
@@ -2605,21 +2771,39 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2605 { 2771 {
2606 mDefaultColumn = 0; 2772 mDefaultColumn = 0;
2607 } 2773 }
2608 std::map<LLString, LLScrollListColumn>::iterator column_itor = mColumns.find(column); 2774
2609 if (column_itor == mColumns.end()) 2775 LLScrollListColumn* columnp = NULL;
2776
2777 // empty columns strings index by ordinal
2778 if (column.empty())
2779 {
2780 std::ostringstream new_name;
2781 new_name << col_index;
2782 column = new_name.str();
2783 }
2784
2785 std::map<LLString, LLScrollListColumn>::iterator column_itor;
2786 column_itor = mColumns.find(column);
2787 if (column_itor != mColumns.end())
2788 {
2789 columnp = &column_itor->second;
2790 }
2791
2792 // create new column on demand
2793 if (!columnp)
2610 { 2794 {
2611 LLSD new_column; 2795 LLSD new_column;
2612 new_column["name"] = column; 2796 new_column["name"] = column;
2613 new_column["label"] = column; 2797 new_column["label"] = column;
2614 new_column["width"] = 0; 2798 new_column["width"] = (*itor)["width"];
2615 addColumn(new_column); 2799 addColumn(new_column);
2616 column_itor = mColumns.find(column); 2800 columnp = &mColumns.find(column)->second;
2617 new_item->setNumColumns(mColumns.size()); 2801 new_item->setNumColumns(mColumns.size());
2618 } 2802 }
2619 2803
2620 S32 index = column_itor->second.mIndex; 2804 S32 index = columnp->mIndex;
2621 S32 width = column_itor->second.mWidth; 2805 S32 width = columnp->mWidth;
2622 LLFontGL::HAlign font_alignment = column_itor->second.mFontAlignment; 2806 LLFontGL::HAlign font_alignment = columnp->mFontAlignment;
2623 2807
2624 LLSD value = (*itor)["value"]; 2808 LLSD value = (*itor)["value"];
2625 LLString fontname = (*itor)["font"].asString(); 2809 LLString fontname = (*itor)["font"].asString();
@@ -2645,10 +2829,20 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2645 LLRect(0, 0, width, width), "label"); 2829 LLRect(0, 0, width, width), "label");
2646 new_item->setColumn(index, new LLScrollListCheck(ctrl,width)); 2830 new_item->setColumn(index, new LLScrollListCheck(ctrl,width));
2647 } 2831 }
2832 else if (type == "separator")
2833 {
2834 new_item->setColumn(index, new LLScrollListSeparator(width));
2835 }
2648 else 2836 else
2649 { 2837 {
2650 new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment)); 2838 new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment));
2839 if (columnp->mHeader && !value.asString().empty())
2840 {
2841 columnp->mHeader->setHasResizableElement(TRUE);
2842 }
2651 } 2843 }
2844
2845 col_index++;
2652 } 2846 }
2653 2847
2654 S32 num_columns = mColumns.size(); 2848 S32 num_columns = mColumns.size();
@@ -2744,6 +2938,14 @@ void LLScrollListCtrl::setFocus(BOOL b)
2744 } 2938 }
2745 LLUICtrl::setFocus(b); 2939 LLUICtrl::setFocus(b);
2746} 2940}
2941
2942//virtual
2943void LLScrollListCtrl::onFocusReceived()
2944{
2945 // forget latent selection changes when getting focus
2946 mSelectionChanged = FALSE;
2947}
2948
2747//virtual 2949//virtual
2748void LLScrollListCtrl::onFocusLost() 2950void LLScrollListCtrl::onFocusLost()
2749{ 2951{
@@ -2754,5 +2956,411 @@ void LLScrollListCtrl::onFocusLost()
2754 getParent()->onFocusLost(); 2956 getParent()->onFocusLost();
2755 } 2957 }
2756 } 2958 }
2959 if (hasMouseCapture())
2960 {
2961 gFocusMgr.setMouseCapture(NULL);
2962 }
2963 LLUICtrl::onFocusLost();
2757} 2964}
2758 2965
2966LLColumnHeader::LLColumnHeader(const LLString& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL* fontp) :
2967 LLComboBox(label, rect, label, NULL, NULL),
2968 mColumn(column),
2969 mOrigLabel(label),
2970 mShowSortOptions(FALSE),
2971 mHasResizableElement(FALSE)
2972{
2973 mListPosition = LLComboBox::ABOVE;
2974 setCommitCallback(onSelectSort);
2975 setCallbackUserData(this);
2976 mButton->setTabStop(FALSE);
2977 // require at least two frames between mouse down and mouse up event to capture intentional "hold" not just bad framerate
2978 mButton->setHeldDownDelay(LLUI::sConfigGroup->getF32("ColumnHeaderDropDownDelay"), 2);
2979 mButton->setHeldDownCallback(onHeldDown);
2980 mButton->setClickedCallback(onClick);
2981 mButton->setMouseDownCallback(onMouseDown);
2982
2983 mButton->setCallbackUserData(this);
2984
2985 mAscendingText = "[LOW]...[HIGH](Ascending)";
2986 mDescendingText = "[HIGH]...[LOW](Descending)";
2987
2988 mList->reshape(llmax(mList->getRect().getWidth(), 110, mRect.getWidth()), mList->getRect().getHeight());
2989
2990 // resize handles on left and right
2991 const S32 RESIZE_BAR_THICKNESS = 3;
2992 mResizeBar = new LLResizeBar(
2993 "resizebar",
2994 LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
2995 MIN_COLUMN_WIDTH, mRect.getHeight(), LLResizeBar::RIGHT );
2996 addChild(mResizeBar);
2997
2998 mResizeBar->setEnabled(FALSE);
2999}
3000
3001LLColumnHeader::~LLColumnHeader()
3002{
3003}
3004
3005void LLColumnHeader::draw()
3006{
3007 if( getVisible() )
3008 {
3009 mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
3010
3011 BOOL is_ascending = mColumn->mParentCtrl->getSortAscending();
3012 mArrowImage = is_ascending ? LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("up_arrow.tga")))
3013 : LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("down_arrow.tga")));
3014
3015 //BOOL clip = mRect.mRight > mColumn->mParentCtrl->getItemListRect().getWidth();
3016 //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE);
3017
3018 //LLRect column_header_local_rect(-mRect.mLeft, mRect.getHeight(), mColumn->mParentCtrl->getItemListRect().getWidth() - mRect.mLeft, 0);
3019 //LLUI::setScissorRegionLocal(column_header_local_rect);
3020
3021 // Draw children
3022 LLComboBox::draw();
3023
3024 if (mList->getVisible())
3025 {
3026 // sync sort order with list selection every frame
3027 mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, getCurrentIndex() == 0);
3028 }
3029
3030 }
3031}
3032
3033BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask)
3034{
3035 if (canResize() && mResizeBar->getRect().pointInRect(x, y))
3036 {
3037 // reshape column to max content width
3038 LLRect column_rect = getRect();
3039 column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth;
3040 userSetShape(column_rect);
3041 }
3042 else
3043 {
3044 onClick(this);
3045 }
3046 return TRUE;
3047}
3048
3049void LLColumnHeader::setImage(const LLString &image_name)
3050{
3051 if (mButton)
3052 {
3053 mButton->setImageSelected(image_name);
3054 mButton->setImageUnselected(image_name);
3055 }
3056}
3057
3058//static
3059void LLColumnHeader::onClick(void* user_data)
3060{
3061 LLColumnHeader* headerp = (LLColumnHeader*)user_data;
3062 if (!headerp) return;
3063
3064 LLScrollListColumn* column = headerp->mColumn;
3065 if (!column) return;
3066
3067 if (headerp->mList->getVisible())
3068 {
3069 headerp->hideList();
3070 }
3071
3072 LLScrollListCtrl::onClickColumn(column);
3073
3074 // propage new sort order to sort order list
3075 headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1);
3076}
3077
3078//static
3079void LLColumnHeader::onMouseDown(void* user_data)
3080{
3081 // for now, do nothing but block the normal showList() behavior
3082 return;
3083}
3084
3085//static
3086void LLColumnHeader::onHeldDown(void* user_data)
3087{
3088 LLColumnHeader* headerp = (LLColumnHeader*)user_data;
3089 headerp->showList();
3090}
3091
3092void LLColumnHeader::showList()
3093{
3094 if (mShowSortOptions)
3095 {
3096 //LLSD item_val = mColumn->mParentCtrl->getFirstData()->getValue();
3097 mOrigLabel = mButton->getLabelSelected();
3098
3099 // move sort column over to this column and do initial sort
3100 mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, mColumn->mParentCtrl->getSortAscending());
3101
3102 LLString low_item_text;
3103 LLString high_item_text;
3104
3105 LLScrollListItem* itemp = mColumn->mParentCtrl->getFirstData();
3106 if (itemp)
3107 {
3108 LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex);
3109 if (cell && cell->isText())
3110 {
3111 if (mColumn->mParentCtrl->getSortAscending())
3112 {
3113 low_item_text = cell->getText();
3114 }
3115 else
3116 {
3117 high_item_text = cell->getText();
3118 }
3119 }
3120 }
3121
3122 itemp = mColumn->mParentCtrl->getLastData();
3123 if (itemp)
3124 {
3125 LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex);
3126 if (cell && cell->isText())
3127 {
3128 if (mColumn->mParentCtrl->getSortAscending())
3129 {
3130 high_item_text = cell->getText();
3131 }
3132 else
3133 {
3134 low_item_text = cell->getText();
3135 }
3136 }
3137 }
3138
3139 LLString::truncate(low_item_text, 3);
3140 LLString::truncate(high_item_text, 3);
3141
3142 LLString ascending_string;
3143 LLString descending_string;
3144
3145 if (low_item_text.empty() || high_item_text.empty())
3146 {
3147 ascending_string = "Ascending";
3148 descending_string = "Descending";
3149 }
3150 else
3151 {
3152 mAscendingText.setArg("[LOW]", low_item_text);
3153 mAscendingText.setArg("[HIGH]", high_item_text);
3154 mDescendingText.setArg("[LOW]", low_item_text);
3155 mDescendingText.setArg("[HIGH]", high_item_text);
3156 ascending_string = mAscendingText.getString();
3157 descending_string = mDescendingText.getString();
3158 }
3159
3160 S32 text_width = LLFontGL::sSansSerifSmall->getWidth(ascending_string);
3161 text_width = llmax(text_width, LLFontGL::sSansSerifSmall->getWidth(descending_string)) + 10;
3162 text_width = llmax(text_width, mRect.getWidth() - 30);
3163
3164 mList->getColumn(0)->mWidth = text_width;
3165 ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string);
3166 ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string);
3167
3168 mList->reshape(llmax(text_width + 30, 110, mRect.getWidth()), mList->getRect().getHeight());
3169
3170 LLComboBox::showList();
3171 }
3172}
3173
3174//static
3175void LLColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data)
3176{
3177 LLColumnHeader* headerp = (LLColumnHeader*)user_data;
3178 if (!headerp) return;
3179
3180 LLScrollListColumn* column = headerp->mColumn;
3181 if (!column) return;
3182 LLScrollListCtrl *parent = column->mParentCtrl;
3183 if (!parent) return;
3184
3185 if (headerp->getCurrentIndex() == 0)
3186 {
3187 // ascending
3188 parent->sortByColumn(column->mSortingColumn, TRUE);
3189 }
3190 else
3191 {
3192 // descending
3193 parent->sortByColumn(column->mSortingColumn, FALSE);
3194 }
3195
3196 // restore original column header
3197 headerp->setLabel(headerp->mOrigLabel);
3198}
3199
3200LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding)
3201{
3202 // this logic assumes dragging on right
3203 llassert(snap_edge == SNAP_RIGHT);
3204
3205 // use higher snap threshold for column headers
3206 threshold = llmin(threshold, 15);
3207
3208 LLRect snap_rect = getSnapRect();
3209
3210 S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth();
3211
3212 // x coord growing means column growing, so same signs mean we're going in right direction
3213 if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
3214 {
3215 new_edge_val = snap_rect.mRight + snap_delta;
3216 }
3217 else
3218 {
3219 LLScrollListColumn* next_column = mColumn->mParentCtrl->getColumn(mColumn->mIndex + 1);
3220 while (next_column)
3221 {
3222 if (next_column->mHeader)
3223 {
3224 snap_delta = (next_column->mHeader->getSnapRect().mRight - next_column->mMaxContentWidth) - snap_rect.mRight;
3225 if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
3226 {
3227 new_edge_val = snap_rect.mRight + snap_delta;
3228 }
3229 break;
3230 }
3231 next_column = mColumn->mParentCtrl->getColumn(next_column->mIndex + 1);
3232 }
3233 }
3234
3235 return this;
3236}
3237
3238void LLColumnHeader::userSetShape(const LLRect& new_rect)
3239{
3240 S32 new_width = new_rect.getWidth();
3241 S32 delta_width = new_width - (mRect.getWidth() + mColumn->mParentCtrl->getColumnPadding());
3242
3243 if (delta_width != 0)
3244 {
3245 S32 remaining_width = delta_width;
3246 S32 col;
3247 for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++)
3248 {
3249 LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
3250 if (!columnp) break;
3251
3252 if (columnp->mHeader && columnp->mHeader->canResize())
3253 {
3254 // how many pixels in width can this column afford to give up?
3255 S32 resize_buffer_amt = llmax(0, columnp->mWidth - MIN_COLUMN_WIDTH);
3256
3257 // user shrinking column, need to add width to other columns
3258 if (delta_width < 0)
3259 {
3260 if (!columnp->mDynamicWidth && columnp->mWidth > 0)
3261 {
3262 // statically sized column, give all remaining width to this column
3263 columnp->mWidth -= remaining_width;
3264 if (columnp->mRelWidth > 0.f)
3265 {
3266 columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
3267 }
3268 }
3269 break;
3270 }
3271 else
3272 {
3273 // user growing column, need to take width from other columns
3274 remaining_width -= resize_buffer_amt;
3275
3276 if (!columnp->mDynamicWidth && columnp->mWidth > 0)
3277 {
3278 columnp->mWidth -= llmin(columnp->mWidth - MIN_COLUMN_WIDTH, delta_width);
3279 if (columnp->mRelWidth > 0.f)
3280 {
3281 columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
3282 }
3283 }
3284
3285 if (remaining_width <= 0)
3286 {
3287 // width sucked up from neighboring columns, done
3288 break;
3289 }
3290 }
3291 }
3292 }
3293
3294 // clamp resize amount to maximum that can be absorbed by other columns
3295 if (delta_width > 0)
3296 {
3297 delta_width -= llmax(remaining_width, 0);
3298 }
3299
3300 // propagate constrained delta_width to new width for this column
3301 new_width = mRect.getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding();
3302
3303 // use requested width
3304 mColumn->mWidth = new_width;
3305
3306 // update proportional spacing
3307 if (mColumn->mRelWidth > 0.f)
3308 {
3309 mColumn->mRelWidth = (F32)new_width / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
3310 }
3311
3312 // tell scroll list to layout columns again
3313 mColumn->mParentCtrl->updateColumns();
3314 }
3315}
3316
3317void LLColumnHeader::setHasResizableElement(BOOL resizable)
3318{
3319 // for now, dynamically spaced columns can't be resized
3320 if (mColumn->mDynamicWidth) return;
3321
3322 if (resizable != mHasResizableElement)
3323 {
3324 mHasResizableElement = resizable;
3325
3326 S32 num_resizable_columns = 0;
3327 S32 col;
3328 for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
3329 {
3330 LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
3331 if (columnp->mHeader && columnp->mHeader->canResize())
3332 {
3333 num_resizable_columns++;
3334 }
3335 }
3336
3337 S32 num_resizers_enabled = 0;
3338
3339 // now enable/disable resize handles on resizable columns if we have at least two
3340 for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
3341 {
3342 LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
3343 if (!columnp->mHeader) continue;
3344 BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
3345 columnp->mHeader->enableResizeBar(enable);
3346 if (enable)
3347 {
3348 num_resizers_enabled++;
3349 }
3350 }
3351 }
3352}
3353
3354void LLColumnHeader::enableResizeBar(BOOL enable)
3355{
3356 // for now, dynamically spaced columns can't be resized
3357 if (!mColumn->mDynamicWidth)
3358 {
3359 mResizeBar->setEnabled(enable);
3360 }
3361}
3362
3363BOOL LLColumnHeader::canResize()
3364{
3365 return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth);
3366}
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h
index a1c4853..eed07b8 100644
--- a/linden/indra/llui/llscrolllistctrl.h
+++ b/linden/indra/llui/llscrolllistctrl.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -42,9 +43,12 @@
42#include "llviewborder.h" 43#include "llviewborder.h"
43#include "llframetimer.h" 44#include "llframetimer.h"
44#include "llcheckboxctrl.h" 45#include "llcheckboxctrl.h"
46#include "llcombobox.h"
45 47
46class LLScrollbar; 48class LLScrollbar;
47class LLScrollListCtrl; 49class LLScrollListCtrl;
50class LLColumnHeader;
51class LLResizeBar;
48 52
49class LLScrollListCell 53class LLScrollListCell
50{ 54{
@@ -58,11 +62,27 @@ public:
58 virtual const BOOL getVisible() const { return TRUE; } 62 virtual const BOOL getVisible() const { return TRUE; }
59 virtual void setWidth(S32 width) = 0; 63 virtual void setWidth(S32 width) = 0;
60 virtual void highlightText(S32 offset, S32 num_chars) {} 64 virtual void highlightText(S32 offset, S32 num_chars) {}
65 virtual BOOL isText() = 0;
61 66
62 virtual BOOL handleClick() { return FALSE; } 67 virtual BOOL handleClick() { return FALSE; }
63 virtual void setEnabled(BOOL enable) { } 68 virtual void setEnabled(BOOL enable) { }
64}; 69};
65 70
71class LLScrollListSeparator : public LLScrollListCell
72{
73public:
74 LLScrollListSeparator(S32 width);
75 virtual ~LLScrollListSeparator() {};
76 virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible
77 virtual S32 getWidth() const {return mWidth;}
78 virtual S32 getHeight() const { return 5; };
79 virtual void setWidth(S32 width) {mWidth = width; }
80 virtual BOOL isText() { return FALSE; }
81
82protected:
83 S32 mWidth;
84};
85
66class LLScrollListText : public LLScrollListCell 86class LLScrollListText : public LLScrollListCell
67{ 87{
68public: 88public:
@@ -77,6 +97,7 @@ public:
77 virtual const BOOL getVisible() const { return mVisible; } 97 virtual const BOOL getVisible() const { return mVisible; }
78 virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;} 98 virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;}
79 void setText(const LLString& text); 99 void setText(const LLString& text);
100 virtual BOOL isText() { return TRUE; }
80 101
81private: 102private:
82 LLUIString mText; 103 LLUIString mText;
@@ -105,6 +126,7 @@ public:
105 virtual const LLString& getText() const { return mImageUUID; } 126 virtual const LLString& getText() const { return mImageUUID; }
106 virtual const LLString& getTextLower() const { return mImageUUID; } 127 virtual const LLString& getTextLower() const { return mImageUUID; }
107 virtual void setWidth(S32 width) { mWidth = width; } 128 virtual void setWidth(S32 width) { mWidth = width; }
129 virtual BOOL isText() { return FALSE; }
108 130
109private: 131private:
110 LLPointer<LLImageGL> mIcon; 132 LLPointer<LLImageGL> mIcon;
@@ -126,6 +148,7 @@ public:
126 virtual void setEnabled(BOOL enable) { if (mCheckBox) mCheckBox->setEnabled(enable); } 148 virtual void setEnabled(BOOL enable) { if (mCheckBox) mCheckBox->setEnabled(enable); }
127 149
128 LLCheckBoxCtrl* getCheckBox() { return mCheckBox; } 150 LLCheckBoxCtrl* getCheckBox() { return mCheckBox; }
151 virtual BOOL isText() { return FALSE; }
129 152
130private: 153private:
131 LLCheckBoxCtrl* mCheckBox; 154 LLCheckBoxCtrl* mCheckBox;
@@ -136,20 +159,50 @@ class LLScrollListColumn
136{ 159{
137public: 160public:
138 // Default constructor 161 // Default constructor
139 LLScrollListColumn() : mName(""), mSortingColumn(""), mLabel(""), mWidth(-1), mRelWidth(-1.0), mDynamicWidth(FALSE), mIndex(-1), mParentCtrl(NULL), mButton(NULL), mFontAlignment(LLFontGL::LEFT) 162 LLScrollListColumn() :
163 mName(""),
164 mSortingColumn(""),
165 mSortAscending(TRUE),
166 mLabel(""),
167 mWidth(-1),
168 mRelWidth(-1.0),
169 mDynamicWidth(FALSE),
170 mMaxContentWidth(0),
171 mIndex(-1),
172 mParentCtrl(NULL),
173 mHeader(NULL),
174 mFontAlignment(LLFontGL::LEFT)
140 { } 175 { }
141 176
142 LLScrollListColumn(LLString name, LLString label, S32 width, F32 relwidth) 177 LLScrollListColumn(LLString name, LLString label, S32 width, F32 relwidth) :
143 : mName(name), mSortingColumn(name), mLabel(label), mWidth(width), mRelWidth(relwidth), mDynamicWidth(FALSE), mIndex(-1), mParentCtrl(NULL), mButton(NULL) { } 178 mName(name),
179 mSortingColumn(name),
180 mSortAscending(TRUE),
181 mLabel(label),
182 mWidth(width),
183 mRelWidth(relwidth),
184 mDynamicWidth(FALSE),
185 mMaxContentWidth(0),
186 mIndex(-1),
187 mParentCtrl(NULL),
188 mHeader(NULL)
189 { }
144 190
145 LLScrollListColumn(const LLSD &sd) 191 LLScrollListColumn(const LLSD &sd)
146 { 192 {
193 mMaxContentWidth = 0;
194
147 mName = sd.get("name").asString(); 195 mName = sd.get("name").asString();
148 mSortingColumn = mName; 196 mSortingColumn = mName;
149 if (sd.has("sort")) 197 if (sd.has("sort"))
150 { 198 {
151 mSortingColumn = sd.get("sort").asString(); 199 mSortingColumn = sd.get("sort").asString();
152 } 200 }
201 mSortAscending = TRUE;
202 if (sd.has("sort_ascending"))
203 {
204 mSortAscending = sd.get("sort_ascending").asBoolean();
205 }
153 mLabel = sd.get("label").asString(); 206 mLabel = sd.get("label").asString();
154 if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0) 207 if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0)
155 { 208 {
@@ -179,21 +232,57 @@ public:
179 232
180 mIndex = -1; 233 mIndex = -1;
181 mParentCtrl = NULL; 234 mParentCtrl = NULL;
182 mButton = NULL; 235 mHeader = NULL;
183 } 236 }
184 237
185 LLString mName; 238 LLString mName;
186 LLString mSortingColumn; 239 LLString mSortingColumn;
240 BOOL mSortAscending;
187 LLString mLabel; 241 LLString mLabel;
188 S32 mWidth; 242 S32 mWidth;
189 F32 mRelWidth; 243 F32 mRelWidth;
190 BOOL mDynamicWidth; 244 BOOL mDynamicWidth;
245 S32 mMaxContentWidth;
191 S32 mIndex; 246 S32 mIndex;
192 LLScrollListCtrl* mParentCtrl; 247 LLScrollListCtrl* mParentCtrl;
193 LLButton* mButton; 248 LLColumnHeader* mHeader;
194 LLFontGL::HAlign mFontAlignment; 249 LLFontGL::HAlign mFontAlignment;
195}; 250};
196 251
252class LLColumnHeader : public LLComboBox
253{
254public:
255 LLColumnHeader(const LLString& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL *font = NULL);
256 ~LLColumnHeader();
257
258 /*virtual*/ void draw();
259 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
260 /*virtual*/ void showList();
261 /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding);
262 /*virtual*/ void userSetShape(const LLRect& new_rect);
263
264 void setImage(const LLString &image_name);
265 LLScrollListColumn* getColumn() { return mColumn; }
266 void setHasResizableElement(BOOL resizable);
267 BOOL canResize();
268 void enableResizeBar(BOOL enable);
269 LLString getLabel() { return mOrigLabel; }
270
271 static void onSelectSort(LLUICtrl* ctrl, void* user_data);
272 static void onClick(void* user_data);
273 static void onMouseDown(void* user_data);
274 static void onHeldDown(void* user_data);
275
276protected:
277 LLScrollListColumn* mColumn;
278 LLResizeBar* mResizeBar;
279 LLString mOrigLabel;
280 LLUIString mAscendingText;
281 LLUIString mDescendingText;
282 BOOL mShowSortOptions;
283 BOOL mHasResizableElement;
284};
285
197class LLScrollListItem 286class LLScrollListItem
198{ 287{
199public: 288public:
@@ -235,7 +324,7 @@ public:
235 324
236 LLScrollListCell *getColumn(const S32 i) const { if (i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; } 325 LLScrollListCell *getColumn(const S32 i) const { if (i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; }
237 326
238 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); 327 virtual BOOL handleClick(S32 x, S32 y, MASK mask);
239 328
240 LLString getContentsCSV(); 329 LLString getContentsCSV();
241 330
@@ -282,6 +371,10 @@ public:
282 virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM); 371 virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM);
283 virtual void clearColumns(); 372 virtual void clearColumns();
284 virtual void setColumnLabel(const LLString& column, const LLString& label); 373 virtual void setColumnLabel(const LLString& column, const LLString& label);
374
375 virtual LLScrollListColumn* getColumn(S32 index);
376 virtual S32 getNumColumns() const { return mColumnsIndexed.size(); }
377
285 // Adds a single element, from an array of: 378 // Adds a single element, from an array of:
286 // "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid 379 // "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid
287 // Creates missing columns automatically. 380 // Creates missing columns automatically.
@@ -316,11 +409,14 @@ public:
316 // Returns FALSE if not found. 409 // Returns FALSE if not found.
317 BOOL setSelectedByValue(LLSD value, BOOL selected); 410 BOOL setSelectedByValue(LLSD value, BOOL selected);
318 411
319 virtual BOOL isSelected(LLSD value); 412 BOOL isSorted();
320 413
414 virtual BOOL isSelected(LLSD value);
415
321 BOOL selectFirstItem(); 416 BOOL selectFirstItem();
322 BOOL selectNthItem( S32 index ); 417 BOOL selectNthItem( S32 index );
323 418 BOOL selectItemAt(S32 x, S32 y, MASK mask);
419
324 void deleteSingleItem( S32 index ) ; 420 void deleteSingleItem( S32 index ) ;
325 void deleteSelectedItems(); 421 void deleteSelectedItems();
326 void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change 422 void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change
@@ -357,23 +453,6 @@ public:
357 LLScrollListItem* addStringUUIDItem(const LLString& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0); 453 LLScrollListItem* addStringUUIDItem(const LLString& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0);
358 LLUUID getStringUUIDSelectedItem(); 454 LLUUID getStringUUIDSelectedItem();
359 455
360 // "Full" interface: use this when you're creating a list that has one or more of the following:
361 // * contains icons
362 // * contains multiple columns
363 // * allows multiple selection
364 // * has items that are not guarenteed to have unique names
365 // * has additional per-item data (e.g. a UUID or void* userdata)
366 //
367 // To add items using this approach, create new LLScrollListItems and LLScrollListCells. Add the
368 // cells (column entries) to each item, and add the item to the LLScrollListCtrl.
369 //
370 // The LLScrollListCtrl owns its items and is responsible for deleting them
371 // (except in the case that the addItem() call fails, in which case it is up
372 // to the caller to delete the item)
373
374 // returns FALSE if item faile to be added to list, does NOT delete 'item'
375 // TomY TODO - Deprecate this API and remove it
376 BOOL addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM );
377 LLScrollListItem* getFirstSelected() const; 456 LLScrollListItem* getFirstSelected() const;
378 virtual S32 getFirstSelectedIndex(); 457 virtual S32 getFirstSelectedIndex();
379 std::vector<LLScrollListItem*> getAllSelected() const; 458 std::vector<LLScrollListItem*> getAllSelected() const;
@@ -382,6 +461,7 @@ public:
382 461
383 // iterate over all items 462 // iterate over all items
384 LLScrollListItem* getFirstData() const; 463 LLScrollListItem* getFirstData() const;
464 LLScrollListItem* getLastData() const;
385 std::vector<LLScrollListItem*> getAllData() const; 465 std::vector<LLScrollListItem*> getAllData() const;
386 466
387 void setAllowMultipleSelection(BOOL mult ) { mAllowMultipleSelection = mult; } 467 void setAllowMultipleSelection(BOOL mult ) { mAllowMultipleSelection = mult; }
@@ -398,6 +478,7 @@ public:
398 void setBackgroundVisible(BOOL b) { mBackgroundVisible = b; } 478 void setBackgroundVisible(BOOL b) { mBackgroundVisible = b; }
399 void setDrawStripes(BOOL b) { mDrawStripes = b; } 479 void setDrawStripes(BOOL b) { mDrawStripes = b; }
400 void setColumnPadding(const S32 c) { mColumnPadding = c; } 480 void setColumnPadding(const S32 c) { mColumnPadding = c; }
481 S32 getColumnPadding() { return mColumnPadding; }
401 void setCommitOnKeyboardMovement(BOOL b) { mCommitOnKeyboardMovement = b; } 482 void setCommitOnKeyboardMovement(BOOL b) { mCommitOnKeyboardMovement = b; }
402 void setCommitOnSelectionChange(BOOL b) { mCommitOnSelectionChange = b; } 483 void setCommitOnSelectionChange(BOOL b) { mCommitOnSelectionChange = b; }
403 void setAllowKeyboardMovement(BOOL b) { mAllowKeyboardMovement = b; } 484 void setAllowKeyboardMovement(BOOL b) { mAllowKeyboardMovement = b; }
@@ -417,6 +498,7 @@ public:
417 // Overridden from LLView 498 // Overridden from LLView
418 virtual void draw(); 499 virtual void draw();
419 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); 500 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
501 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
420 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); 502 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
421 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 503 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
422 virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); 504 virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
@@ -424,6 +506,7 @@ public:
424 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 506 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
425 virtual void setEnabled(BOOL enabled); 507 virtual void setEnabled(BOOL enabled);
426 virtual void setFocus( BOOL b ); 508 virtual void setFocus( BOOL b );
509 virtual void onFocusReceived();
427 virtual void onFocusLost(); 510 virtual void onFocusLost();
428 511
429 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); 512 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -431,17 +514,18 @@ public:
431 virtual LLRect getRequiredRect(); 514 virtual LLRect getRequiredRect();
432 static BOOL rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row); 515 static BOOL rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row);
433 516
517 LLRect getItemListRect() { return mItemListRect; }
518
434 // Used "internally" by the scroll bar. 519 // Used "internally" by the scroll bar.
435 static void onScrollChange( S32 new_pos, LLScrollbar* src, void* userdata ); 520 static void onScrollChange( S32 new_pos, LLScrollbar* src, void* userdata );
436 521
437 static void onClickColumn(void *userdata); 522 static void onClickColumn(void *userdata);
438 523
439 void updateColumns(); 524 void updateColumns();
440 void updateColumnButtons(); 525 void updateMaxContentWidth(LLScrollListItem* changed_item);
441 526
442 void setDisplayHeading(BOOL display); 527 void setDisplayHeading(BOOL display);
443 void setHeadingHeight(S32 heading_height); 528 void setHeadingHeight(S32 heading_height);
444 void setHeadingFont(const LLFontGL* heading_font);
445 void setCollapseEmptyColumns(BOOL collapse); 529 void setCollapseEmptyColumns(BOOL collapse);
446 void setIsPopup(BOOL is_popup) { mIsPopup = is_popup; } 530 void setIsPopup(BOOL is_popup) { mIsPopup = is_popup; }
447 531
@@ -473,6 +557,22 @@ public:
473 S32 selectMultiple( LLDynamicArray<LLUUID> ids ); 557 S32 selectMultiple( LLDynamicArray<LLUUID> ids );
474 558
475protected: 559protected:
560 // "Full" interface: use this when you're creating a list that has one or more of the following:
561 // * contains icons
562 // * contains multiple columns
563 // * allows multiple selection
564 // * has items that are not guarenteed to have unique names
565 // * has additional per-item data (e.g. a UUID or void* userdata)
566 //
567 // To add items using this approach, create new LLScrollListItems and LLScrollListCells. Add the
568 // cells (column entries) to each item, and add the item to the LLScrollListCtrl.
569 //
570 // The LLScrollListCtrl owns its items and is responsible for deleting them
571 // (except in the case that the addItem() call fails, in which case it is up
572 // to the caller to delete the item)
573
574 // returns FALSE if item faile to be added to list, does NOT delete 'item'
575 BOOL addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM );
476 void selectPrevItem(BOOL extend_selection); 576 void selectPrevItem(BOOL extend_selection);
477 void selectNextItem(BOOL extend_selection); 577 void selectNextItem(BOOL extend_selection);
478 void drawItems(); 578 void drawItems();
@@ -482,6 +582,7 @@ protected:
482 void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE); 582 void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
483 void deselectItem(LLScrollListItem* itemp); 583 void deselectItem(LLScrollListItem* itemp);
484 void commitIfChanged(); 584 void commitIfChanged();
585 void setSorted(BOOL sorted);
485 586
486protected: 587protected:
487 S32 mCurIndex; // For get[First/Next]Data 588 S32 mCurIndex; // For get[First/Next]Data
@@ -492,7 +593,6 @@ protected:
492 S32 mPageLines; // max number of lines is it possible to see on the screen given mRect and mLineHeight 593 S32 mPageLines; // max number of lines is it possible to see on the screen given mRect and mLineHeight
493 S32 mHeadingHeight; // the height of the column header buttons, if visible 594 S32 mHeadingHeight; // the height of the column header buttons, if visible
494 U32 mMaxSelectable; 595 U32 mMaxSelectable;
495 const LLFontGL* mHeadingFont; // the font to use for column head buttons, if visible
496 LLScrollbar* mScrollbar; 596 LLScrollbar* mScrollbar;
497 BOOL mAllowMultipleSelection; 597 BOOL mAllowMultipleSelection;
498 BOOL mAllowKeyboardMovement; 598 BOOL mAllowKeyboardMovement;
@@ -500,7 +600,7 @@ protected:
500 BOOL mCommitOnSelectionChange; 600 BOOL mCommitOnSelectionChange;
501 BOOL mSelectionChanged; 601 BOOL mSelectionChanged;
502 BOOL mCanSelect; 602 BOOL mCanSelect;
503 BOOL mDisplayColumnButtons; 603 BOOL mDisplayColumnHeaders;
504 BOOL mCollapseEmptyColumns; 604 BOOL mCollapseEmptyColumns;
505 BOOL mIsPopup; 605 BOOL mIsPopup;
506 606
@@ -544,8 +644,9 @@ protected:
544 S32 mNumDynamicWidthColumns; 644 S32 mNumDynamicWidthColumns;
545 S32 mTotalStaticColumnWidth; 645 S32 mTotalStaticColumnWidth;
546 646
547 U32 mSortColumn; 647 S32 mSortColumn;
548 BOOL mSortAscending; 648 BOOL mSortAscending;
649 BOOL mSorted;
549 650
550 std::map<LLString, LLScrollListColumn> mColumns; 651 std::map<LLString, LLScrollListColumn> mColumns;
551 std::vector<LLScrollListColumn*> mColumnsIndexed; 652 std::vector<LLScrollListColumn*> mColumnsIndexed;
diff --git a/linden/indra/llui/llslider.cpp b/linden/indra/llui/llslider.cpp
index 20d77bf..8c0d2a1 100644
--- a/linden/indra/llui/llslider.cpp
+++ b/linden/indra/llui/llslider.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -117,7 +118,7 @@ F32 LLSlider::getValueF32() const
117 118
118BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask) 119BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
119{ 120{
120 if( gFocusMgr.getMouseCapture() == this ) 121 if( hasMouseCapture() )
121 { 122 {
122 S32 left_edge = THUMB_WIDTH/2; 123 S32 left_edge = THUMB_WIDTH/2;
123 S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2); 124 S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2);
@@ -144,9 +145,9 @@ BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask)
144{ 145{
145 BOOL handled = FALSE; 146 BOOL handled = FALSE;
146 147
147 if( gFocusMgr.getMouseCapture() == this ) 148 if( hasMouseCapture() )
148 { 149 {
149 gFocusMgr.setMouseCapture( NULL, NULL ); 150 gFocusMgr.setMouseCapture( NULL );
150 151
151 if( mMouseUpCallback ) 152 if( mMouseUpCallback )
152 { 153 {
@@ -194,7 +195,7 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
194 195
195 // Start dragging the thumb 196 // Start dragging the thumb
196 // No handler needed for focus lost since this class has no state that depends on it. 197 // No handler needed for focus lost since this class has no state that depends on it.
197 gFocusMgr.setMouseCapture( this, NULL ); 198 gFocusMgr.setMouseCapture( this );
198 mDragStartThumbRect = mThumbRect; 199 mDragStartThumbRect = mThumbRect;
199 } 200 }
200 make_ui_sound("UISndClick"); 201 make_ui_sound("UISndClick");
@@ -261,12 +262,12 @@ void LLSlider::draw()
261 if (!thumb_imagep) 262 if (!thumb_imagep)
262 { 263 {
263 gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE); 264 gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
264 if (gFocusMgr.getMouseCapture() == this) 265 if (hasMouseCapture())
265 { 266 {
266 gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE); 267 gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE);
267 } 268 }
268 } 269 }
269 else if( gFocusMgr.getMouseCapture() == this ) 270 else if( hasMouseCapture() )
270 { 271 {
271 gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(), 272 gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(),
272 thumb_imagep, mThumbCenterColor % 0.3f, TRUE); 273 thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
diff --git a/linden/indra/llui/llslider.h b/linden/indra/llui/llslider.h
index 1cf1a90..4f42a56 100644
--- a/linden/indra/llui/llslider.h
+++ b/linden/indra/llui/llslider.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp
index c62ec9a..9a67bca 100644
--- a/linden/indra/llui/llsliderctrl.cpp
+++ b/linden/indra/llui/llsliderctrl.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -205,7 +206,7 @@ void LLSliderCtrl::clear()
205 206
206BOOL LLSliderCtrl::isMouseHeldDown() 207BOOL LLSliderCtrl::isMouseHeldDown()
207{ 208{
208 return gFocusMgr.getMouseCapture() == mSlider; 209 return mSlider->hasMouseCapture();
209} 210}
210 211
211void LLSliderCtrl::updateText() 212void LLSliderCtrl::updateText()
@@ -319,7 +320,7 @@ void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
319 320
320void LLSliderCtrl::setEnabled(BOOL b) 321void LLSliderCtrl::setEnabled(BOOL b)
321{ 322{
322 LLUICtrl::setEnabled( b ); 323 LLView::setEnabled( b );
323 324
324 if( mLabelBox ) 325 if( mLabelBox )
325 { 326 {
diff --git a/linden/indra/llui/llsliderctrl.h b/linden/indra/llui/llsliderctrl.h
index baa0c42..26c9dee 100644
--- a/linden/indra/llui/llsliderctrl.h
+++ b/linden/indra/llui/llsliderctrl.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llspinctrl.cpp b/linden/indra/llui/llspinctrl.cpp
index 1f33279..668ddfa 100644
--- a/linden/indra/llui/llspinctrl.cpp
+++ b/linden/indra/llui/llspinctrl.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -142,6 +143,23 @@ LLSpinCtrl::~LLSpinCtrl()
142} 143}
143 144
144 145
146F32 clamp_precision(F32 value, S32 decimal_precision)
147{
148 // pow() isn't perfect
149
150 F64 clamped_value = value;
151 for (S32 i = 0; i < decimal_precision; i++)
152 clamped_value *= 10.0;
153
154 clamped_value = llround((F32)clamped_value);
155
156 for (S32 i = 0; i < decimal_precision; i++)
157 clamped_value /= 10.0;
158
159 return (F32)clamped_value;
160}
161
162
145// static 163// static
146void LLSpinCtrl::onUpBtn( void *userdata ) 164void LLSpinCtrl::onUpBtn( void *userdata )
147{ 165{
@@ -150,6 +168,7 @@ void LLSpinCtrl::onUpBtn( void *userdata )
150 { 168 {
151 // use getValue()/setValue() to force reload from/to control 169 // use getValue()/setValue() to force reload from/to control
152 F32 val = (F32)self->getValue().asReal() + self->mIncrement; 170 F32 val = (F32)self->getValue().asReal() + self->mIncrement;
171 val = clamp_precision(val, self->mPrecision);
153 val = llmin( val, self->mMaxValue ); 172 val = llmin( val, self->mMaxValue );
154 173
155 if( self->mValidateCallback ) 174 if( self->mValidateCallback )
@@ -182,6 +201,7 @@ void LLSpinCtrl::onDownBtn( void *userdata )
182 if( self->getEnabled() ) 201 if( self->getEnabled() )
183 { 202 {
184 F32 val = (F32)self->getValue().asReal() - self->mIncrement; 203 F32 val = (F32)self->getValue().asReal() - self->mIncrement;
204 val = clamp_precision(val, self->mPrecision);
185 val = llmax( val, self->mMinValue ); 205 val = llmax( val, self->mMinValue );
186 206
187 if( self->mValidateCallback ) 207 if( self->mValidateCallback )
@@ -243,12 +263,13 @@ void LLSpinCtrl::clear()
243} 263}
244 264
245 265
266
246void LLSpinCtrl::updateEditor() 267void LLSpinCtrl::updateEditor()
247{ 268{
248 LLLocale locale(LLLocale::USER_LOCALE); 269 LLLocale locale(LLLocale::USER_LOCALE);
249 270
250 // Don't display very small negative values as -0.000 271 // Don't display very small negative values as -0.000
251 F32 displayed_value = (F32)floor(getValue().asReal() * pow(10.0, (F64)mPrecision) + 0.5) / (F32)pow(10.0, (F64)mPrecision); 272 F32 displayed_value = clamp_precision((F32)getValue().asReal(), mPrecision);
252 273
253// if( S32( displayed_value * pow( 10, mPrecision ) ) == 0 ) 274// if( S32( displayed_value * pow( 10, mPrecision ) ) == 0 )
254// { 275// {
@@ -320,7 +341,7 @@ void LLSpinCtrl::setFocus(BOOL b)
320 341
321void LLSpinCtrl::setEnabled(BOOL b) 342void LLSpinCtrl::setEnabled(BOOL b)
322{ 343{
323 LLUICtrl::setEnabled( b ); 344 LLView::setEnabled( b );
324 mEditor->setEnabled( b ); 345 mEditor->setEnabled( b );
325} 346}
326 347
@@ -335,8 +356,8 @@ void LLSpinCtrl::setTentative(BOOL b)
335BOOL LLSpinCtrl::isMouseHeldDown() 356BOOL LLSpinCtrl::isMouseHeldDown()
336{ 357{
337 return 358 return
338 gFocusMgr.getMouseCapture() == mDownBtn || 359 mDownBtn->hasMouseCapture()
339 gFocusMgr.getMouseCapture() == mUpBtn; 360 || mUpBtn->hasMouseCapture();
340} 361}
341 362
342void LLSpinCtrl::onCommit() 363void LLSpinCtrl::onCommit()
diff --git a/linden/indra/llui/llspinctrl.h b/linden/indra/llui/llspinctrl.h
index 46776ed..dcc305e 100644
--- a/linden/indra/llui/llspinctrl.h
+++ b/linden/indra/llui/llspinctrl.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc. 5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llstyle.cpp b/linden/indra/llui/llstyle.cpp
index aaacb46..1efb4cc 100644
--- a/linden/indra/llui/llstyle.cpp
+++ b/linden/indra/llui/llstyle.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llstyle.h b/linden/indra/llui/llstyle.h
index 424db40..e6e88e7 100644
--- a/linden/indra/llui/llstyle.h
+++ b/linden/indra/llui/llstyle.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lltabcontainer.cpp b/linden/indra/llui/lltabcontainer.cpp
index 4687414..db09717 100644
--- a/linden/indra/llui/lltabcontainer.cpp
+++ b/linden/indra/llui/lltabcontainer.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -476,6 +477,24 @@ void LLTabContainerCommon::onPrevBtn( void* userdata )
476 self->mScrolled = FALSE; 477 self->mScrolled = FALSE;
477} 478}
478 479
480
481void LLTabContainerCommon::onJumpFirstBtn( void* userdata )
482{
483 LLTabContainer* self = (LLTabContainer*) userdata;
484
485 self->mScrollPos = 0;
486
487}
488
489
490void LLTabContainerCommon::onJumpLastBtn( void* userdata )
491{
492 LLTabContainer* self = (LLTabContainer*) userdata;
493
494 self->mScrollPos = self->mMaxScrollPos;
495}
496
497
479// static 498// static
480void LLTabContainerCommon::onPrevBtnHeld( void* userdata ) 499void LLTabContainerCommon::onPrevBtnHeld( void* userdata )
481{ 500{
@@ -692,6 +711,8 @@ LLTabContainer::LLTabContainer(
692 LLTabContainerCommon(name, rect, pos, close_callback, callback_userdata, bordered), 711 LLTabContainerCommon(name, rect, pos, close_callback, callback_userdata, bordered),
693 mLeftArrowBtn(NULL), 712 mLeftArrowBtn(NULL),
694 mRightArrowBtn(NULL), 713 mRightArrowBtn(NULL),
714 mJumpLeftArrowBtn(NULL),
715 mJumpRightArrowBtn(NULL),
695 mRightTabBtnOffset(0), 716 mRightTabBtnOffset(0),
696 mMinTabWidth(TABCNTR_TAB_MIN_WIDTH), 717 mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
697 mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH), 718 mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
@@ -708,6 +729,8 @@ LLTabContainer::LLTabContainer(
708 LLTabContainerCommon(name, rect_control, pos, close_callback, callback_userdata, bordered), 729 LLTabContainerCommon(name, rect_control, pos, close_callback, callback_userdata, bordered),
709 mLeftArrowBtn(NULL), 730 mLeftArrowBtn(NULL),
710 mRightArrowBtn(NULL), 731 mRightArrowBtn(NULL),
732 mJumpLeftArrowBtn(NULL),
733 mJumpRightArrowBtn(NULL),
711 mRightTabBtnOffset(0), 734 mRightTabBtnOffset(0),
712 mMinTabWidth(TABCNTR_TAB_MIN_WIDTH), 735 mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
713 mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH), 736 mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
@@ -739,14 +762,35 @@ void LLTabContainer::initButtons()
739 S32 btn_top = (mTabPosition == TOP ) ? mRect.getHeight() - mTopBorderHeight : TABCNTR_ARROW_BTN_SIZE + 1; 762 S32 btn_top = (mTabPosition == TOP ) ? mRect.getHeight() - mTopBorderHeight : TABCNTR_ARROW_BTN_SIZE + 1;
740 763
741 LLRect left_arrow_btn_rect; 764 LLRect left_arrow_btn_rect;
742 left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); 765 left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+TABCNTR_ARROW_BTN_SIZE, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
766
767 LLRect jump_left_arrow_btn_rect;
768 jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
743 769
744 S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1; 770 S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1;
771
745 LLRect right_arrow_btn_rect; 772 LLRect right_arrow_btn_rect;
746 right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad, 773 right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad - TABCNTR_ARROW_BTN_SIZE,
747 btn_top + arrow_fudge, 774 btn_top + arrow_fudge,
748 TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE ); 775 TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
749 776
777
778 LLRect jump_right_arrow_btn_rect;
779 jump_right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad,
780 btn_top + arrow_fudge,
781 TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
782
783 out_id = "UIImgBtnJumpLeftOutUUID";
784 in_id = "UIImgBtnJumpLeftInUUID";
785 mJumpLeftArrowBtn = new LLButton(
786 "Jump Left Arrow", jump_left_arrow_btn_rect,
787 out_id, in_id, "",
788 &LLTabContainer::onJumpFirstBtn, this, LLFontGL::sSansSerif );
789 mJumpLeftArrowBtn->setFollowsLeft();
790 mJumpLeftArrowBtn->setSaveToXML(false);
791 mJumpLeftArrowBtn->setTabStop(FALSE);
792 addChild(mJumpLeftArrowBtn);
793
750 out_id = "UIImgBtnScrollLeftOutUUID"; 794 out_id = "UIImgBtnScrollLeftOutUUID";
751 in_id = "UIImgBtnScrollLeftInUUID"; 795 in_id = "UIImgBtnScrollLeftInUUID";
752 mLeftArrowBtn = new LLButton( 796 mLeftArrowBtn = new LLButton(
@@ -758,6 +802,18 @@ void LLTabContainer::initButtons()
758 mLeftArrowBtn->setSaveToXML(false); 802 mLeftArrowBtn->setSaveToXML(false);
759 mLeftArrowBtn->setTabStop(FALSE); 803 mLeftArrowBtn->setTabStop(FALSE);
760 addChild(mLeftArrowBtn); 804 addChild(mLeftArrowBtn);
805
806 out_id = "UIImgBtnJumpRightOutUUID";
807 in_id = "UIImgBtnJumpRightInUUID";
808 mJumpRightArrowBtn = new LLButton(
809 "Jump Right Arrow", jump_right_arrow_btn_rect,
810 out_id, in_id, "",
811 &LLTabContainer::onJumpLastBtn, this,
812 LLFontGL::sSansSerif);
813 mJumpRightArrowBtn->setFollowsRight();
814 mJumpRightArrowBtn->setSaveToXML(false);
815 mJumpRightArrowBtn->setTabStop(FALSE);
816 addChild(mJumpRightArrowBtn);
761 817
762 out_id = "UIImgBtnScrollRightOutUUID"; 818 out_id = "UIImgBtnScrollRightOutUUID";
763 in_id = "UIImgBtnScrollRightInUUID"; 819 in_id = "UIImgBtnScrollRightInUUID";
@@ -772,15 +828,20 @@ void LLTabContainer::initButtons()
772 mRightArrowBtn->setTabStop(FALSE); 828 mRightArrowBtn->setTabStop(FALSE);
773 addChild(mRightArrowBtn); 829 addChild(mRightArrowBtn);
774 830
831
775 if( mTabPosition == TOP ) 832 if( mTabPosition == TOP )
776 { 833 {
777 mRightArrowBtn->setFollowsTop(); 834 mRightArrowBtn->setFollowsTop();
778 mLeftArrowBtn->setFollowsTop(); 835 mLeftArrowBtn->setFollowsTop();
836 mJumpLeftArrowBtn->setFollowsTop();
837 mJumpRightArrowBtn->setFollowsTop();
779 } 838 }
780 else 839 else
781 { 840 {
782 mRightArrowBtn->setFollowsBottom(); 841 mRightArrowBtn->setFollowsBottom();
783 mLeftArrowBtn->setFollowsBottom(); 842 mLeftArrowBtn->setFollowsBottom();
843 mJumpLeftArrowBtn->setFollowsBottom();
844 mJumpRightArrowBtn->setFollowsBottom();
784 } 845 }
785 846
786 // set default tab group to be panel contents 847 // set default tab group to be panel contents
@@ -971,7 +1032,7 @@ void LLTabContainer::updateMaxScrollPos()
971 1032
972 if( tab_space > available_space ) 1033 if( tab_space > available_space )
973 { 1034 {
974 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + 1); 1035 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
975 // subtract off reserved portion on left 1036 // subtract off reserved portion on left
976 available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH; 1037 available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH;
977 1038
@@ -1002,7 +1063,7 @@ void LLTabContainer::updateMaxScrollPos()
1002 1063
1003void LLTabContainer::commitHoveredButton(S32 x, S32 y) 1064void LLTabContainer::commitHoveredButton(S32 x, S32 y)
1004{ 1065{
1005 if (gFocusMgr.getMouseCapture() == this) 1066 if (hasMouseCapture())
1006 { 1067 {
1007 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) 1068 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
1008 { 1069 {
@@ -1078,7 +1139,7 @@ BOOL LLTabContainer::selectTab(S32 which)
1078 } 1139 }
1079 else 1140 else
1080 { 1141 {
1081 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + 1); 1142 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
1082 S32 running_tab_width = tuple->mButton->getRect().getWidth(); 1143 S32 running_tab_width = tuple->mButton->getRect().getWidth();
1083 S32 j = i - 1; 1144 S32 j = i - 1;
1084 S32 min_scroll_pos = i; 1145 S32 min_scroll_pos = i;
@@ -1120,7 +1181,7 @@ void LLTabContainer::draw()
1120 S32 cur_scroll_pos = mScrollPos; 1181 S32 cur_scroll_pos = mScrollPos;
1121 if (cur_scroll_pos > 0) 1182 if (cur_scroll_pos > 0)
1122 { 1183 {
1123 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + 1); 1184 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
1124 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) 1185 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
1125 { 1186 {
1126 if (cur_scroll_pos == 0) 1187 if (cur_scroll_pos == 0)
@@ -1141,11 +1202,13 @@ void LLTabContainer::draw()
1141 if( getVisible() ) 1202 if( getVisible() )
1142 { 1203 {
1143 BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0); 1204 BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
1205 mJumpLeftArrowBtn->setVisible( has_scroll_arrows );
1206 mJumpRightArrowBtn->setVisible( has_scroll_arrows );
1144 mLeftArrowBtn->setVisible( has_scroll_arrows ); 1207 mLeftArrowBtn->setVisible( has_scroll_arrows );
1145 mRightArrowBtn->setVisible( has_scroll_arrows ); 1208 mRightArrowBtn->setVisible( has_scroll_arrows );
1146 1209
1147 // Set the leftmost position of the tab buttons. 1210 // Set the leftmost position of the tab buttons.
1148 S32 left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? TABCNTR_ARROW_BTN_SIZE : TABCNTR_TAB_H_PAD); 1211 S32 left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD);
1149 left -= mScrollPosPixels; 1212 left -= mScrollPosPixels;
1150 1213
1151 // Hide all the buttons 1214 // Hide all the buttons
@@ -1234,7 +1297,19 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
1234 BOOL has_scroll_arrows = (mMaxScrollPos > 0); 1297 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
1235 1298
1236 if (has_scroll_arrows) 1299 if (has_scroll_arrows)
1237 { 1300 {
1301 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
1302 {
1303 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
1304 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
1305 handled = mJumpLeftArrowBtn->handleMouseDown(local_x, local_y, mask);
1306 }
1307 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
1308 {
1309 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
1310 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
1311 handled = mJumpRightArrowBtn->handleMouseDown(local_x, local_y, mask);
1312 }
1238 if (mLeftArrowBtn->getRect().pointInRect(x, y)) 1313 if (mLeftArrowBtn->getRect().pointInRect(x, y))
1239 { 1314 {
1240 S32 local_x = x - mLeftArrowBtn->getRect().mLeft; 1315 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
@@ -1256,14 +1331,14 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
1256 if (mTabList.size() > 0) 1331 if (mTabList.size() > 0)
1257 { 1332 {
1258 LLTabTuple* firsttuple = mTabList[0]; 1333 LLTabTuple* firsttuple = mTabList[0];
1259 LLRect tab_rect(has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mLeftArrowBtn->getRect().mLeft, 1334 LLRect tab_rect(has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft,
1260 firsttuple->mButton->getRect().mTop, 1335 firsttuple->mButton->getRect().mTop,
1261 has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight, 1336 has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mJumpRightArrowBtn->getRect().mRight,
1262 firsttuple->mButton->getRect().mBottom ); 1337 firsttuple->mButton->getRect().mBottom );
1263 if( tab_rect.pointInRect( x, y ) ) 1338 if( tab_rect.pointInRect( x, y ) )
1264 { 1339 {
1265 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; 1340 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
1266 gFocusMgr.setMouseCapture(this, NULL); 1341 gFocusMgr.setMouseCapture(this);
1267 gFocusMgr.setKeyboardFocus(tab_button, NULL); 1342 gFocusMgr.setKeyboardFocus(tab_button, NULL);
1268 } 1343 }
1269 } 1344 }
@@ -1276,7 +1351,19 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
1276 BOOL has_scroll_arrows = (mMaxScrollPos > 0); 1351 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
1277 1352
1278 if (has_scroll_arrows) 1353 if (has_scroll_arrows)
1279 { 1354 {
1355 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
1356 {
1357 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
1358 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
1359 handled = mJumpLeftArrowBtn->handleHover(local_x, local_y, mask);
1360 }
1361 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
1362 {
1363 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
1364 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
1365 handled = mJumpRightArrowBtn->handleHover(local_x, local_y, mask);
1366 }
1280 if (mLeftArrowBtn->getRect().pointInRect(x, y)) 1367 if (mLeftArrowBtn->getRect().pointInRect(x, y))
1281 { 1368 {
1282 S32 local_x = x - mLeftArrowBtn->getRect().mLeft; 1369 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
@@ -1306,6 +1393,18 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
1306 1393
1307 if (has_scroll_arrows) 1394 if (has_scroll_arrows)
1308 { 1395 {
1396 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
1397 {
1398 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
1399 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
1400 handled = mJumpLeftArrowBtn->handleMouseUp(local_x, local_y, mask);
1401 }
1402 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
1403 {
1404 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
1405 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
1406 handled = mJumpRightArrowBtn->handleMouseUp(local_x, local_y, mask);
1407 }
1309 if (mLeftArrowBtn->getRect().pointInRect(x, y)) 1408 if (mLeftArrowBtn->getRect().pointInRect(x, y))
1310 { 1409 {
1311 S32 local_x = x - mLeftArrowBtn->getRect().mLeft; 1410 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
@@ -1326,7 +1425,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
1326 1425
1327 commitHoveredButton(x, y); 1426 commitHoveredButton(x, y);
1328 LLPanel* cur_panel = getCurrentPanel(); 1427 LLPanel* cur_panel = getCurrentPanel();
1329 if (gFocusMgr.getMouseCapture() == this) 1428 if (hasMouseCapture())
1330 { 1429 {
1331 if (cur_panel) 1430 if (cur_panel)
1332 { 1431 {
@@ -1337,7 +1436,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
1337 mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE); 1436 mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE);
1338 } 1437 }
1339 } 1438 }
1340 gFocusMgr.setMouseCapture(NULL, NULL); 1439 gFocusMgr.setMouseCapture(NULL);
1341 } 1440 }
1342 return handled; 1441 return handled;
1343} 1442}
@@ -1351,7 +1450,7 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_
1351 1450
1352 BOOL has_scroll_arrows = (mMaxScrollPos > 0); 1451 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
1353 LLRect clip( 1452 LLRect clip(
1354 has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mLeftArrowBtn->getRect().mLeft, 1453 has_scroll_arrows ? mJumpLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft,
1355 firsttuple->mButton->getRect().mTop, 1454 firsttuple->mButton->getRect().mTop,
1356 has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight, 1455 has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight,
1357 0 ); 1456 0 );
@@ -1457,6 +1556,18 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
1457 1556
1458 if (has_scroll_arrows) 1557 if (has_scroll_arrows)
1459 { 1558 {
1559 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
1560 {
1561 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
1562 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
1563 mJumpLeftArrowBtn->handleHover(local_x, local_y, mask);
1564 }
1565 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
1566 {
1567 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
1568 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
1569 mJumpRightArrowBtn->handleHover(local_x, local_y, mask);
1570 }
1460 if (mLeftArrowBtn->getRect().pointInRect(x, y)) 1571 if (mLeftArrowBtn->getRect().pointInRect(x, y))
1461 { 1572 {
1462 S32 local_x = x - mLeftArrowBtn->getRect().mLeft; 1573 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
diff --git a/linden/indra/llui/lltabcontainer.h b/linden/indra/llui/lltabcontainer.h
index c3146a1..5fe6bc5 100644
--- a/linden/indra/llui/lltabcontainer.h
+++ b/linden/indra/llui/lltabcontainer.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -128,6 +129,8 @@ public:
128 static void onNextBtnHeld(void* userdata); 129 static void onNextBtnHeld(void* userdata);
129 static void onPrevBtn(void* userdata); 130 static void onPrevBtn(void* userdata);
130 static void onPrevBtnHeld(void* userdata); 131 static void onPrevBtnHeld(void* userdata);
132 static void onJumpFirstBtn( void* userdata );
133 static void onJumpLastBtn( void* userdata );
131 134
132 virtual void setRightTabBtnOffset( S32 offset ) { } 135 virtual void setRightTabBtnOffset( S32 offset ) { }
133 virtual void setPanelTitle(S32 index, const LLString& title) { } 136 virtual void setPanelTitle(S32 index, const LLString& title) { }
@@ -242,7 +245,9 @@ public:
242protected: 245protected:
243 246
244 LLButton* mLeftArrowBtn; 247 LLButton* mLeftArrowBtn;
248 LLButton* mJumpLeftArrowBtn;
245 LLButton* mRightArrowBtn; 249 LLButton* mRightArrowBtn;
250 LLButton* mJumpRightArrowBtn;
246 251
247 S32 mRightTabBtnOffset; // Extra room to the right of the tab buttons. 252 S32 mRightTabBtnOffset; // Extra room to the right of the tab buttons.
248 253
diff --git a/linden/indra/llui/lltabcontainervertical.cpp b/linden/indra/llui/lltabcontainervertical.cpp
index 121adf1..a921b4b 100644
--- a/linden/indra/llui/lltabcontainervertical.cpp
+++ b/linden/indra/llui/lltabcontainervertical.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -279,7 +280,7 @@ void LLTabContainerVertical::updateMaxScrollPos()
279 280
280void LLTabContainerVertical::commitHoveredButton(S32 x, S32 y) 281void LLTabContainerVertical::commitHoveredButton(S32 x, S32 y)
281{ 282{
282 if (gFocusMgr.getMouseCapture() == this) 283 if (hasMouseCapture())
283 { 284 {
284 for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) 285 for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
285 { 286 {
@@ -473,7 +474,7 @@ BOOL LLTabContainerVertical::handleMouseDown( S32 x, S32 y, MASK mask )
473 if( tab_rect.pointInRect( x, y ) ) 474 if( tab_rect.pointInRect( x, y ) )
474 { 475 {
475 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; 476 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
476 gFocusMgr.setMouseCapture(this, NULL); 477 gFocusMgr.setMouseCapture(this);
477 gFocusMgr.setKeyboardFocus(tab_button, NULL); 478 gFocusMgr.setKeyboardFocus(tab_button, NULL);
478 } 479 }
479 } 480 }
@@ -536,7 +537,7 @@ BOOL LLTabContainerVertical::handleMouseUp( S32 x, S32 y, MASK mask )
536 537
537 commitHoveredButton(x, y); 538 commitHoveredButton(x, y);
538 LLPanel* cur_panel = getCurrentPanel(); 539 LLPanel* cur_panel = getCurrentPanel();
539 if (gFocusMgr.getMouseCapture() == this) 540 if (hasMouseCapture())
540 { 541 {
541 if (cur_panel) 542 if (cur_panel)
542 { 543 {
@@ -545,7 +546,7 @@ BOOL LLTabContainerVertical::handleMouseUp( S32 x, S32 y, MASK mask )
545 mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE); 546 mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE);
546 } 547 }
547 } 548 }
548 gFocusMgr.setMouseCapture(NULL, NULL); 549 gFocusMgr.setMouseCapture(NULL);
549 } 550 }
550 551
551 return handled; 552 return handled;
diff --git a/linden/indra/llui/lltabcontainervertical.h b/linden/indra/llui/lltabcontainervertical.h
index 81b2331..77817c2 100644
--- a/linden/indra/llui/lltabcontainervertical.h
+++ b/linden/indra/llui/lltabcontainervertical.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lltextbox.cpp b/linden/indra/llui/lltextbox.cpp
index d70f223..884d638 100644
--- a/linden/indra/llui/lltextbox.cpp
+++ b/linden/indra/llui/lltextbox.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -113,7 +114,7 @@ BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
113 handled = TRUE; 114 handled = TRUE;
114 115
115 // Route future Mouse messages here preemptively. (Release on mouse up.) 116 // Route future Mouse messages here preemptively. (Release on mouse up.)
116 gFocusMgr.setMouseCapture( this, NULL ); 117 gFocusMgr.setMouseCapture( this );
117 118
118 if (mSoundFlags & MOUSE_DOWN) 119 if (mSoundFlags & MOUSE_DOWN)
119 { 120 {
@@ -134,12 +135,12 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
134 // HACK: Only do this if there actually is a click callback, so that 135 // HACK: Only do this if there actually is a click callback, so that
135 // overly large text boxes in the older UI won't start eating clicks. 136 // overly large text boxes in the older UI won't start eating clicks.
136 if (mClickedCallback 137 if (mClickedCallback
137 && this == gFocusMgr.getMouseCapture()) 138 && hasMouseCapture())
138 { 139 {
139 handled = TRUE; 140 handled = TRUE;
140 141
141 // Release the mouse 142 // Release the mouse
142 gFocusMgr.setMouseCapture( NULL, NULL ); 143 gFocusMgr.setMouseCapture( NULL );
143 144
144 if (mSoundFlags & MOUSE_UP) 145 if (mSoundFlags & MOUSE_UP)
145 { 146 {
@@ -347,7 +348,7 @@ void LLTextBox::draw()
347void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent) 348void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
348{ 349{
349 // reparse line lengths 350 // reparse line lengths
350 setText(mText); 351 setLineLengths();
351 LLView::reshape(width, height, called_from_parent); 352 LLView::reshape(width, height, called_from_parent);
352} 353}
353 354
diff --git a/linden/indra/llui/lltextbox.h b/linden/indra/llui/lltextbox.h
index 7e445e1..45d6acb 100644
--- a/linden/indra/llui/lltextbox.h
+++ b/linden/indra/llui/lltextbox.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index 8f22545..787eba5 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -812,6 +813,31 @@ LLWString LLTextEditor::getWSubString(S32 pos, S32 len)
812 return mWText.substr(pos, len); 813 return mWText.substr(pos, len);
813} 814}
814 815
816LLTextSegment* LLTextEditor::getCurrentSegment()
817{
818 return getSegmentAtOffset(mCursorPos);
819}
820
821LLTextSegment* LLTextEditor::getPreviousSegment()
822{
823 // find segment index at character to left of cursor (or rightmost edge of selection)
824 S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
825 return idx >= 0 ? mSegments[idx] : NULL;
826}
827
828void LLTextEditor::getSelectedSegments(std::vector<LLTextSegment*>& segments)
829{
830 S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
831 S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
832 S32 first_idx = llmax(0, getSegmentIdxAtOffset(left));
833 S32 last_idx = llmax(0, first_idx, getSegmentIdxAtOffset(right));
834
835 for (S32 idx = first_idx; idx <= last_idx; ++idx)
836 {
837 segments.push_back(mSegments[idx]);
838 }
839}
840
815S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) 841S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round )
816{ 842{
817 // If round is true, if the position is on the right half of a character, the cursor 843 // If round is true, if the position is on the right half of a character, the cursor
@@ -1201,7 +1227,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
1201 setCursorAtLocalPos( x, y, TRUE ); 1227 setCursorAtLocalPos( x, y, TRUE );
1202 startSelection(); 1228 startSelection();
1203 } 1229 }
1204 gFocusMgr.setMouseCapture( this, &LLTextEditor::onMouseCaptureLost ); 1230 gFocusMgr.setMouseCapture( this );
1205 } 1231 }
1206 1232
1207 handled = TRUE; 1233 handled = TRUE;
@@ -1227,7 +1253,7 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
1227 mHoverSegment = NULL; 1253 mHoverSegment = NULL;
1228 if( getVisible() ) 1254 if( getVisible() )
1229 { 1255 {
1230 if(gFocusMgr.getMouseCapture() == this ) 1256 if(hasMouseCapture() )
1231 { 1257 {
1232 if( mIsSelecting ) 1258 if( mIsSelecting )
1233 { 1259 {
@@ -1360,9 +1386,9 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
1360 // Delay cursor flashing 1386 // Delay cursor flashing
1361 mKeystrokeTimer.reset(); 1387 mKeystrokeTimer.reset();
1362 1388
1363 if( gFocusMgr.getMouseCapture() == this ) 1389 if( hasMouseCapture() )
1364 { 1390 {
1365 gFocusMgr.setMouseCapture( NULL, NULL ); 1391 gFocusMgr.setMouseCapture( NULL );
1366 handled = TRUE; 1392 handled = TRUE;
1367 } 1393 }
1368 1394
@@ -2473,6 +2499,8 @@ void LLTextEditor::onFocusLost()
2473 2499
2474 // Make sure cursor is shown again 2500 // Make sure cursor is shown again
2475 getWindow()->showCursorFromMouseMove(); 2501 getWindow()->showCursorFromMouseMove();
2502
2503 LLUICtrl::onFocusLost();
2476} 2504}
2477 2505
2478void LLTextEditor::setEnabled(BOOL enabled) 2506void LLTextEditor::setEnabled(BOOL enabled)
@@ -3753,11 +3781,9 @@ S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset)
3753 } 3781 }
3754} 3782}
3755 3783
3756//static 3784void LLTextEditor::onMouseCaptureLost()
3757void LLTextEditor::onMouseCaptureLost( LLMouseHandler* old_captor )
3758{ 3785{
3759 LLTextEditor* self = (LLTextEditor*) old_captor; 3786 endSelection();
3760 self->endSelection();
3761} 3787}
3762 3788
3763void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdata) 3789void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdata)
diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h
index e5ba8ca..32375be 100644
--- a/linden/indra/llui/lltexteditor.h
+++ b/linden/indra/llui/lltexteditor.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -94,6 +95,8 @@ public:
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, void *cargo_data, 96 EDragAndDropType cargo_type, void *cargo_data,
96 EAcceptance *accept, LLString& tooltip_msg); 97 EAcceptance *accept, LLString& tooltip_msg);
98 virtual void onMouseCaptureLost();
99
97 100
98 // view overrides 101 // view overrides
99 virtual void reshape(S32 width, S32 height, BOOL called_from_parent); 102 virtual void reshape(S32 width, S32 height, BOOL called_from_parent);
@@ -209,7 +212,6 @@ public:
209 void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; } 212 void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; }
210 213
211 // Callbacks 214 // Callbacks
212 static void onMouseCaptureLost( LLMouseHandler* old_captor );
213 static void setLinkColor(LLColor4 color) { mLinkColor = color; } 215 static void setLinkColor(LLColor4 color) { mLinkColor = color; }
214 static void setURLCallbacks( void (*callback1) (const char* url), 216 static void setURLCallbacks( void (*callback1) (const char* url),
215 BOOL (*callback2) (LLString url) ) 217 BOOL (*callback2) (LLString url) )
@@ -239,6 +241,10 @@ public:
239 llwchar getWChar(S32 pos); 241 llwchar getWChar(S32 pos);
240 LLWString getWSubString(S32 pos, S32 len); 242 LLWString getWSubString(S32 pos, S32 len);
241 243
244 LLTextSegment* getCurrentSegment();
245 LLTextSegment* getPreviousSegment();
246 void getSelectedSegments(std::vector<LLTextSegment*>& segments);
247
242protected: 248protected:
243 S32 getLength() const; 249 S32 getLength() const;
244 void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ); 250 void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp );
diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp
index 61dede2..9d689b5 100644
--- a/linden/indra/llui/llui.cpp
+++ b/linden/indra/llui/llui.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -74,6 +75,7 @@ LLImageProviderInterface* LLUI::sImageProvider = NULL;
74LLUIAudioCallback LLUI::sAudioCallback = NULL; 75LLUIAudioCallback LLUI::sAudioCallback = NULL;
75LLVector2 LLUI::sGLScaleFactor(1.f, 1.f); 76LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
76LLWindow* LLUI::sWindow = NULL; 77LLWindow* LLUI::sWindow = NULL;
78LLHtmlHelp* LLUI::sHtmlHelp = NULL;
77BOOL LLUI::sShowXUINames = FALSE; 79BOOL LLUI::sShowXUINames = FALSE;
78// 80//
79// Functions 81// Functions
@@ -406,7 +408,7 @@ void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max
406 408
407void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color ) 409void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color )
408{ 410{
409 gl_draw_scaled_rotated_image( x, y, image->getWidth(), image->getHeight(), 0.f, image, color ); 411 gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color );
410} 412}
411 413
412void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color) 414void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color)
@@ -458,8 +460,8 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
458 460
459 glColor4fv(color.mV); 461 glColor4fv(color.mV);
460 462
461 F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(); 463 F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
462 F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(); 464 F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
463 465
464 glBegin(GL_QUADS); 466 glBegin(GL_QUADS);
465 { 467 {
@@ -592,7 +594,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
592 594
593void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color) 595void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color)
594{ 596{
595 gl_draw_scaled_rotated_image( x, y, image->getWidth(), image->getHeight(), degrees, image, color ); 597 gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color );
596} 598}
597 599
598void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color) 600void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color)
@@ -1742,6 +1744,10 @@ LLString LLUI::locateSkin(const LLString& filename)
1742 if (!gDirUtilp->fileExists(found_file)) 1744 if (!gDirUtilp->fileExists(found_file))
1743 { 1745 {
1744 LLString localization(sConfigGroup->getString("Language")); 1746 LLString localization(sConfigGroup->getString("Language"));
1747 if(localization == "default")
1748 {
1749 localization = sConfigGroup->getString("SystemLanguage");
1750 }
1745 LLString local_skin = "xui" + slash + localization + slash + filename; 1751 LLString local_skin = "xui" + slash + localization + slash + filename;
1746 found_file = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, local_skin); 1752 found_file = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, local_skin);
1747 } 1753 }
@@ -1781,3 +1787,9 @@ LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name)
1781 } 1787 }
1782 return LLUUID( foundValue ); 1788 return LLUUID( foundValue );
1783} 1789}
1790
1791// static
1792void LLUI::setHtmlHelp(LLHtmlHelp* html_help)
1793{
1794 LLUI::sHtmlHelp = html_help;
1795}
diff --git a/linden/indra/llui/llui.h b/linden/indra/llui/llui.h
index cd57990..6b8a86a 100644
--- a/linden/indra/llui/llui.h
+++ b/linden/indra/llui/llui.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -34,6 +35,7 @@
34#include "llcontrol.h" 35#include "llcontrol.h"
35#include "llrect.h" 36#include "llrect.h"
36#include "llcoord.h" 37#include "llcoord.h"
38#include "llhtmlhelp.h"
37 39
38class LLColor4; 40class LLColor4;
39class LLVector3; 41class LLVector3;
@@ -170,6 +172,7 @@ public:
170 static void setLineWidth(F32 width); 172 static void setLineWidth(F32 width);
171 static LLUUID findAssetUUIDByName(const LLString& name); 173 static LLUUID findAssetUUIDByName(const LLString& name);
172 static LLVector2 getWindowSize(); 174 static LLVector2 getWindowSize();
175 static void setHtmlHelp(LLHtmlHelp* html_help);
173public: 176public:
174 static LLControlGroup* sConfigGroup; 177 static LLControlGroup* sConfigGroup;
175 static LLControlGroup* sColorsGroup; 178 static LLControlGroup* sColorsGroup;
@@ -179,6 +182,7 @@ public:
179 static LLVector2 sGLScaleFactor; 182 static LLVector2 sGLScaleFactor;
180 static LLWindow* sWindow; 183 static LLWindow* sWindow;
181 static BOOL sShowXUINames; 184 static BOOL sShowXUINames;
185 static LLHtmlHelp* sHtmlHelp;
182}; 186};
183 187
184// UI widgets 188// UI widgets
diff --git a/linden/indra/llui/llui.vcproj b/linden/indra/llui/llui.vcproj
index e3d0da6..37428d2 100644
--- a/linden/indra/llui/llui.vcproj
+++ b/linden/indra/llui/llui.vcproj
@@ -310,6 +310,9 @@
310 RelativePath=".\llfocusmgr.h"> 310 RelativePath=".\llfocusmgr.h">
311 </File> 311 </File>
312 <File 312 <File
313 RelativePath=".\llhtmlhelp.h">
314 </File>
315 <File
313 RelativePath=".\lliconctrl.h"> 316 RelativePath=".\lliconctrl.h">
314 </File> 317 </File>
315 <File 318 <File
diff --git a/linden/indra/llui/lluiconstants.h b/linden/indra/llui/lluiconstants.h
index d941e82..a51267a 100644
--- a/linden/indra/llui/lluiconstants.h
+++ b/linden/indra/llui/lluiconstants.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp
index 977f523..1762d7c 100644
--- a/linden/indra/llui/lluictrl.cpp
+++ b/linden/indra/llui/lluictrl.cpp
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2001-2007, Linden Research, Inc. 6 * Copyright (c) 2001-2007, Linden Research, Inc.
7 * 7 *
8 * Second Life Viewer Source Code
8 * The source code in this file ("Source Code") is provided by Linden Lab 9 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0 10 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -45,6 +46,7 @@ const U32 MAX_STRING_LENGTH = 10;
45 46
46LLUICtrl::LLUICtrl() : 47LLUICtrl::LLUICtrl() :
47 mCommitCallback(NULL), 48 mCommitCallback(NULL),
49 mFocusLostCallback(NULL),
48 mFocusReceivedCallback(NULL), 50 mFocusReceivedCallback(NULL),
49 mFocusChangedCallback(NULL), 51 mFocusChangedCallback(NULL),
50 mValidateCallback(NULL), 52 mValidateCallback(NULL),
@@ -63,6 +65,7 @@ LLUICtrl::LLUICtrl(const LLString& name, const LLRect& rect, BOOL mouse_opaque,
63 // of buttons in the UI. JC 7/20/2002 65 // of buttons in the UI. JC 7/20/2002
64 LLView( name, rect, mouse_opaque, reshape ), 66 LLView( name, rect, mouse_opaque, reshape ),
65 mCommitCallback( on_commit_callback) , 67 mCommitCallback( on_commit_callback) ,
68 mFocusLostCallback( NULL ),
66 mFocusReceivedCallback( NULL ), 69 mFocusReceivedCallback( NULL ),
67 mFocusChangedCallback( NULL ), 70 mFocusChangedCallback( NULL ),
68 mValidateCallback( NULL ), 71 mValidateCallback( NULL ),
@@ -76,6 +79,12 @@ LLUICtrl::LLUICtrl(const LLString& name, const LLRect& rect, BOOL mouse_opaque,
76LLUICtrl::~LLUICtrl() 79LLUICtrl::~LLUICtrl()
77{ 80{
78 gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() 81 gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
82
83 if( gFocusMgr.getTopCtrl() == this )
84 {
85 llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl;
86 gFocusMgr.removeTopCtrlWithoutCallback( this );
87 }
79} 88}
80 89
81void LLUICtrl::onCommit() 90void LLUICtrl::onCommit()
@@ -170,6 +179,11 @@ void LLUICtrl::onFocusReceived()
170 179
171void LLUICtrl::onFocusLost() 180void LLUICtrl::onFocusLost()
172{ 181{
182 if( mFocusLostCallback )
183 {
184 mFocusLostCallback( this, mCallbackUserData );
185 }
186
173 if( mFocusChangedCallback ) 187 if( mFocusChangedCallback )
174 { 188 {
175 mFocusChangedCallback( this, mCallbackUserData ); 189 mFocusChangedCallback( this, mCallbackUserData );
diff --git a/linden/indra/llui/lluictrl.h b/linden/indra/llui/lluictrl.h
index 47b5d66..3093437 100644
--- a/linden/indra/llui/lluictrl.h
+++ b/linden/indra/llui/lluictrl.h
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2001-2007, Linden Research, Inc. 6 * Copyright (c) 2001-2007, Linden Research, Inc.
7 * 7 *
8 * Second Life Viewer Source Code
8 * The source code in this file ("Source Code") is provided by Linden Lab 9 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0 10 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -123,6 +124,7 @@ public:
123 virtual void setMaxValue(LLSD max_value); 124 virtual void setMaxValue(LLSD max_value);
124 125
125 // In general, only LLPanel uses these. 126 // In general, only LLPanel uses these.
127 void setFocusLostCallback(void (*cb)(LLUICtrl* caller, void* user_data)) { mFocusLostCallback = cb; }
126 void setFocusReceivedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusReceivedCallback = cb; } 128 void setFocusReceivedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusReceivedCallback = cb; }
127 void setFocusChangedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusChangedCallback = cb; } 129 void setFocusChangedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusChangedCallback = cb; }
128 130
@@ -154,6 +156,7 @@ protected:
154protected: 156protected:
155 157
156 void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata ); 158 void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata );
159 void (*mFocusLostCallback)( LLUICtrl* caller, void* userdata );
157 void (*mFocusReceivedCallback)( LLUICtrl* ctrl, void* userdata ); 160 void (*mFocusReceivedCallback)( LLUICtrl* ctrl, void* userdata );
158 void (*mFocusChangedCallback)( LLUICtrl* ctrl, void* userdata ); 161 void (*mFocusChangedCallback)( LLUICtrl* ctrl, void* userdata );
159 BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata ); 162 BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata );
diff --git a/linden/indra/llui/lluictrlfactory.cpp b/linden/indra/llui/lluictrlfactory.cpp
index 77ef749..475ef2e 100644
--- a/linden/indra/llui/lluictrlfactory.cpp
+++ b/linden/indra/llui/lluictrlfactory.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2003-2007, Linden Research, Inc. 5 * Copyright (c) 2003-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -241,6 +242,10 @@ void LLUICtrlFactory::setupPaths()
241 if (LLUI::sConfigGroup) 242 if (LLUI::sConfigGroup)
242 { 243 {
243 language = LLUI::sConfigGroup->getString("Language"); 244 language = LLUI::sConfigGroup->getString("Language");
245 if(language == "default")
246 {
247 language = LLUI::sConfigGroup->getString("SystemLanguage");
248 }
244 } 249 }
245 path_val_ui.setArg("[Language]", language); 250 path_val_ui.setArg("[Language]", language);
246 LLString fullpath = app_dir + path_val_ui.getString(); 251 LLString fullpath = app_dir + path_val_ui.getString();
diff --git a/linden/indra/llui/lluictrlfactory.h b/linden/indra/llui/lluictrlfactory.h
index b96dc5d..18b0ba9 100644
--- a/linden/indra/llui/lluictrlfactory.h
+++ b/linden/indra/llui/lluictrlfactory.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2003-2007, Linden Research, Inc. 5 * Copyright (c) 2003-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lluistring.cpp b/linden/indra/llui/lluistring.cpp
index 5029082..49b6fca 100755
--- a/linden/indra/llui/lluistring.cpp
+++ b/linden/indra/llui/lluistring.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc. 5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lluistring.h b/linden/indra/llui/lluistring.h
index efd200a..37792aa 100755
--- a/linden/indra/llui/lluistring.h
+++ b/linden/indra/llui/lluistring.h
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2006-2007, Linden Research, Inc. 6 * Copyright (c) 2006-2007, Linden Research, Inc.
7 * 7 *
8 * Second Life Viewer Source Code
8 * The source code in this file ("Source Code") is provided by Linden Lab 9 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0 10 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/lluixmltags.h b/linden/indra/llui/lluixmltags.h
index 5de4d90..08c5f67 100644
--- a/linden/indra/llui/lluixmltags.h
+++ b/linden/indra/llui/lluixmltags.h
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (c) 2006-2007, Linden Research, Inc. 4 * Copyright (c) 2006-2007, Linden Research, Inc.
5 * 5 *
6 * Second Life Viewer Source Code
6 * The source code in this file ("Source Code") is provided by Linden Lab 7 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0 8 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement 9 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llundo.cpp b/linden/indra/llui/llundo.cpp
index b662a1a..4e62bad 100644
--- a/linden/indra/llui/llundo.cpp
+++ b/linden/indra/llui/llundo.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llundo.h b/linden/indra/llui/llundo.h
index 10d556f..9a4bece 100644
--- a/linden/indra/llui/llundo.h
+++ b/linden/indra/llui/llundo.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2000-2007, Linden Research, Inc. 5 * Copyright (c) 2000-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp
index 13f1ddc..d150e10 100644
--- a/linden/indra/llui/llview.cpp
+++ b/linden/indra/llui/llview.cpp
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2001-2007, Linden Research, Inc. 6 * Copyright (c) 2001-2007, Linden Research, Inc.
7 * 7 *
8 * Second Life Viewer Source Code
8 * The source code in this file ("Source Code") is provided by Linden Lab 9 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0 10 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -174,18 +175,12 @@ LLView::~LLView()
174 gFocusMgr.removeKeyboardFocusWithoutCallback( this ); 175 gFocusMgr.removeKeyboardFocusWithoutCallback( this );
175 } 176 }
176 177
177 if( gFocusMgr.getMouseCapture() == this ) 178 if( hasMouseCapture() )
178 { 179 {
179 llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; 180 llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl;
180 gFocusMgr.removeMouseCaptureWithoutCallback( this ); 181 gFocusMgr.removeMouseCaptureWithoutCallback( this );
181 } 182 }
182 183
183 if( gFocusMgr.getTopView() == this )
184 {
185 llwarns << "View holding top view deleted: " << getName() << ". Top view removed." << llendl;
186 gFocusMgr.removeTopViewWithoutCallback( this );
187 }
188
189 sViewHandleMap.erase(mViewHandle); 184 sViewHandleMap.erase(mViewHandle);
190 185
191 deleteAllChildren(); 186 deleteAllChildren();
@@ -752,9 +747,9 @@ void LLView::setEnabled(BOOL enabled)
752// virtual 747// virtual
753void LLView::setVisible(BOOL visible) 748void LLView::setVisible(BOOL visible)
754{ 749{
755 if( !visible && (gFocusMgr.getTopView() == this) ) 750 if( !visible && (gFocusMgr.getTopCtrl() == this) )
756 { 751 {
757 gFocusMgr.setTopView( NULL, NULL ); 752 gFocusMgr.setTopCtrl( NULL );
758 } 753 }
759 754
760 if ( mVisible != visible ) 755 if ( mVisible != visible )
@@ -1053,7 +1048,14 @@ LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
1053 return handled_view; 1048 return handled_view;
1054} 1049}
1055 1050
1051void LLView::onMouseCaptureLost()
1052{
1053}
1056 1054
1055BOOL LLView::hasMouseCapture()
1056{
1057 return gFocusMgr.getMouseCapture() == this;
1058}
1057 1059
1058BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask) 1060BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
1059{ 1061{
@@ -1610,6 +1612,13 @@ const LLRect LLView::getLocalRect() const
1610 return local_rect; 1612 return local_rect;
1611} 1613}
1612 1614
1615const LLRect LLView::getLocalSnapRect() const
1616{
1617 LLRect local_snap_rect = getSnapRect();
1618 local_snap_rect.translate(-mRect.mLeft, -mRect.mBottom);
1619 return local_snap_rect;
1620}
1621
1613void LLView::updateRect() 1622void LLView::updateRect()
1614{ 1623{
1615 if (mSpanChildren && mChildList.size()) 1624 if (mSpanChildren && mChildList.size())
@@ -2106,6 +2115,12 @@ const LLCtrlQuery & LLView::getFocusRootsQuery()
2106} 2115}
2107 2116
2108 2117
2118void LLView::userSetShape(const LLRect& new_rect)
2119{
2120 reshape(new_rect.getWidth(), new_rect.getHeight());
2121 translate(new_rect.mLeft - mRect.mLeft, new_rect.mBottom - mRect.mBottom);
2122}
2123
2109LLView* LLView::findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, 2124LLView* LLView::findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir,
2110 LLView::ESnapType snap_type, S32 threshold, S32 padding) 2125 LLView::ESnapType snap_type, S32 threshold, S32 padding)
2111{ 2126{
@@ -2127,8 +2142,7 @@ LLView* LLView::findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir,
2127 BOOL snapped_x = FALSE; 2142 BOOL snapped_x = FALSE;
2128 BOOL snapped_y = FALSE; 2143 BOOL snapped_y = FALSE;
2129 2144
2130 LLRect parent_local_snap_rect = mParentView->getSnapRect(); 2145 LLRect parent_local_snap_rect = mParentView->getLocalSnapRect();
2131 parent_local_snap_rect.translate(-mParentView->getRect().mLeft, -mParentView->getRect().mBottom);
2132 2146
2133 if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS) 2147 if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS)
2134 { 2148 {
@@ -2303,8 +2317,7 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna
2303 BOOL snapped_x = FALSE; 2317 BOOL snapped_x = FALSE;
2304 BOOL snapped_y = FALSE; 2318 BOOL snapped_y = FALSE;
2305 2319
2306 LLRect parent_local_snap_rect = mParentView->getSnapRect(); 2320 LLRect parent_local_snap_rect = mParentView->getLocalSnapRect();
2307 parent_local_snap_rect.translate(-mParentView->getRect().mLeft, -mParentView->getRect().mBottom);
2308 2321
2309 if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS) 2322 if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS)
2310 { 2323 {
diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h
index 3885789..cb9a35c 100644
--- a/linden/indra/llui/llview.h
+++ b/linden/indra/llui/llview.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
@@ -313,6 +314,7 @@ public:
313 const LLRect getScreenRect() const; 314 const LLRect getScreenRect() const;
314 const LLRect getLocalRect() const; 315 const LLRect getLocalRect() const;
315 virtual const LLRect getSnapRect() const { return mRect; } 316 virtual const LLRect getSnapRect() const { return mRect; }
317 virtual const LLRect getLocalSnapRect() const;
316 318
317 virtual LLRect getRequiredRect(); // Get required size for this object. 0 for width/height means don't care. 319 virtual LLRect getRequiredRect(); // Get required size for this object. 0 for width/height means don't care.
318 virtual void updateRect(); // apply procedural updates to own rectangle 320 virtual void updateRect(); // apply procedural updates to own rectangle
@@ -334,12 +336,13 @@ public:
334 336
335 // Default behavior is to use reshape flags to resize child views 337 // Default behavior is to use reshape flags to resize child views
336 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); 338 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
337
338 virtual void translate( S32 x, S32 y ); 339 virtual void translate( S32 x, S32 y );
339 virtual void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); } 340 virtual void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
340 BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); 341 BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside );
341 LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); 342
342 LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); 343 virtual void userSetShape(const LLRect& new_rect);
344 virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0);
345 virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0);
343 346
344 // Defaults to other_view->getVisible() 347 // Defaults to other_view->getVisible()
345 virtual BOOL canSnapTo(LLView* other_view); 348 virtual BOOL canSnapTo(LLView* other_view);
@@ -364,6 +367,8 @@ public:
364 /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 367 /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
365 /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); 368 /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
366 /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); 369 /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
370 /*virtual*/ void onMouseCaptureLost();
371 /*virtual*/ BOOL hasMouseCapture();
367 372
368 // Default behavior is to pass the tooltip event to children, 373 // Default behavior is to pass the tooltip event to children,
369 // then display mToolTipMsg if no child handled it. 374 // then display mToolTipMsg if no child handled it.
diff --git a/linden/indra/llui/llviewborder.cpp b/linden/indra/llui/llviewborder.cpp
index c26a818..4c2b602 100644
--- a/linden/indra/llui/llviewborder.cpp
+++ b/linden/indra/llui/llviewborder.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llviewborder.h b/linden/indra/llui/llviewborder.h
index 2795a71..7e5de4b 100644
--- a/linden/indra/llui/llviewborder.h
+++ b/linden/indra/llui/llviewborder.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llviewquery.cpp b/linden/indra/llui/llviewquery.cpp
index 89b2192..3f9ccf4 100644
--- a/linden/indra/llui/llviewquery.cpp
+++ b/linden/indra/llui/llviewquery.cpp
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement
diff --git a/linden/indra/llui/llviewquery.h b/linden/indra/llui/llviewquery.h
index 7ab401a..a35726a 100644
--- a/linden/indra/llui/llviewquery.h
+++ b/linden/indra/llui/llviewquery.h
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 * 6 *
7 * Second Life Viewer Source Code
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement 10 * ("GPL"), unless you have obtained a separate licensing agreement