aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llui')
-rw-r--r--linden/indra/llui/llalertdialog.cpp47
-rw-r--r--linden/indra/llui/llalertdialog.h9
-rw-r--r--linden/indra/llui/llbutton.cpp281
-rw-r--r--linden/indra/llui/llbutton.h72
-rw-r--r--linden/indra/llui/llcallbackmap.h4
-rw-r--r--linden/indra/llui/llcheckboxctrl.cpp23
-rw-r--r--linden/indra/llui/llcheckboxctrl.h4
-rw-r--r--linden/indra/llui/llclipboard.cpp4
-rw-r--r--linden/indra/llui/llclipboard.h4
-rw-r--r--linden/indra/llui/llcombobox.cpp514
-rw-r--r--linden/indra/llui/llcombobox.h61
-rw-r--r--linden/indra/llui/llctrlselectioninterface.cpp4
-rw-r--r--linden/indra/llui/llctrlselectioninterface.h6
-rw-r--r--linden/indra/llui/lldraghandle.cpp4
-rw-r--r--linden/indra/llui/lldraghandle.h5
-rw-r--r--linden/indra/llui/lleditmenuhandler.cpp4
-rw-r--r--linden/indra/llui/lleditmenuhandler.h4
-rw-r--r--linden/indra/llui/llfloater.cpp39
-rw-r--r--linden/indra/llui/llfloater.h4
-rw-r--r--linden/indra/llui/llfocusmgr.cpp45
-rw-r--r--linden/indra/llui/llfocusmgr.h13
-rw-r--r--linden/indra/llui/llhtmlhelp.h5
-rw-r--r--linden/indra/llui/lliconctrl.cpp20
-rw-r--r--linden/indra/llui/lliconctrl.h6
-rw-r--r--linden/indra/llui/llkeywords.cpp18
-rw-r--r--linden/indra/llui/llkeywords.h8
-rw-r--r--linden/indra/llui/lllineeditor.cpp363
-rw-r--r--linden/indra/llui/lllineeditor.h42
-rw-r--r--linden/indra/llui/llmemberlistener.h4
-rw-r--r--linden/indra/llui/llmenugl.cpp11
-rw-r--r--linden/indra/llui/llmenugl.h4
-rw-r--r--linden/indra/llui/llmodaldialog.cpp16
-rw-r--r--linden/indra/llui/llmodaldialog.h6
-rw-r--r--linden/indra/llui/llpanel.cpp236
-rw-r--r--linden/indra/llui/llpanel.h13
-rw-r--r--linden/indra/llui/llradiogroup.cpp6
-rw-r--r--linden/indra/llui/llradiogroup.h6
-rw-r--r--linden/indra/llui/llresizebar.cpp4
-rw-r--r--linden/indra/llui/llresizebar.h4
-rw-r--r--linden/indra/llui/llresizehandle.cpp6
-rw-r--r--linden/indra/llui/llresizehandle.h4
-rw-r--r--linden/indra/llui/llresmgr.cpp4
-rw-r--r--linden/indra/llui/llresmgr.h4
-rw-r--r--linden/indra/llui/llrootview.cpp4
-rw-r--r--linden/indra/llui/llrootview.h4
-rw-r--r--linden/indra/llui/llscrollbar.cpp48
-rw-r--r--linden/indra/llui/llscrollbar.h7
-rw-r--r--linden/indra/llui/llscrollcontainer.cpp42
-rw-r--r--linden/indra/llui/llscrollcontainer.h4
-rw-r--r--linden/indra/llui/llscrollingpanellist.cpp4
-rw-r--r--linden/indra/llui/llscrollingpanellist.h4
-rw-r--r--linden/indra/llui/llscrolllistctrl.cpp1048
-rw-r--r--linden/indra/llui/llscrolllistctrl.h197
-rw-r--r--linden/indra/llui/llslider.cpp149
-rw-r--r--linden/indra/llui/llslider.h11
-rw-r--r--linden/indra/llui/llsliderctrl.cpp8
-rw-r--r--linden/indra/llui/llsliderctrl.h6
-rw-r--r--linden/indra/llui/llspinctrl.cpp10
-rw-r--r--linden/indra/llui/llspinctrl.h6
-rw-r--r--linden/indra/llui/llstyle.cpp6
-rw-r--r--linden/indra/llui/llstyle.h4
-rw-r--r--linden/indra/llui/lltabcontainer.cpp43
-rw-r--r--linden/indra/llui/lltabcontainer.h7
-rw-r--r--linden/indra/llui/lltabcontainervertical.cpp14
-rw-r--r--linden/indra/llui/lltabcontainervertical.h4
-rw-r--r--linden/indra/llui/lltextbox.cpp14
-rw-r--r--linden/indra/llui/lltextbox.h6
-rw-r--r--linden/indra/llui/lltexteditor.cpp539
-rw-r--r--linden/indra/llui/lltexteditor.h57
-rw-r--r--linden/indra/llui/llui.cpp461
-rw-r--r--linden/indra/llui/llui.h90
-rw-r--r--linden/indra/llui/llui_vc9.vcproj596
-rw-r--r--linden/indra/llui/lluiconstants.h4
-rw-r--r--linden/indra/llui/lluictrl.cpp203
-rw-r--r--linden/indra/llui/lluictrl.h59
-rw-r--r--linden/indra/llui/lluictrlfactory.cpp18
-rw-r--r--linden/indra/llui/lluictrlfactory.h4
-rw-r--r--linden/indra/llui/lluistring.cpp4
-rw-r--r--linden/indra/llui/lluistring.h4
-rw-r--r--linden/indra/llui/lluixmltags.h5
-rw-r--r--linden/indra/llui/llundo.cpp4
-rw-r--r--linden/indra/llui/llundo.h4
-rw-r--r--linden/indra/llui/llview.cpp440
-rw-r--r--linden/indra/llui/llview.h36
-rw-r--r--linden/indra/llui/llviewborder.cpp6
-rw-r--r--linden/indra/llui/llviewborder.h4
-rw-r--r--linden/indra/llui/llviewquery.cpp65
-rw-r--r--linden/indra/llui/llviewquery.h36
88 files changed, 4267 insertions, 1963 deletions
diff --git a/linden/indra/llui/llalertdialog.cpp b/linden/indra/llui/llalertdialog.cpp
index fd0262d..204fb10 100644
--- a/linden/indra/llui/llalertdialog.cpp
+++ b/linden/indra/llui/llalertdialog.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -41,6 +41,7 @@
41#include "llcheckboxctrl.h" 41#include "llcheckboxctrl.h"
42#include "llkeyboard.h" 42#include "llkeyboard.h"
43#include "llfocusmgr.h" 43#include "llfocusmgr.h"
44#include "lliconctrl.h"
44#include "llui.h" 45#include "llui.h"
45#include "llxmlnode.h" 46#include "llxmlnode.h"
46#include "lllineeditor.h" 47#include "lllineeditor.h"
@@ -143,6 +144,7 @@ LLAlertDialog::LLAlertDialog( const LLAlertDialogTemplate* xml_template,
143 mDefaultOption( 0 ), 144 mDefaultOption( 0 ),
144 mOptionChosen( -1 ), 145 mOptionChosen( -1 ),
145 mCheck(NULL), 146 mCheck(NULL),
147 mCaution(xml_template->mCaution),
146 mUnique(xml_template->mUnique), 148 mUnique(xml_template->mUnique),
147 mIgnorable(xml_template->mIgnorable), 149 mIgnorable(xml_template->mIgnorable),
148 mLabel(xml_template->mLabel), 150 mLabel(xml_template->mLabel),
@@ -211,6 +213,16 @@ bool LLAlertDialog::show()
211 } 213 }
212 } 214 }
213 215
216 // If this is a caution message, change the color and add an icon.
217 if (mCaution)
218 {
219 setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertCautionBoxColor" ) );
220 }
221 else
222 {
223 setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertBoxColor" ) );
224 }
225
214 // Check to see if we are already displaying the alert 226 // Check to see if we are already displaying the alert
215 if (mUnique) 227 if (mUnique)
216 { 228 {
@@ -311,19 +323,35 @@ void LLAlertDialog::createDialog(const std::vector<LLString>* optionsp, S32 defa
311 dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f)); 323 dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f));
312 dialog_height += EDITOR_HEIGHT; 324 dialog_height += EDITOR_HEIGHT;
313 } 325 }
314 326 if (mCaution)
327 {
328 // Make room for the caution icon.
329 dialog_width += 32 + HPAD;
330 }
315 reshape( dialog_width, dialog_height, FALSE ); 331 reshape( dialog_width, dialog_height, FALSE );
316 332
317 S32 msg_y = mRect.getHeight() - VPAD; 333 S32 msg_y = mRect.getHeight() - VPAD;
334 S32 msg_x = HPAD;
318 if (hasTitleBar()) 335 if (hasTitleBar())
319 { 336 {
320 msg_y -= LINE_HEIGHT; // room for title 337 msg_y -= LINE_HEIGHT; // room for title
321 } 338 }
322 339
340 if (mCaution)
341 {
342 LLIconCtrl* icon = new LLIconCtrl("icon", LLRect(msg_x, msg_y, msg_x+32, msg_y-32), "notify_caution_icon.tga");
343 icon->setMouseOpaque(FALSE);
344 addChild(icon);
345 msg_x += 32 + HPAD;
346 msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertCautionTextColor" ) );
347 }
348 else
349 {
350 msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) );
351 }
323 LLRect rect; 352 LLRect rect;
324 rect.setLeftTopAndSize( HPAD, msg_y, text_rect.getWidth(), text_rect.getHeight() ); 353 rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() );
325 msg_box->setRect( rect ); 354 msg_box->setRect( rect );
326 msg_box->setColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) );
327 addChild(msg_box); 355 addChild(msg_box);
328 356
329 // Buttons 357 // Buttons
@@ -688,6 +716,15 @@ bool LLAlertDialog::parseAlerts(const LLString& xml_filename, LLControlGroup* se
688 xml_template->mModal = modal; 716 xml_template->mModal = modal;
689 } 717 }
690 } 718 }
719 // caution=
720 BOOL caution;
721 if (alert->getAttributeBOOL("caution", caution))
722 {
723 if (xml_template)
724 {
725 xml_template->mCaution = caution;
726 }
727 }
691 // unique= 728 // unique=
692 BOOL unique; 729 BOOL unique;
693 if (alert->getAttributeBOOL("unique", unique)) 730 if (alert->getAttributeBOOL("unique", unique))
diff --git a/linden/indra/llui/llalertdialog.h b/linden/indra/llui/llalertdialog.h
index 016a4b4..31f4769 100644
--- a/linden/indra/llui/llalertdialog.h
+++ b/linden/indra/llui/llalertdialog.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -78,6 +78,7 @@ public:
78 78
79 bool setCheckBox( const LLString&, const LLString& ); 79 bool setCheckBox( const LLString&, const LLString& );
80 void setOptionEnabled( S32 option, BOOL enable ); 80 void setOptionEnabled( S32 option, BOOL enable );
81 void setCaution(BOOL val = TRUE) { mCaution = val; }
81 // If mUnique==TRUE only one copy of this message should exist 82 // If mUnique==TRUE only one copy of this message should exist
82 void setUnique(BOOL val = TRUE) { mUnique = val; } 83 void setUnique(BOOL val = TRUE) { mUnique = val; }
83 void setEditTextCallback(alert_text_callback_t callback, void *user_data); 84 void setEditTextCallback(alert_text_callback_t callback, void *user_data);
@@ -129,6 +130,7 @@ protected:
129 S32 mDefaultOption; 130 S32 mDefaultOption;
130 BOOL mOptionChosen; 131 BOOL mOptionChosen;
131 LLCheckBoxCtrl* mCheck; 132 LLCheckBoxCtrl* mCheck;
133 BOOL mCaution;
132 BOOL mUnique; 134 BOOL mUnique;
133 S32 mIgnorable; 135 S32 mIgnorable;
134 LLString mLabel; 136 LLString mLabel;
@@ -163,7 +165,7 @@ private:
163class LLAlertDialogTemplate : public LLRefCount 165class LLAlertDialogTemplate : public LLRefCount
164{ 166{
165public: 167public:
166 LLAlertDialogTemplate() : mTitle(), mURLOption(0), mModal(FALSE), mUnique(FALSE), mIgnorable(0), mDefaultOption(0) {} 168 LLAlertDialogTemplate() : mTitle(), mURLOption(0), mModal(FALSE), mCaution(FALSE), mUnique(FALSE), mIgnorable(0), mDefaultOption(0) {}
167 169
168 void addOption(const LLString& label, const LLString& ignore_text, BOOL is_default = FALSE) 170 void addOption(const LLString& label, const LLString& ignore_text, BOOL is_default = FALSE)
169 { 171 {
@@ -205,6 +207,7 @@ public:
205 LLString mURL; // Some alerts will direct the resident to a URL 207 LLString mURL; // Some alerts will direct the resident to a URL
206 S32 mURLOption; 208 S32 mURLOption;
207 BOOL mModal; 209 BOOL mModal;
210 BOOL mCaution;
208 BOOL mUnique; 211 BOOL mUnique;
209 S32 mIgnorable; // 0 = Never Ignore, 1 = Do default option, 2 = Do saved option 212 S32 mIgnorable; // 0 = Never Ignore, 1 = Do default option, 2 = Do saved option
210 std::vector<LLString> mOptions; 213 std::vector<LLString> mOptions;
diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp
index 71260b2..9fa1c8e 100644
--- a/linden/indra/llui/llbutton.cpp
+++ b/linden/indra/llui/llbutton.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -59,9 +59,6 @@ S32 BTN_HEIGHT = 0;
59S32 BTN_GRID = 12; 59S32 BTN_GRID = 12;
60S32 BORDER_SIZE = 1; 60S32 BORDER_SIZE = 1;
61 61
62// static
63LLFrameTimer LLButton::sFlashingTimer;
64
65LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& control_name, void (*click_callback)(void*), void *callback_data) 62LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& control_name, void (*click_callback)(void*), void *callback_data)
66: LLUICtrl(name, rect, TRUE, NULL, NULL), 63: LLUICtrl(name, rect, TRUE, NULL, NULL),
67 mClickedCallback( click_callback ), 64 mClickedCallback( click_callback ),
@@ -79,6 +76,7 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co
79 mImageDisabled( NULL ), 76 mImageDisabled( NULL ),
80 mImageDisabledSelected( NULL ), 77 mImageDisabledSelected( NULL ),
81 mToggleState( FALSE ), 78 mToggleState( FALSE ),
79 mIsToggle( FALSE ),
82 mScaleImage( TRUE ), 80 mScaleImage( TRUE ),
83 mDropShadowedText( TRUE ), 81 mDropShadowedText( TRUE ),
84 mBorderEnabled( FALSE ), 82 mBorderEnabled( FALSE ),
@@ -86,8 +84,6 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co
86 mHAlign( LLFontGL::HCENTER ), 84 mHAlign( LLFontGL::HCENTER ),
87 mLeftHPad( LLBUTTON_H_PAD ), 85 mLeftHPad( LLBUTTON_H_PAD ),
88 mRightHPad( LLBUTTON_H_PAD ), 86 mRightHPad( LLBUTTON_H_PAD ),
89 mFixedWidth( 16 ),
90 mFixedHeight( 16 ),
91 mHoverGlowStrength(0.15f), 87 mHoverGlowStrength(0.15f),
92 mCurGlowStrength(0.f), 88 mCurGlowStrength(0.f),
93 mNeedsHighlight(FALSE), 89 mNeedsHighlight(FALSE),
@@ -134,6 +130,7 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
134 mImageDisabled( NULL ), 130 mImageDisabled( NULL ),
135 mImageDisabledSelected( NULL ), 131 mImageDisabledSelected( NULL ),
136 mToggleState( FALSE ), 132 mToggleState( FALSE ),
133 mIsToggle( FALSE ),
137 mScaleImage( TRUE ), 134 mScaleImage( TRUE ),
138 mDropShadowedText( TRUE ), 135 mDropShadowedText( TRUE ),
139 mBorderEnabled( FALSE ), 136 mBorderEnabled( FALSE ),
@@ -141,8 +138,6 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
141 mHAlign( LLFontGL::HCENTER ), 138 mHAlign( LLFontGL::HCENTER ),
142 mLeftHPad( LLBUTTON_H_PAD ), 139 mLeftHPad( LLBUTTON_H_PAD ),
143 mRightHPad( LLBUTTON_H_PAD ), 140 mRightHPad( LLBUTTON_H_PAD ),
144 mFixedWidth( 16 ),
145 mFixedHeight( 16 ),
146 mHoverGlowStrength(0.25f), 141 mHoverGlowStrength(0.25f),
147 mCurGlowStrength(0.f), 142 mCurGlowStrength(0.f),
148 mNeedsHighlight(FALSE), 143 mNeedsHighlight(FALSE),
@@ -158,15 +153,11 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
158 153
159 if( unselected_image_name != "" ) 154 if( unselected_image_name != "" )
160 { 155 {
156 // user-specified image - don't use fixed borders unless requested
161 setImageUnselected(unselected_image_name); 157 setImageUnselected(unselected_image_name);
162 setImageDisabled(unselected_image_name); 158 setImageDisabled(unselected_image_name);
163 159
164 mDisabledImageColor.mV[VALPHA] = 0.5f; 160 mDisabledImageColor.mV[VALPHA] = 0.5f;
165 mImageDisabled = mImageUnselected;
166 mDisabledImageColor.mV[VALPHA] = 0.5f;
167 // user-specified image - don't use fixed borders unless requested
168 mFixedWidth = 0;
169 mFixedHeight = 0;
170 mScaleImage = FALSE; 161 mScaleImage = FALSE;
171 } 162 }
172 else 163 else
@@ -177,13 +168,11 @@ LLButton::LLButton(const LLString& name, const LLRect& rect,
177 168
178 if( selected_image_name != "" ) 169 if( selected_image_name != "" )
179 { 170 {
171 // user-specified image - don't use fixed borders unless requested
180 setImageSelected(selected_image_name); 172 setImageSelected(selected_image_name);
181 setImageDisabledSelected(selected_image_name); 173 setImageDisabledSelected(selected_image_name);
182 174
183 mDisabledImageColor.mV[VALPHA] = 0.5f; 175 mDisabledImageColor.mV[VALPHA] = 0.5f;
184 // user-specified image - don't use fixed borders unless requested
185 mFixedWidth = 0;
186 mFixedHeight = 0;
187 mScaleImage = FALSE; 176 mScaleImage = FALSE;
188 } 177 }
189 else 178 else
@@ -273,6 +262,12 @@ void LLButton::onCommit()
273 make_ui_sound("UISndClickRelease"); 262 make_ui_sound("UISndClickRelease");
274 } 263 }
275 264
265 if (mIsToggle)
266 {
267 toggleState();
268 }
269
270 // do this last, as it can result in destroying this button
276 if (mClickedCallback) 271 if (mClickedCallback)
277 { 272 {
278 (*mClickedCallback)( mCallbackUserData ); 273 (*mClickedCallback)( mCallbackUserData );
@@ -286,6 +281,11 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
286 BOOL handled = FALSE; 281 BOOL handled = FALSE;
287 if( getVisible() && mEnabled && !called_from_parent && ' ' == uni_char && !gKeyboard->getKeyRepeated(' ')) 282 if( getVisible() && mEnabled && !called_from_parent && ' ' == uni_char && !gKeyboard->getKeyRepeated(' '))
288 { 283 {
284 if (mIsToggle)
285 {
286 toggleState();
287 }
288
289 if (mClickedCallback) 289 if (mClickedCallback)
290 { 290 {
291 (*mClickedCallback)( mCallbackUserData ); 291 (*mClickedCallback)( mCallbackUserData );
@@ -302,11 +302,17 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
302 { 302 {
303 if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) 303 if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
304 { 304 {
305 if (mIsToggle)
306 {
307 toggleState();
308 }
309
310 handled = TRUE;
311
305 if (mClickedCallback) 312 if (mClickedCallback)
306 { 313 {
307 (*mClickedCallback)( mCallbackUserData ); 314 (*mClickedCallback)( mCallbackUserData );
308 } 315 }
309 handled = TRUE;
310 } 316 }
311 } 317 }
312 return handled; 318 return handled;
@@ -354,6 +360,9 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
354 (*mMouseUpCallback)(mCallbackUserData); 360 (*mMouseUpCallback)(mCallbackUserData);
355 } 361 }
356 362
363 mMouseDownTimer.stop();
364 mMouseDownTimer.reset();
365
357 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. 366 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
358 // If mouseup in the widget, it's been clicked 367 // If mouseup in the widget, it's been clicked
359 if (pointInView(x, y)) 368 if (pointInView(x, y))
@@ -363,6 +372,11 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
363 make_ui_sound("UISndClickRelease"); 372 make_ui_sound("UISndClickRelease");
364 } 373 }
365 374
375 if (mIsToggle)
376 {
377 toggleState();
378 }
379
366 if (mClickedCallback) 380 if (mClickedCallback)
367 { 381 {
368 (*mClickedCallback)( mCallbackUserData ); 382 (*mClickedCallback)( mCallbackUserData );
@@ -422,8 +436,10 @@ void LLButton::draw()
422 BOOL flash = FALSE; 436 BOOL flash = FALSE;
423 if( mFlashing ) 437 if( mFlashing )
424 { 438 {
425 F32 elapsed = LLButton::sFlashingTimer.getElapsedTimeF32(); 439 F32 elapsed = mFlashingTimer.getElapsedTimeF32();
426 flash = S32(elapsed * 2) & 1; 440 S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f);
441 // flash on or off?
442 flash = (flash_count % 2 == 0) || flash_count > (F32)LLUI::sConfigGroup->getS32("ButtonFlashCount");
427 } 443 }
428 444
429 BOOL pressed_by_keyboard = FALSE; 445 BOOL pressed_by_keyboard = FALSE;
@@ -443,24 +459,14 @@ void LLButton::draw()
443 cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); 459 cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
444 screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); 460 screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
445 461
446 BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)); 462 BOOL pressed = pressed_by_keyboard
447 463 || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
448 BOOL display_state = FALSE; 464 || mToggleState;
449 if( pressed )
450 {
451 mImagep = mImageSelected;
452 // show the resulting state after releasing the mouse button while it is down
453 display_state = mToggleState ? FALSE : TRUE;
454 }
455 else
456 {
457 display_state = mToggleState || flash;
458 }
459 465
460 BOOL use_glow_effect = FALSE; 466 BOOL use_glow_effect = FALSE;
461 if ( mNeedsHighlight ) 467 if ( mNeedsHighlight || flash )
462 { 468 {
463 if (display_state) 469 if (pressed)
464 { 470 {
465 if (mImageHoverSelected) 471 if (mImageHoverSelected)
466 { 472 {
@@ -485,7 +491,7 @@ void LLButton::draw()
485 } 491 }
486 } 492 }
487 } 493 }
488 else if ( display_state ) 494 else if ( pressed )
489 { 495 {
490 mImagep = mImageSelected; 496 mImagep = mImageSelected;
491 } 497 }
@@ -499,11 +505,11 @@ void LLButton::draw()
499 // enabled and tentative 505 // enabled and tentative
500 // or 506 // or
501 // disabled but checked 507 // disabled but checked
502 if (!mImageDisabledSelected.isNull() && ( (mEnabled && mTentative) || (!mEnabled && display_state ) ) ) 508 if (!mImageDisabledSelected.isNull() && ( (mEnabled && mTentative) || (!mEnabled && pressed ) ) )
503 { 509 {
504 mImagep = mImageDisabledSelected; 510 mImagep = mImageDisabledSelected;
505 } 511 }
506 else if (!mImageDisabled.isNull() && !mEnabled && !display_state) 512 else if (!mImageDisabled.isNull() && !mEnabled && !pressed)
507 { 513 {
508 mImagep = mImageDisabled; 514 mImagep = mImageDisabled;
509 } 515 }
@@ -516,33 +522,34 @@ void LLButton::draw()
516 // Figure out appropriate color for the text 522 // Figure out appropriate color for the text
517 LLColor4 label_color; 523 LLColor4 label_color;
518 524
525 // label changes when button state changes, not when pressed
519 if ( mEnabled ) 526 if ( mEnabled )
520 { 527 {
521 if ( !display_state ) 528 if ( mToggleState )
522 { 529 {
523 label_color = mUnselectedLabelColor; 530 label_color = mSelectedLabelColor;
524 } 531 }
525 else 532 else
526 { 533 {
527 label_color = mSelectedLabelColor; 534 label_color = mUnselectedLabelColor;
528 } 535 }
529 } 536 }
530 else 537 else
531 { 538 {
532 if ( !display_state ) 539 if ( mToggleState )
533 { 540 {
534 label_color = mDisabledLabelColor; 541 label_color = mDisabledSelectedLabelColor;
535 } 542 }
536 else 543 else
537 { 544 {
538 label_color = mDisabledSelectedLabelColor; 545 label_color = mDisabledLabelColor;
539 } 546 }
540 } 547 }
541 548
542 // Unselected label assignments 549 // Unselected label assignments
543 LLWString label; 550 LLWString label;
544 551
545 if( display_state ) 552 if( mToggleState )
546 { 553 {
547 if( mEnabled || mDisabledSelectedLabel.empty() ) 554 if( mEnabled || mDisabledSelectedLabel.empty() )
548 { 555 {
@@ -591,24 +598,22 @@ void LLButton::draw()
591 // Otherwise draw basic rectangular button. 598 // Otherwise draw basic rectangular button.
592 if( mImagep.notNull() && !mScaleImage) 599 if( mImagep.notNull() && !mScaleImage)
593 { 600 {
594 gl_draw_image( 0, 0, mImagep, mEnabled ? mImageColor : mDisabledImageColor ); 601 mImagep->draw(0, 0, mEnabled ? mImageColor : mDisabledImageColor );
595 if (mCurGlowStrength > 0.01f) 602 if (mCurGlowStrength > 0.01f)
596 { 603 {
597 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 604 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
598 gl_draw_scaled_image_with_border(0, 0, 0, 0, mImagep->getWidth(), mImagep->getHeight(), mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE); 605 mImagep->drawSolid(0, 0, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
599 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 606 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
600 } 607 }
601 } 608 }
602 else 609 else
603 if ( mImagep.notNull() && mScaleImage) 610 if ( mImagep.notNull() && mScaleImage)
604 { 611 {
605 gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(), 612 mImagep->draw(0, 0, mRect.getWidth(), mRect.getHeight(), mEnabled ? mImageColor : mDisabledImageColor );
606 mImagep, mEnabled ? mImageColor : mDisabledImageColor );
607 if (mCurGlowStrength > 0.01f) 613 if (mCurGlowStrength > 0.01f)
608 { 614 {
609 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 615 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
610 gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(), 616 mImagep->drawSolid(0, 0, mRect.getWidth(), mRect.getHeight(), LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
611 mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE);
612 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 617 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
613 } 618 }
614 } 619 }
@@ -620,13 +625,17 @@ void LLButton::draw()
620 gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE); 625 gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE);
621 } 626 }
622 627
628 // let overlay image and text play well together
629 S32 text_left = mLeftHPad;
630 S32 text_right = mRect.getWidth() - mRightHPad;
631 S32 text_width = mRect.getWidth() - mLeftHPad - mRightHPad;
632
623 // draw overlay image 633 // draw overlay image
624 if (mImageOverlay.notNull()) 634 if (mImageOverlay.notNull())
625 { 635 {
626 const S32 IMG_PAD = 5;
627 // get max width and height (discard level 0) 636 // get max width and height (discard level 0)
628 S32 overlay_width = mImageOverlay->getWidth(0); 637 S32 overlay_width = mImageOverlay->getWidth();
629 S32 overlay_height = mImageOverlay->getHeight(0); 638 S32 overlay_height = mImageOverlay->getHeight();
630 639
631 F32 scale_factor = llmin((F32)mRect.getWidth() / (F32)overlay_width, (F32)mRect.getHeight() / (F32)overlay_height, 1.f); 640 F32 scale_factor = llmin((F32)mRect.getWidth() / (F32)overlay_width, (F32)mRect.getHeight() / (F32)overlay_height, 1.f);
632 overlay_width = llround((F32)overlay_width * scale_factor); 641 overlay_width = llround((F32)overlay_width * scale_factor);
@@ -635,34 +644,49 @@ void LLButton::draw()
635 S32 center_x = getLocalRect().getCenterX(); 644 S32 center_x = getLocalRect().getCenterX();
636 S32 center_y = getLocalRect().getCenterY(); 645 S32 center_y = getLocalRect().getCenterY();
637 646
647 //FUGLY HACK FOR "DEPRESSED" BUTTONS
648 if (pressed)
649 {
650 center_y--;
651 center_x++;
652 }
653
654 // fade out overlay images on disabled buttons
655 LLColor4 overlay_color = mImageOverlayColor;
656 if (!getEnabled())
657 {
658 overlay_color.mV[VALPHA] = 0.5f;
659 }
660
638 switch(mImageOverlayAlignment) 661 switch(mImageOverlayAlignment)
639 { 662 {
640 case LLFontGL::LEFT: 663 case LLFontGL::LEFT:
641 gl_draw_scaled_image( 664 text_left += overlay_width + 1;
642 IMG_PAD, 665 text_width -= overlay_width + 1;
666 mImageOverlay->draw(
667 mLeftHPad,
643 center_y - (overlay_height / 2), 668 center_y - (overlay_height / 2),
644 overlay_width, 669 overlay_width,
645 overlay_height, 670 overlay_height,
646 mImageOverlay, 671 overlay_color);
647 mImageOverlayColor);
648 break; 672 break;
649 case LLFontGL::HCENTER: 673 case LLFontGL::HCENTER:
650 gl_draw_scaled_image( 674 mImageOverlay->draw(
651 center_x - (overlay_width / 2), 675 center_x - (overlay_width / 2),
652 center_y - (overlay_height / 2), 676 center_y - (overlay_height / 2),
653 overlay_width, 677 overlay_width,
654 overlay_height, 678 overlay_height,
655 mImageOverlay, 679 overlay_color);
656 mImageOverlayColor);
657 break; 680 break;
658 case LLFontGL::RIGHT: 681 case LLFontGL::RIGHT:
659 gl_draw_scaled_image( 682 text_right -= overlay_width + 1;
660 mRect.getWidth() - IMG_PAD - overlay_width, 683 text_width -= overlay_width + 1;
684 mImageOverlay->draw(
685 mRect.getWidth() - mRightHPad - overlay_width,
661 center_y - (overlay_height / 2), 686 center_y - (overlay_height / 2),
662 overlay_width, 687 overlay_width,
663 overlay_height, 688 overlay_height,
664 mImageOverlay, 689 overlay_color);
665 mImageOverlayColor);
666 break; 690 break;
667 default: 691 default:
668 // draw nothing 692 // draw nothing
@@ -673,28 +697,26 @@ void LLButton::draw()
673 // Draw label 697 // Draw label
674 if( !label.empty() ) 698 if( !label.empty() )
675 { 699 {
676 S32 drawable_width = mRect.getWidth() - mLeftHPad - mRightHPad;
677
678 LLWString::trim(label); 700 LLWString::trim(label);
679 701
680 S32 x; 702 S32 x;
681 switch( mHAlign ) 703 switch( mHAlign )
682 { 704 {
683 case LLFontGL::RIGHT: 705 case LLFontGL::RIGHT:
684 x = mRect.getWidth() - mRightHPad; 706 x = text_right;
685 break; 707 break;
686 case LLFontGL::HCENTER: 708 case LLFontGL::HCENTER:
687 x = mRect.getWidth() / 2; 709 x = mRect.getWidth() / 2;
688 break; 710 break;
689 case LLFontGL::LEFT: 711 case LLFontGL::LEFT:
690 default: 712 default:
691 x = mLeftHPad; 713 x = text_left;
692 break; 714 break;
693 } 715 }
694 716
695 S32 y_offset = 2 + (mRect.getHeight() - 20)/2; 717 S32 y_offset = 2 + (mRect.getHeight() - 20)/2;
696 718
697 if (pressed || display_state) 719 if (pressed)
698 { 720 {
699 y_offset--; 721 y_offset--;
700 x++; 722 x++;
@@ -704,7 +726,7 @@ void LLButton::draw()
704 label_color, 726 label_color,
705 mHAlign, LLFontGL::BOTTOM, 727 mHAlign, LLFontGL::BOTTOM,
706 mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL, 728 mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL,
707 U32_MAX, drawable_width, 729 U32_MAX, text_width,
708 NULL, FALSE, FALSE); 730 NULL, FALSE, FALSE);
709 } 731 }
710 732
@@ -733,13 +755,11 @@ void LLButton::drawBorder(const LLColor4& color, S32 size)
733 755
734 if (mScaleImage) 756 if (mScaleImage)
735 { 757 {
736 gl_draw_scaled_image_with_border(left, bottom, mFixedWidth, mFixedHeight, right-left, top-bottom, 758 mImagep->drawSolid(left, bottom, right-left, top-bottom, color);
737 mImagep, color, TRUE );
738 } 759 }
739 else 760 else
740 { 761 {
741 gl_draw_scaled_image_with_border(left, bottom, 0, 0, mImagep->getWidth() + size * 2, 762 mImagep->drawSolid(left, bottom, mImagep->getWidth() + size * 2, mImagep->getHeight() + size * 2, color);
742 mImagep->getHeight() + size * 2, mImagep, color, TRUE );
743 } 763 }
744} 764}
745 765
@@ -763,6 +783,22 @@ void LLButton::setToggleState(BOOL b)
763 } 783 }
764} 784}
765 785
786void LLButton::setFlashing( BOOL b )
787{
788 if (b != mFlashing)
789 {
790 mFlashing = b;
791 mFlashingTimer.reset();
792 }
793}
794
795
796BOOL LLButton::toggleState()
797{
798 setToggleState( !mToggleState );
799 return mToggleState;
800}
801
766void LLButton::setValue(const LLSD& value ) 802void LLButton::setValue(const LLSD& value )
767{ 803{
768 mToggleState = value.asBoolean(); 804 mToggleState = value.asBoolean();
@@ -770,7 +806,7 @@ void LLButton::setValue(const LLSD& value )
770 806
771LLSD LLButton::getValue() const 807LLSD LLButton::getValue() const
772{ 808{
773 return mToggleState; 809 return mToggleState == TRUE;
774} 810}
775 811
776void LLButton::setLabel( const LLStringExplicit& label ) 812void LLButton::setLabel( const LLStringExplicit& label )
@@ -807,10 +843,9 @@ void LLButton::setDisabledSelectedLabel( const LLStringExplicit& label )
807 mDisabledSelectedLabel = label; 843 mDisabledSelectedLabel = label;
808} 844}
809 845
810void LLButton::setImageUnselectedID( const LLUUID &image_id ) 846void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
811{ 847{
812 mImageUnselectedName = ""; 848 mImageUnselected = image;
813 mImageUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
814} 849}
815 850
816void LLButton::setImages( const LLString &image_name, const LLString &selected_name ) 851void LLButton::setImages( const LLString &image_name, const LLString &selected_name )
@@ -820,10 +855,9 @@ void LLButton::setImages( const LLString &image_name, const LLString &selected_n
820 855
821} 856}
822 857
823void LLButton::setImageSelectedID( const LLUUID &image_id ) 858void LLButton::setImageSelected(LLPointer<LLUIImage> image)
824{ 859{
825 mImageSelectedName = ""; 860 mImageSelected = image;
826 mImageSelected = LLUI::sImageProvider->getUIImageByID(image_id);
827} 861}
828 862
829void LLButton::setImageColor(const LLColor4& c) 863void LLButton::setImageColor(const LLColor4& c)
@@ -831,19 +865,22 @@ void LLButton::setImageColor(const LLColor4& c)
831 mImageColor = c; 865 mImageColor = c;
832} 866}
833 867
868void LLButton::setColor(const LLColor4& color)
869{
870 setImageColor(color);
871}
872
834 873
835void LLButton::setImageDisabledID( const LLUUID &image_id ) 874void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
836{ 875{
837 mImageDisabledName = ""; 876 mImageDisabled = image;
838 mImageDisabled = LLUI::sImageProvider->getUIImageByID(image_id);
839 mDisabledImageColor = mImageColor; 877 mDisabledImageColor = mImageColor;
840 mDisabledImageColor.mV[VALPHA] *= 0.5f; 878 mDisabledImageColor.mV[VALPHA] *= 0.5f;
841} 879}
842 880
843void LLButton::setImageDisabledSelectedID( const LLUUID &image_id ) 881void LLButton::setImageDisabledSelected(LLPointer<LLUIImage> image)
844{ 882{
845 mImageDisabledSelectedName = ""; 883 mImageDisabledSelected = image;
846 mImageDisabledSelected = LLUI::sImageProvider->getUIImageByID(image_id);
847 mDisabledImageColor = mImageColor; 884 mDisabledImageColor = mImageColor;
848 mDisabledImageColor.mV[VALPHA] *= 0.5f; 885 mDisabledImageColor.mV[VALPHA] *= 0.5f;
849} 886}
@@ -855,11 +892,9 @@ void LLButton::setDisabledImages( const LLString &image_name, const LLString &se
855 mDisabledImageColor = c; 892 mDisabledImageColor = c;
856} 893}
857 894
858 895void LLButton::setImageHoverSelected(LLPointer<LLUIImage> image)
859void LLButton::setImageHoverSelectedID( const LLUUID& image_id )
860{ 896{
861 mImageHoverSelectedName = ""; 897 mImageHoverSelected = image;
862 mImageHoverSelected = LLUI::sImageProvider->getUIImageByID(image_id);
863} 898}
864 899
865void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name) 900void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name)
@@ -869,10 +904,9 @@ void LLButton::setDisabledImages( const LLString &image_name, const LLString &se
869 setDisabledImages( image_name, selected_name, clr ); 904 setDisabledImages( image_name, selected_name, clr );
870} 905}
871 906
872void LLButton::setImageHoverUnselectedID( const LLUUID& image_id ) 907void LLButton::setImageHoverUnselected(LLPointer<LLUIImage> image)
873{ 908{
874 mImageHoverUnselectedName = ""; 909 mImageHoverUnselected = image;
875 mImageHoverUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
876} 910}
877 911
878void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name ) 912void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name )
@@ -889,8 +923,7 @@ void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alig
889 } 923 }
890 else 924 else
891 { 925 {
892 LLUUID overlay_image_id = LLUI::findAssetUUIDByName(image_name); 926 mImageOverlay = LLUI::getUIImageByName(image_name);
893 mImageOverlay = LLUI::sImageProvider->getUIImageByID(overlay_image_id);
894 mImageOverlayAlignment = alignment; 927 mImageOverlayAlignment = alignment;
895 mImageOverlayColor = color; 928 mImageOverlayColor = color;
896 } 929 }
@@ -904,34 +937,6 @@ void LLButton::onMouseCaptureLost()
904} 937}
905 938
906//------------------------------------------------------------------------- 939//-------------------------------------------------------------------------
907// LLSquareButton
908//-------------------------------------------------------------------------
909LLSquareButton::LLSquareButton(const LLString& name, const LLRect& rect,
910 const LLString& label,
911 const LLFontGL *font,
912 const LLString& control_name,
913 void (*click_callback)(void*),
914 void *callback_data,
915 const LLString& selected_label )
916: LLButton(name, rect, "","",
917 control_name,
918 click_callback, callback_data,
919 font,
920 label,
921 (selected_label.empty() ? label : selected_label) )
922{
923 setImageUnselected("square_btn_32x128.tga");
924 // mImageUnselected = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga")));
925 setImageSelected("square_btn_selected_32x128.tga");
926 // mImageSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga")));
927 setImageDisabled("square_btn_32x128.tga");
928 //mDisabledImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga")));
929 setImageDisabledSelected("square_btn_selected_32x128.tga");
930 //mDisabledSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga")));
931 mImageColor = LLUI::sColorsGroup->getColor("ButtonColor");
932}
933
934//-------------------------------------------------------------------------
935// Utilities 940// Utilities
936//------------------------------------------------------------------------- 941//-------------------------------------------------------------------------
937S32 round_up(S32 grid, S32 value) 942S32 round_up(S32 grid, S32 value)
@@ -951,37 +956,37 @@ S32 round_up(S32 grid, S32 value)
951 956
952void LLButton::setImageUnselected(const LLString &image_name) 957void LLButton::setImageUnselected(const LLString &image_name)
953{ 958{
954 setImageUnselectedID(LLUI::findAssetUUIDByName(image_name)); 959 setImageUnselected(LLUI::getUIImageByName(image_name));
955 mImageUnselectedName = image_name; 960 mImageUnselectedName = image_name;
956} 961}
957 962
958void LLButton::setImageSelected(const LLString &image_name) 963void LLButton::setImageSelected(const LLString &image_name)
959{ 964{
960 setImageSelectedID(LLUI::findAssetUUIDByName(image_name)); 965 setImageSelected(LLUI::getUIImageByName(image_name));
961 mImageSelectedName = image_name; 966 mImageSelectedName = image_name;
962} 967}
963 968
964void LLButton::setImageHoverSelected(const LLString &image_name) 969void LLButton::setImageHoverSelected(const LLString &image_name)
965{ 970{
966 setImageHoverSelectedID(LLUI::findAssetUUIDByName(image_name)); 971 setImageHoverSelected(LLUI::getUIImageByName(image_name));
967 mImageHoverSelectedName = image_name; 972 mImageHoverSelectedName = image_name;
968} 973}
969 974
970void LLButton::setImageHoverUnselected(const LLString &image_name) 975void LLButton::setImageHoverUnselected(const LLString &image_name)
971{ 976{
972 setImageHoverUnselectedID(LLUI::findAssetUUIDByName(image_name)); 977 setImageHoverUnselected(LLUI::getUIImageByName(image_name));
973 mImageHoverUnselectedName = image_name; 978 mImageHoverUnselectedName = image_name;
974} 979}
975 980
976void LLButton::setImageDisabled(const LLString &image_name) 981void LLButton::setImageDisabled(const LLString &image_name)
977{ 982{
978 setImageDisabledID(LLUI::findAssetUUIDByName(image_name)); 983 setImageDisabled(LLUI::getUIImageByName(image_name));
979 mImageDisabledName = image_name; 984 mImageDisabledName = image_name;
980} 985}
981 986
982void LLButton::setImageDisabledSelected(const LLString &image_name) 987void LLButton::setImageDisabledSelected(const LLString &image_name)
983{ 988{
984 setImageDisabledSelectedID(LLUI::findAssetUUIDByName(image_name)); 989 setImageDisabledSelected(LLUI::getUIImageByName(image_name));
985 mImageDisabledSelectedName = image_name; 990 mImageDisabledSelectedName = image_name;
986} 991}
987 992
@@ -1009,8 +1014,6 @@ LLXMLNodePtr LLButton::getXML(bool save_children) const
1009 node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected()); 1014 node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected());
1010 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); 1015 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
1011 node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign)); 1016 node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
1012 node->createChild("border_width", TRUE)->setIntValue(mFixedWidth);
1013 node->createChild("border_height", TRUE)->setIntValue(mFixedHeight);
1014 1017
1015 addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected"); 1018 addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected");
1016 addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected"); 1019 addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected");
@@ -1092,8 +1095,12 @@ LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
1092 label, 1095 label,
1093 label_selected); 1096 label_selected);
1094 1097
1095 node->getAttributeS32("border_width", button->mFixedWidth); 1098 node->getAttributeS32("pad_right", button->mRightHPad);
1096 node->getAttributeS32("border_height", button->mFixedHeight); 1099 node->getAttributeS32("pad_left", button->mLeftHPad);
1100
1101 BOOL is_toggle = button->getIsToggle();
1102 node->getAttributeBOOL("toggle", is_toggle);
1103 button->setIsToggle(is_toggle);
1097 1104
1098 if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected); 1105 if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected);
1099 1106
diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h
index 6a2b4a1..7d50f40 100644
--- a/linden/indra/llui/llbutton.h
+++ b/linden/indra/llui/llbutton.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -114,11 +114,13 @@ public:
114 114
115 F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } 115 F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); }
116 116
117 BOOL toggleState() { setToggleState( !mToggleState ); return mToggleState; } 117 BOOL getIsToggle() const { return mIsToggle; }
118 void setIsToggle(BOOL is_toggle) { mIsToggle = is_toggle; }
119 BOOL toggleState();
118 BOOL getToggleState() const { return mToggleState; } 120 BOOL getToggleState() const { return mToggleState; }
119 void setToggleState(BOOL b); 121 void setToggleState(BOOL b);
120 122
121 void setFlashing( BOOL b ) { mFlashing = b; } 123 void setFlashing( BOOL b );
122 BOOL getFlashing() const { return mFlashing; } 124 BOOL getFlashing() const { return mFlashing; }
123 125
124 void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } 126 void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
@@ -128,14 +130,11 @@ public:
128 const LLString getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); } 130 const LLString getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); }
129 const LLString getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); } 131 const LLString getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); }
130 132
131
132 // HACK to allow images to be freed when the caller knows he's done with it.
133 LLImageGL* getImageUnselected() const { return mImageUnselected; }
134
135 void setImageColor(const LLString& color_control); 133 void setImageColor(const LLString& color_control);
136 void setImages(const LLString &image_name, const LLString &selected_name);
137 void setImageColor(const LLColor4& c); 134 void setImageColor(const LLColor4& c);
138 135 virtual void setColor(const LLColor4& c);
136
137 void setImages(const LLString &image_name, const LLString &selected_name);
139 void setDisabledImages(const LLString &image_name, const LLString &selected_name); 138 void setDisabledImages(const LLString &image_name, const LLString &selected_name);
140 void setDisabledImages(const LLString &image_name, const LLString &selected_name, const LLColor4& c); 139 void setDisabledImages(const LLString &image_name, const LLString &selected_name, const LLColor4& c);
141 140
@@ -146,7 +145,7 @@ public:
146 void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; } 145 void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; }
147 146
148 void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); 147 void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
149 LLPointer<LLImageGL> getImageOverlay() { return mImageOverlay; } 148 LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }
150 149
151 150
152 virtual void setValue(const LLSD& value ); 151 virtual void setValue(const LLSD& value );
@@ -170,16 +169,8 @@ public:
170 169
171 static void onHeldDown(void *userdata); // to be called by gIdleCallbacks 170 static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
172 171
173 void setFixedBorder(S32 width, S32 height) { mFixedWidth = width; mFixedHeight = height; }
174 void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } 172 void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; }
175 173
176private:
177 void setImageUnselectedID(const LLUUID &image_id);
178 void setImageSelectedID(const LLUUID &image_id);
179 void setImageHoverSelectedID(const LLUUID &image_id);
180 void setImageHoverUnselectedID(const LLUUID &image_id);
181 void setImageDisabledID(const LLUUID &image_id);
182 void setImageDisabledSelectedID(const LLUUID &image_id);
183public: 174public:
184 void setImageUnselected(const LLString &image_name); 175 void setImageUnselected(const LLString &image_name);
185 void setImageSelected(const LLString &image_name); 176 void setImageSelected(const LLString &image_name);
@@ -187,6 +178,14 @@ public:
187 void setImageHoverUnselected(const LLString &image_name); 178 void setImageHoverUnselected(const LLString &image_name);
188 void setImageDisabled(const LLString &image_name); 179 void setImageDisabled(const LLString &image_name);
189 void setImageDisabledSelected(const LLString &image_name); 180 void setImageDisabledSelected(const LLString &image_name);
181
182 void setImageUnselected(LLPointer<LLUIImage> image);
183 void setImageSelected(LLPointer<LLUIImage> image);
184 void setImageHoverSelected(LLPointer<LLUIImage> image);
185 void setImageHoverUnselected(LLPointer<LLUIImage> image);
186 void setImageDisabled(LLPointer<LLUIImage> image);
187 void setImageDisabledSelected(LLPointer<LLUIImage> image);
188
190 void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } 189 void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
191 BOOL getCommitOnReturn() { return mCommitOnReturn; } 190 BOOL getCommitOnReturn() { return mCommitOnReturn; }
192 191
@@ -209,27 +208,27 @@ protected:
209 F32 mHeldDownDelay; // seconds, after which held-down callbacks get called 208 F32 mHeldDownDelay; // seconds, after which held-down callbacks get called
210 S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called 209 S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called
211 210
212 LLPointer<LLImageGL> mImageOverlay; 211 LLPointer<LLUIImage> mImageOverlay;
213 LLFontGL::HAlign mImageOverlayAlignment; 212 LLFontGL::HAlign mImageOverlayAlignment;
214 LLColor4 mImageOverlayColor; 213 LLColor4 mImageOverlayColor;
215 214
216 LLPointer<LLImageGL> mImageUnselected; 215 LLPointer<LLUIImage> mImageUnselected;
217 LLUIString mUnselectedLabel; 216 LLUIString mUnselectedLabel;
218 LLColor4 mUnselectedLabelColor; 217 LLColor4 mUnselectedLabelColor;
219 218
220 LLPointer<LLImageGL> mImageSelected; 219 LLPointer<LLUIImage> mImageSelected;
221 LLUIString mSelectedLabel; 220 LLUIString mSelectedLabel;
222 LLColor4 mSelectedLabelColor; 221 LLColor4 mSelectedLabelColor;
223 222
224 LLPointer<LLImageGL> mImageHoverSelected; 223 LLPointer<LLUIImage> mImageHoverSelected;
225 224
226 LLPointer<LLImageGL> mImageHoverUnselected; 225 LLPointer<LLUIImage> mImageHoverUnselected;
227 226
228 LLPointer<LLImageGL> mImageDisabled; 227 LLPointer<LLUIImage> mImageDisabled;
229 LLUIString mDisabledLabel; 228 LLUIString mDisabledLabel;
230 LLColor4 mDisabledLabelColor; 229 LLColor4 mDisabledLabelColor;
231 230
232 LLPointer<LLImageGL> mImageDisabledSelected; 231 LLPointer<LLUIImage> mImageDisabledSelected;
233 LLUIString mDisabledSelectedLabel; 232 LLUIString mDisabledSelectedLabel;
234 LLColor4 mDisabledSelectedLabelColor; 233 LLColor4 mDisabledSelectedLabelColor;
235 234
@@ -254,6 +253,7 @@ protected:
254 LLColor4 mImageColor; 253 LLColor4 mImageColor;
255 LLColor4 mDisabledImageColor; 254 LLColor4 mDisabledImageColor;
256 255
256 BOOL mIsToggle;
257 BOOL mToggleState; 257 BOOL mToggleState;
258 BOOL mScaleImage; 258 BOOL mScaleImage;
259 259
@@ -267,9 +267,6 @@ protected:
267 S32 mLeftHPad; 267 S32 mLeftHPad;
268 S32 mRightHPad; 268 S32 mRightHPad;
269 269
270 S32 mFixedWidth;
271 S32 mFixedHeight;
272
273 F32 mHoverGlowStrength; 270 F32 mHoverGlowStrength;
274 F32 mCurGlowStrength; 271 F32 mCurGlowStrength;
275 272
@@ -278,22 +275,9 @@ protected:
278 275
279 LLString mHelpURL; 276 LLString mHelpURL;
280 277
281 LLPointer<LLImageGL> mImagep; 278 LLPointer<LLUIImage> mImagep;
282
283 static LLFrameTimer sFlashingTimer;
284};
285 279
286class LLSquareButton 280 LLFrameTimer mFlashingTimer;
287: public LLButton
288{
289public:
290 LLSquareButton(const LLString& name, const LLRect& rect,
291 const LLString& label,
292 const LLFontGL *font = NULL,
293 const LLString& control_name = LLString(),
294 void (*click_callback)(void*) = NULL,
295 void *callback_data = NULL,
296 const LLString& selected_label = LLString::null );
297}; 281};
298 282
299// Helpful functions 283// Helpful functions
diff --git a/linden/indra/llui/llcallbackmap.h b/linden/indra/llui/llcallbackmap.h
index 6b40f09..9241751 100644
--- a/linden/indra/llui/llcallbackmap.h
+++ b/linden/indra/llui/llcallbackmap.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llcheckboxctrl.cpp b/linden/indra/llui/llcheckboxctrl.cpp
index b184eda..ff46a80 100644
--- a/linden/indra/llui/llcheckboxctrl.cpp
+++ b/linden/indra/llui/llcheckboxctrl.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -75,7 +75,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLString& name, const LLRect& rect,
75 } 75 }
76 76
77 // must be big enough to hold all children 77 // must be big enough to hold all children
78 setSpanChildren(TRUE); 78 setUseBoundingRect(TRUE);
79 79
80 mKeyboardFocusOnClick = TRUE; 80 mKeyboardFocusOnClick = TRUE;
81 81
@@ -130,6 +130,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLString& name, const LLRect& rect,
130 mButton->setDisabledImages( inactive_false_id, inactive_true_id ); 130 mButton->setDisabledImages( inactive_false_id, inactive_true_id );
131 mButton->setHoverGlowStrength(0.35f); 131 mButton->setHoverGlowStrength(0.35f);
132 } 132 }
133 mButton->setIsToggle(TRUE);
133 mButton->setToggleState( initial_value ); 134 mButton->setToggleState( initial_value );
134 mButton->setFollowsLeft(); 135 mButton->setFollowsLeft();
135 mButton->setFollowsBottom(); 136 mButton->setFollowsBottom();
@@ -150,16 +151,11 @@ void LLCheckBoxCtrl::onButtonPress( void *userdata )
150 151
151 if (self->mRadioStyle) 152 if (self->mRadioStyle)
152 { 153 {
153 if (!self->getValue()) 154 self->setValue(TRUE);
154 {
155 self->setValue(TRUE);
156 }
157 }
158 else
159 {
160 self->toggle();
161 } 155 }
156
162 self->setControlValue(self->getValue()); 157 self->setControlValue(self->getValue());
158 // HACK: because buttons don't normally commit
163 self->onCommit(); 159 self->onCommit();
164 160
165 if (self->mKeyboardFocusOnClick) 161 if (self->mKeyboardFocusOnClick)
@@ -232,14 +228,13 @@ void LLCheckBoxCtrl::draw()
232//virtual 228//virtual
233void LLCheckBoxCtrl::setValue(const LLSD& value ) 229void LLCheckBoxCtrl::setValue(const LLSD& value )
234{ 230{
235 mSetValue = value.asBoolean(); 231 mButton->setValue( value );
236 mButton->setToggleState( mSetValue );
237} 232}
238 233
239//virtual 234//virtual
240LLSD LLCheckBoxCtrl::getValue() const 235LLSD LLCheckBoxCtrl::getValue() const
241{ 236{
242 return mButton->getToggleState(); 237 return mButton->getValue();
243} 238}
244 239
245void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label ) 240void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label )
diff --git a/linden/indra/llui/llcheckboxctrl.h b/linden/indra/llui/llcheckboxctrl.h
index 3fd0be7..1f92708 100644
--- a/linden/indra/llui/llcheckboxctrl.h
+++ b/linden/indra/llui/llcheckboxctrl.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llclipboard.cpp b/linden/indra/llui/llclipboard.cpp
index 774bad6..eaf7798 100644
--- a/linden/indra/llui/llclipboard.cpp
+++ b/linden/indra/llui/llclipboard.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llclipboard.h b/linden/indra/llui/llclipboard.h
index d4efc3a..82ea334 100644
--- a/linden/indra/llui/llclipboard.h
+++ b/linden/indra/llui/llclipboard.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llcombobox.cpp b/linden/indra/llui/llcombobox.cpp
index cfdcf58..22b5033 100644
--- a/linden/indra/llui/llcombobox.cpp
+++ b/linden/indra/llui/llcombobox.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -55,17 +55,16 @@
55// Globals 55// Globals
56S32 LLCOMBOBOX_HEIGHT = 0; 56S32 LLCOMBOBOX_HEIGHT = 0;
57S32 LLCOMBOBOX_WIDTH = 0; 57S32 LLCOMBOBOX_WIDTH = 0;
58 58S32 MAX_COMBO_WIDTH = 500;
59
59LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString& label, 60LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString& label,
60 void (*commit_callback)(LLUICtrl*,void*), 61 void (*commit_callback)(LLUICtrl*,void*),
61 void *callback_userdata 62 void *callback_userdata
62 ) 63 )
63: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata, 64: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata,
64 FOLLOWS_LEFT | FOLLOWS_TOP), 65 FOLLOWS_LEFT | FOLLOWS_TOP),
65 mDrawArrow(TRUE),
66 mTextEntry(NULL), 66 mTextEntry(NULL),
67 mArrowImage(NULL), 67 mArrowImage(NULL),
68 mArrowImageWidth(8),
69 mAllowTextEntry(FALSE), 68 mAllowTextEntry(FALSE),
70 mMaxChars(20), 69 mMaxChars(20),
71 mTextEntryTentative(TRUE), 70 mTextEntryTentative(TRUE),
@@ -73,55 +72,43 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString
73 mPrearrangeCallback( NULL ), 72 mPrearrangeCallback( NULL ),
74 mTextEntryCallback( NULL ) 73 mTextEntryCallback( NULL )
75{ 74{
76 // For now, all comboboxes don't take keyboard focus when clicked.
77 // This might change if it is part of a modal dialog.
78 // mKeyboardFocusOnClick = FALSE;
79
80 // Revert to standard behavior. When this control's parent is hidden, it needs to
81 // hide this ctrl--which won't just happen automatically since when LLComboBox is
82 // showing its list, it's also set to TopCtrl. When keyboard focus is cleared all
83 // controls (including this one) know that they are no longer editing.
84 mKeyboardFocusOnClick = TRUE;
85
86 LLRect r;
87 r.setOriginAndSize(0, 0, rect.getWidth(), rect.getHeight());
88
89 // Always use text box 75 // Always use text box
90 // Text label button 76 // Text label button
91 mButton = new LLSquareButton("comboxbox button", 77 mButton = new LLButton("comboxbox button",
92 r, label, NULL, LLString::null, 78 LLRect(), label, NULL, LLString::null,
93 NULL, this); 79 NULL, this);
80 mButton->setImageUnselected("square_btn_32x128.tga");
81 mButton->setImageSelected("square_btn_selected_32x128.tga");
82 mButton->setImageDisabled("square_btn_32x128.tga");
83 mButton->setImageDisabledSelected("square_btn_selected_32x128.tga");
84 mButton->setScaleImage(TRUE);
85
94 mButton->setMouseDownCallback(onButtonDown); 86 mButton->setMouseDownCallback(onButtonDown);
95 mButton->setFont(LLFontGL::sSansSerifSmall); 87 mButton->setFont(LLFontGL::sSansSerifSmall);
96 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); 88 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
97 mButton->setHAlign( LLFontGL::LEFT ); 89 mButton->setHAlign( LLFontGL::LEFT );
98 90 mButton->setRightHPad(2);
99 const S32 ARROW_WIDTH = 16;
100 mButton->setRightHPad( ARROW_WIDTH );
101 addChild(mButton); 91 addChild(mButton);
102 92
103 // Default size, will be set by arrange() call in button callback.
104 S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE;
105 r.setOriginAndSize(0, 16, list_width, 220);
106
107 // disallow multiple selection 93 // disallow multiple selection
108 mList = new LLScrollListCtrl( 94 mList = new LLScrollListCtrl(
109 "ComboBox", r, 95 "ComboBox", LLRect(),
110 &LLComboBox::onItemSelected, this, FALSE); 96 &LLComboBox::onItemSelected, this, FALSE);
111 mList->setVisible(FALSE); 97 mList->setVisible(FALSE);
112 mList->setBgWriteableColor( LLColor4(1,1,1,1) ); 98 mList->setBgWriteableColor( LLColor4(1,1,1,1) );
113 mList->setCommitOnKeyboardMovement(FALSE); 99 mList->setCommitOnKeyboardMovement(FALSE);
114 mList->setFocusChangedCallback(onListFocusChanged);
115 addChild(mList); 100 addChild(mList);
116 101
117 LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0); 102 LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
118 mBorder = new LLViewBorder( "combo border", border_rect ); 103 mBorder = new LLViewBorder( "combo border", border_rect );
119 addChild( mBorder ); 104 addChild( mBorder );
120 mBorder->setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP|FOLLOWS_BOTTOM); 105 mBorder->setFollowsAll();
121 106
122 LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") ); 107 LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") );
123 mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id); 108 mArrowImage = LLUI::sImageProvider->getImageByID(arrow_image_id);
124 mArrowImageWidth = llmax(8,mArrowImage->getWidth(0)); // In case image hasn't loaded yet 109 mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT);
110
111 updateLayout();
125} 112}
126 113
127 114
@@ -155,7 +142,7 @@ LLXMLNodePtr LLComboBox::getXML(bool save_children) const
155 LLSD value = item->getValue(); 142 LLSD value = item->getValue();
156 item_node->createChild("value", TRUE)->setStringValue(value.asString()); 143 item_node->createChild("value", TRUE)->setStringValue(value.asString());
157 item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled()); 144 item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled());
158 item_node->setStringValue(cell->getText()); 145 item_node->setStringValue(cell->getValue().asString());
159 } 146 }
160 } 147 }
161 148
@@ -272,34 +259,46 @@ void LLComboBox::resetDirty()
272 259
273 260
274// add item "name" to menu 261// add item "name" to menu
275void LLComboBox::add(const LLString& name, EAddPosition pos, BOOL enabled) 262LLScrollListItem* LLComboBox::add(const LLString& name, EAddPosition pos, BOOL enabled)
276{ 263{
277 mList->addSimpleItem(name, pos, enabled); 264 LLScrollListItem* item = mList->addSimpleElement(name, pos);
265 item->setEnabled(enabled);
278 mList->selectFirstItem(); 266 mList->selectFirstItem();
267 return item;
279} 268}
280 269
281// add item "name" with a unique id to menu 270// add item "name" with a unique id to menu
282void LLComboBox::add(const LLString& name, const LLUUID& id, EAddPosition pos, BOOL enabled ) 271LLScrollListItem* LLComboBox::add(const LLString& name, const LLUUID& id, EAddPosition pos, BOOL enabled )
283{ 272{
284 mList->addSimpleItem(name, LLSD(id), pos, enabled); 273 LLScrollListItem* item = mList->addSimpleElement(name, pos, id);
274 item->setEnabled(enabled);
285 mList->selectFirstItem(); 275 mList->selectFirstItem();
276 return item;
286} 277}
287 278
288// add item "name" with attached userdata 279// add item "name" with attached userdata
289void LLComboBox::add(const LLString& name, void* userdata, EAddPosition pos, BOOL enabled ) 280LLScrollListItem* LLComboBox::add(const LLString& name, void* userdata, EAddPosition pos, BOOL enabled )
290{ 281{
291 LLScrollListItem* item = mList->addSimpleItem(name, pos, enabled); 282 LLScrollListItem* item = mList->addSimpleElement(name, pos);
283 item->setEnabled(enabled);
292 item->setUserdata( userdata ); 284 item->setUserdata( userdata );
293 mList->selectFirstItem(); 285 mList->selectFirstItem();
286 return item;
294} 287}
295 288
296// add item "name" with attached generic data 289// add item "name" with attached generic data
297void LLComboBox::add(const LLString& name, LLSD value, EAddPosition pos, BOOL enabled ) 290LLScrollListItem* LLComboBox::add(const LLString& name, LLSD value, EAddPosition pos, BOOL enabled )
298{ 291{
299 mList->addSimpleItem(name, value, pos, enabled); 292 LLScrollListItem* item = mList->addSimpleElement(name, pos, value);
293 item->setEnabled(enabled);
300 mList->selectFirstItem(); 294 mList->selectFirstItem();
295 return item;
301} 296}
302 297
298LLScrollListItem* LLComboBox::addSeparator(EAddPosition pos)
299{
300 return mList->addSeparator(pos);
301}
303 302
304void LLComboBox::sortByName() 303void LLComboBox::sortByName()
305{ 304{
@@ -311,7 +310,7 @@ void LLComboBox::sortByName()
311// Returns TRUE if the item was found. 310// Returns TRUE if the item was found.
312BOOL LLComboBox::setSimple(const LLStringExplicit& name) 311BOOL LLComboBox::setSimple(const LLStringExplicit& name)
313{ 312{
314 BOOL found = mList->selectSimpleItem(name, FALSE); 313 BOOL found = mList->selectItemByLabel(name, FALSE);
315 314
316 if (found) 315 if (found)
317 { 316 {
@@ -330,14 +329,14 @@ void LLComboBox::setValue(const LLSD& value)
330 LLScrollListItem* item = mList->getFirstSelected(); 329 LLScrollListItem* item = mList->getFirstSelected();
331 if (item) 330 if (item)
332 { 331 {
333 setLabel( mList->getSimpleSelectedItem() ); 332 setLabel( mList->getSelectedItemLabel() );
334 } 333 }
335 } 334 }
336} 335}
337 336
338const LLString& LLComboBox::getSimple() const 337const LLString LLComboBox::getSimple() const
339{ 338{
340 const LLString& res = mList->getSimpleSelectedItem(); 339 const LLString res = mList->getSelectedItemLabel();
341 if (res.empty() && mAllowTextEntry) 340 if (res.empty() && mAllowTextEntry)
342 { 341 {
343 return mTextEntry->getText(); 342 return mTextEntry->getText();
@@ -348,9 +347,9 @@ const LLString& LLComboBox::getSimple() const
348 } 347 }
349} 348}
350 349
351const LLString& LLComboBox::getSimpleSelectedItem(S32 column) const 350const LLString LLComboBox::getSelectedItemLabel(S32 column) const
352{ 351{
353 return mList->getSimpleSelectedItem(column); 352 return mList->getSelectedItemLabel(column);
354} 353}
355 354
356// virtual 355// virtual
@@ -373,10 +372,10 @@ LLSD LLComboBox::getValue() const
373 372
374void LLComboBox::setLabel(const LLStringExplicit& name) 373void LLComboBox::setLabel(const LLStringExplicit& name)
375{ 374{
376 if ( mAllowTextEntry ) 375 if ( mTextEntry )
377 { 376 {
378 mTextEntry->setText(name); 377 mTextEntry->setText(name);
379 if (mList->selectSimpleItem(name, FALSE)) 378 if (mList->selectItemByLabel(name, FALSE))
380 { 379 {
381 mTextEntry->setTentative(FALSE); 380 mTextEntry->setTentative(FALSE);
382 } 381 }
@@ -385,7 +384,8 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
385 mTextEntry->setTentative(mTextEntryTentative); 384 mTextEntry->setTentative(mTextEntryTentative);
386 } 385 }
387 } 386 }
388 else 387
388 if (!mAllowTextEntry)
389 { 389 {
390 mButton->setLabelUnselected(name); 390 mButton->setLabelUnselected(name);
391 mButton->setLabelSelected(name); 391 mButton->setLabelSelected(name);
@@ -397,7 +397,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
397 397
398BOOL LLComboBox::remove(const LLString& name) 398BOOL LLComboBox::remove(const LLString& name)
399{ 399{
400 BOOL found = mList->selectSimpleItem(name); 400 BOOL found = mList->selectItemByLabel(name);
401 401
402 if (found) 402 if (found)
403 { 403 {
@@ -433,16 +433,21 @@ void LLComboBox::onFocusLost()
433 LLUICtrl::onFocusLost(); 433 LLUICtrl::onFocusLost();
434} 434}
435 435
436void LLComboBox::onLostTop()
437{
438 hideList();
439}
440
441
436void LLComboBox::setButtonVisible(BOOL visible) 442void LLComboBox::setButtonVisible(BOOL visible)
437{ 443{
438 mButton->setVisible(visible); 444 mButton->setVisible(visible);
439 mDrawArrow = visible;
440 if (mTextEntry) 445 if (mTextEntry)
441 { 446 {
442 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0); 447 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
443 if (visible) 448 if (visible)
444 { 449 {
445 text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton"); 450 text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth(0)) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
446 } 451 }
447 //mTextEntry->setRect(text_entry_rect); 452 //mTextEntry->setRect(text_entry_rect);
448 mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); 453 mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
@@ -457,22 +462,8 @@ void LLComboBox::draw()
457 462
458 mButton->setEnabled(mEnabled /*&& !mList->isEmpty()*/); 463 mButton->setEnabled(mEnabled /*&& !mList->isEmpty()*/);
459 464
460 // Draw children 465 // Draw children normally
461 LLUICtrl::draw(); 466 LLUICtrl::draw();
462
463 if (mDrawArrow)
464 {
465 // Paste the graphic on the right edge
466 if (!mArrowImage.isNull())
467 {
468 S32 arrow_height = llmin(mRect.getHeight(), mArrowImage->getHeight());
469 S32 arrow_width = llround((F32)mArrowImage->getWidth() * ((F32)arrow_height / (F32)mArrowImage->getHeight()));
470
471 S32 left = mRect.getWidth() - mArrowImage->getWidth() - LLUI::sConfigGroup->getS32("DropShadowButton");
472
473 gl_draw_scaled_image( left, 0, arrow_width, arrow_height, mArrowImage, LLColor4::white);
474 }
475 }
476 } 467 }
477} 468}
478 469
@@ -481,7 +472,7 @@ BOOL LLComboBox::setCurrentByIndex( S32 index )
481 BOOL found = mList->selectNthItem( index ); 472 BOOL found = mList->selectNthItem( index );
482 if (found) 473 if (found)
483 { 474 {
484 setLabel(mList->getSimpleSelectedItem()); 475 setLabel(mList->getSelectedItemLabel());
485 } 476 }
486 return found; 477 return found;
487} 478}
@@ -497,6 +488,67 @@ S32 LLComboBox::getCurrentIndex() const
497} 488}
498 489
499 490
491void LLComboBox::updateLayout()
492{
493 LLRect rect = getLocalRect();
494 if (mAllowTextEntry)
495 {
496 S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
497 mButton->setRect(LLRect( mRect.getWidth() - llmax(8,mArrowImage->getWidth(0)) - 2 * shadow_size,
498 rect.mTop, rect.mRight, rect.mBottom));
499 mButton->setTabStop(FALSE);
500
501 if (!mTextEntry)
502 {
503 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
504 text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth(0)) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
505 // clear label on button
506 LLString cur_label = mButton->getLabelSelected();
507 mTextEntry = new LLLineEditor("combo_text_entry",
508 text_entry_rect,
509 "",
510 LLFontGL::sSansSerifSmall,
511 mMaxChars,
512 onTextCommit,
513 onTextEntry,
514 NULL,
515 this,
516 NULL, // prevalidate func
517 LLViewBorder::BEVEL_NONE,
518 LLViewBorder::STYLE_LINE,
519 0); // no border
520 mTextEntry->setSelectAllonFocusReceived(TRUE);
521 mTextEntry->setHandleEditKeysDirectly(TRUE);
522 mTextEntry->setCommitOnFocusLost(FALSE);
523 mTextEntry->setText(cur_label);
524 mTextEntry->setIgnoreTab(TRUE);
525 mTextEntry->setFollowsAll();
526 addChild(mTextEntry);
527 }
528 else
529 {
530 mTextEntry->setVisible(TRUE);
531 mTextEntry->setMaxTextLength(mMaxChars);
532 }
533
534 // clear label on button
535 setLabel(LLString::null);
536
537 mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
538 }
539 else if (!mAllowTextEntry)
540 {
541 mButton->setRect(rect);
542 mButton->setTabStop(TRUE);
543
544 if (mTextEntry)
545 {
546 mTextEntry->setVisible(FALSE);
547 }
548 mButton->setFollowsAll();
549 }
550}
551
500void* LLComboBox::getCurrentUserdata() 552void* LLComboBox::getCurrentUserdata()
501{ 553{
502 LLScrollListItem* item = mList->getFirstSelected(); 554 LLScrollListItem* item = mList->getFirstSelected();
@@ -514,7 +566,7 @@ void LLComboBox::showList()
514 LLCoordWindow window_size; 566 LLCoordWindow window_size;
515 getWindow()->getSize(&window_size); 567 getWindow()->getSize(&window_size);
516 //HACK: shouldn't have to know about scale here 568 //HACK: shouldn't have to know about scale here
517 mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); 569 mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
518 570
519 // Make sure that we can see the whole list 571 // Make sure that we can see the whole list
520 LLRect root_view_local; 572 LLRect root_view_local;
@@ -523,7 +575,9 @@ void LLComboBox::showList()
523 575
524 LLRect rect = mList->getRect(); 576 LLRect rect = mList->getRect();
525 577
526 S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE; 578 S32 min_width = mRect.getWidth();
579 S32 max_width = llmax(min_width, MAX_COMBO_WIDTH);
580 S32 list_width = llclamp(mList->getMaxContentWidth(), min_width, max_width);
527 581
528 if (mListPosition == BELOW) 582 if (mListPosition == BELOW)
529 { 583 {
@@ -583,12 +637,6 @@ void LLComboBox::showList()
583 mList->translate(0, -y); 637 mList->translate(0, -y);
584 } 638 }
585 639
586 // pass mouse capture on to list if button is depressed
587 if (mButton->hasMouseCapture())
588 {
589 gFocusMgr.setMouseCapture(mList);
590 }
591
592 // NB: this call will trigger the focuslost callback which will hide the list, so do it first 640 // NB: this call will trigger the focuslost callback which will hide the list, so do it first
593 // before finally showing the list 641 // before finally showing the list
594 642
@@ -604,24 +652,29 @@ void LLComboBox::showList()
604 mButton->setToggleState(TRUE); 652 mButton->setToggleState(TRUE);
605 mList->setVisible(TRUE); 653 mList->setVisible(TRUE);
606 654
607 gFocusMgr.setTopCtrl(mList); 655 setUseBoundingRect(TRUE);
656 gFocusMgr.setTopCtrl(this);
608} 657}
609 658
610void LLComboBox::hideList() 659void LLComboBox::hideList()
611{ 660{
661 //*HACK: store the original value explicitly somewhere, not just in label
662 LLString orig_selection = mAllowTextEntry ? mTextEntry->getText() : mButton->getLabelSelected();
663
664 // assert selection in list
665 mList->selectItemByLabel(orig_selection, FALSE);
666
612 mButton->setToggleState(FALSE); 667 mButton->setToggleState(FALSE);
613 mList->setVisible(FALSE); 668 mList->setVisible(FALSE);
614 mList->highlightNthItem(-1); 669 mList->highlightNthItem(-1);
615 670
616 if( gFocusMgr.getTopCtrl() == mList ) 671 setUseBoundingRect(FALSE);
672 if( gFocusMgr.getTopCtrl() == this )
617 { 673 {
618 gFocusMgr.setTopCtrl(NULL); 674 gFocusMgr.setTopCtrl(NULL);
619 } 675 }
620
621 //mList->setFocus(FALSE);
622} 676}
623 677
624
625//------------------------------------------------------------------ 678//------------------------------------------------------------------
626// static functions 679// static functions
627//------------------------------------------------------------------ 680//------------------------------------------------------------------
@@ -650,21 +703,20 @@ void LLComboBox::onButtonDown(void *userdata)
650 self->showList(); 703 self->showList();
651 } 704 }
652 705
653 if (self->mKeyboardFocusOnClick && !self->hasFocus()) 706 self->setFocus( TRUE );
707
708 // pass mouse capture on to list if button is depressed
709 if (self->mButton->hasMouseCapture())
654 { 710 {
655 self->setFocus( TRUE ); 711 gFocusMgr.setMouseCapture(self->mList);
656 } 712 }
657 } 713 }
658 else 714 else
659 { 715 {
660 // hide and release keyboard focus
661 self->hideList(); 716 self->hideList();
662
663 self->onCommit();
664 } 717 }
665}
666
667 718
719}
668 720
669// static 721// static
670void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata) 722void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
@@ -672,7 +724,7 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
672 // Note: item is the LLScrollListCtrl 724 // Note: item is the LLScrollListCtrl
673 LLComboBox *self = (LLComboBox *) userdata; 725 LLComboBox *self = (LLComboBox *) userdata;
674 726
675 const LLString& name = self->mList->getSimpleSelectedItem(); 727 const LLString name = self->mList->getSelectedItemLabel();
676 728
677 S32 cur_id = self->getCurrentIndex(); 729 S32 cur_id = self->getCurrentIndex();
678 if (cur_id != -1) 730 if (cur_id != -1)
@@ -681,40 +733,24 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
681 733
682 if (self->mAllowTextEntry) 734 if (self->mAllowTextEntry)
683 { 735 {
684 gFocusMgr.setKeyboardFocus(self->mTextEntry, NULL); 736 gFocusMgr.setKeyboardFocus(self->mTextEntry);
685 self->mTextEntry->selectAll(); 737 self->mTextEntry->selectAll();
686 } 738 }
687 } 739 }
688 else 740 else
689 { 741 {
690 // invalid selection, just restore existing value 742 // invalid selection, just restore existing value
691 self->mList->selectSimpleItem(self->mButton->getLabelSelected()); 743 LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
744
745 self->mList->selectItemByLabel(orig_selection);
692 } 746 }
693 self->onCommit(); 747 self->onCommit();
694 748
695 self->hideList(); 749 self->hideList();
696} 750}
697 751
698// static
699void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data)
700{
701 LLComboBox *self = (LLComboBox *) list->getParent();
702 // user not manipulating list or clicking on drop down button
703 if (!self->mList->hasFocus() && !self->mButton->hasMouseCapture())
704 {
705 //*HACK: store the original value explicitly somewhere, not just in label
706 LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
707
708 self->hideList();
709
710 // reassert original selection
711 self->mList->selectSimpleItem(orig_selection, FALSE);
712 }
713}
714
715BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) 752BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
716{ 753{
717
718 LLString tool_tip; 754 LLString tool_tip;
719 755
720 if (LLUI::sShowXUINames) 756 if (LLUI::sShowXUINames)
@@ -726,23 +762,19 @@ BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_
726 tool_tip = mToolTipMsg; 762 tool_tip = mToolTipMsg;
727 } 763 }
728 764
729 if( getVisible() && pointInView( x, y ) ) 765 if( !tool_tip.empty() )
730 { 766 {
731 if( !tool_tip.empty() ) 767 msg = tool_tip;
732 { 768
733 msg = tool_tip; 769 // Convert rect local to screen coordinates
734 770 localPointToScreen(
735 // Convert rect local to screen coordinates 771 0, 0,
736 localPointToScreen( 772 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
737 0, 0, 773 localPointToScreen(
738 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); 774 mRect.getWidth(), mRect.getHeight(),
739 localPointToScreen( 775 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
740 mRect.getWidth(), mRect.getHeight(),
741 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
742 }
743 return TRUE;
744 } 776 }
745 return FALSE; 777 return TRUE;
746} 778}
747 779
748BOOL LLComboBox::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) 780BOOL LLComboBox::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
@@ -793,63 +825,11 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent
793 825
794void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative) 826void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative)
795{ 827{
796 LLRect rect( 0, mRect.getHeight(), mRect.getWidth(), 0);
797 if (allow && !mAllowTextEntry)
798 {
799 S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
800 mButton->setRect(LLRect( mRect.getWidth() - mArrowImageWidth - 2 * shadow_size,
801 rect.mTop, rect.mRight, rect.mBottom));
802 mButton->setTabStop(FALSE);
803
804 // clear label on button
805 LLString cur_label = mButton->getLabelSelected();
806 setLabel(LLString::null);
807 if (!mTextEntry)
808 {
809 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
810 text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
811 mTextEntry = new LLLineEditor("combo_text_entry",
812 text_entry_rect,
813 "",
814 LLFontGL::sSansSerifSmall,
815 max_chars,
816 onTextCommit,
817 onTextEntry,
818 NULL,
819 this,
820 NULL, // prevalidate func
821 LLViewBorder::BEVEL_NONE,
822 LLViewBorder::STYLE_LINE,
823 0); // no border
824 mTextEntry->setSelectAllonFocusReceived(TRUE);
825 mTextEntry->setHandleEditKeysDirectly(TRUE);
826 mTextEntry->setCommitOnFocusLost(FALSE);
827 mTextEntry->setText(cur_label);
828 mTextEntry->setIgnoreTab(TRUE);
829 mTextEntry->setFollowsAll();
830 addChild(mTextEntry);
831 mMaxChars = max_chars;
832 }
833 else
834 {
835 mTextEntry->setVisible(TRUE);
836 }
837
838 mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
839 }
840 else if (!allow && mAllowTextEntry)
841 {
842 mButton->setRect(rect);
843 mButton->setTabStop(TRUE);
844
845 if (mTextEntry)
846 {
847 mTextEntry->setVisible(FALSE);
848 }
849 mButton->setFollowsAll();
850 }
851 mAllowTextEntry = allow; 828 mAllowTextEntry = allow;
852 mTextEntryTentative = set_tentative; 829 mTextEntryTentative = set_tentative;
830 mMaxChars = max_chars;
831
832 updateLayout();
853} 833}
854 834
855void LLComboBox::setTextEntry(const LLStringExplicit& text) 835void LLComboBox::setTextEntry(const LLStringExplicit& text)
@@ -875,7 +855,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
875 if (key == KEY_BACKSPACE || 855 if (key == KEY_BACKSPACE ||
876 key == KEY_DELETE) 856 key == KEY_DELETE)
877 { 857 {
878 if (self->mList->selectSimpleItem(line_editor->getText(), FALSE)) 858 if (self->mList->selectItemByLabel(line_editor->getText(), FALSE))
879 { 859 {
880 line_editor->setTentative(FALSE); 860 line_editor->setTentative(FALSE);
881 } 861 }
@@ -955,11 +935,11 @@ void LLComboBox::updateSelection()
955 } 935 }
956 } 936 }
957 937
958 if (mList->selectSimpleItem(full_string, FALSE)) 938 if (mList->selectItemByLabel(full_string, FALSE))
959 { 939 {
960 mTextEntry->setTentative(FALSE); 940 mTextEntry->setTentative(FALSE);
961 } 941 }
962 else if (!mList->selectSimpleItemByPrefix(left_wstring, FALSE)) 942 else if (!mList->selectItemByPrefix(left_wstring, FALSE))
963 { 943 {
964 mList->deselectAllItems(); 944 mList->deselectAllItems();
965 mTextEntry->setText(wstring_to_utf8str(user_wstring)); 945 mTextEntry->setText(wstring_to_utf8str(user_wstring));
@@ -967,7 +947,7 @@ void LLComboBox::updateSelection()
967 } 947 }
968 else 948 else
969 { 949 {
970 LLWString selected_item = utf8str_to_wstring(mList->getSimpleSelectedItem()); 950 LLWString selected_item = utf8str_to_wstring(mList->getSelectedItemLabel());
971 LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); 951 LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size());
972 mTextEntry->setText(wstring_to_utf8str(wtext)); 952 mTextEntry->setText(wstring_to_utf8str(wtext));
973 mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); 953 mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size());
@@ -993,6 +973,10 @@ void LLComboBox::setFocus(BOOL b)
993 if (b) 973 if (b)
994 { 974 {
995 mList->clearSearchString(); 975 mList->clearSearchString();
976 if (mList->getVisible())
977 {
978 mList->setFocus(TRUE);
979 }
996 } 980 }
997} 981}
998 982
@@ -1048,7 +1032,7 @@ BOOL LLComboBox::setCurrentByID(const LLUUID& id)
1048 1032
1049 if (found) 1033 if (found)
1050 { 1034 {
1051 setLabel(mList->getSimpleSelectedItem()); 1035 setLabel(mList->getSelectedItemLabel());
1052 } 1036 }
1053 1037
1054 return found; 1038 return found;
@@ -1063,14 +1047,14 @@ BOOL LLComboBox::setSelectedByValue(LLSD value, BOOL selected)
1063 BOOL found = mList->setSelectedByValue(value, selected); 1047 BOOL found = mList->setSelectedByValue(value, selected);
1064 if (found) 1048 if (found)
1065 { 1049 {
1066 setLabel(mList->getSimpleSelectedItem()); 1050 setLabel(mList->getSelectedItemLabel());
1067 } 1051 }
1068 return found; 1052 return found;
1069} 1053}
1070 1054
1071LLSD LLComboBox::getSimpleSelectedValue() 1055LLSD LLComboBox::getSelectedValue()
1072{ 1056{
1073 return mList->getSimpleSelectedValue(); 1057 return mList->getSelectedValue();
1074} 1058}
1075 1059
1076BOOL LLComboBox::isSelected(LLSD value) 1060BOOL LLComboBox::isSelected(LLSD value)
@@ -1097,3 +1081,155 @@ BOOL LLComboBox::operateOnAll(EOperation op)
1097 } 1081 }
1098 return FALSE; 1082 return FALSE;
1099} 1083}
1084
1085
1086
1087//
1088// LLFlyoutButton
1089//
1090
1091const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24;
1092
1093LLFlyoutButton::LLFlyoutButton(
1094 const LLString& name,
1095 const LLRect &rect,
1096 const LLString& label,
1097 void (*commit_callback)(LLUICtrl*, void*) ,
1098 void *callback_userdata)
1099: LLComboBox(name, rect, LLString::null, commit_callback, callback_userdata),
1100 mToggleState(FALSE),
1101 mActionButton(NULL)
1102{
1103 // Always use text box
1104 // Text label button
1105 mActionButton = new LLButton("flyout_button_main",
1106 LLRect(), label, NULL, LLString::null,
1107 NULL, this);
1108 mActionButton->setScaleImage(TRUE);
1109
1110 mActionButton->setClickedCallback(onActionButtonClick);
1111 mActionButton->setFollowsAll();
1112 mActionButton->setHAlign( LLFontGL::HCENTER );
1113 mActionButton->setLabel(label);
1114 addChild(mActionButton);
1115
1116 mActionButtonImage = LLUI::getUIImageByName("flyout_btn_left.tga");
1117 mExpanderButtonImage = LLUI::getUIImageByName("flyout_btn_right.tga");
1118 mActionButtonImageSelected = LLUI::getUIImageByName("flyout_btn_left_selected.tga");
1119 mExpanderButtonImageSelected = LLUI::getUIImageByName("flyout_btn_right_selected.tga");
1120
1121 mActionButton->setImageSelected(mActionButtonImageSelected);
1122 mActionButton->setImageUnselected(mActionButtonImage);
1123 mActionButton->setImageDisabled(LLPointer<LLUIImage>(NULL));
1124 mActionButton->setImageDisabledSelected(LLPointer<LLUIImage>(NULL));
1125
1126 mButton->setImageSelected(mExpanderButtonImageSelected);
1127 mButton->setImageUnselected(mExpanderButtonImage);
1128 mButton->setImageDisabled(LLPointer<LLUIImage>(NULL));
1129 mButton->setImageDisabledSelected(LLPointer<LLUIImage>(NULL));
1130 mButton->setRightHPad(6);
1131
1132 mBorder->setVisible(FALSE);
1133
1134 updateLayout();
1135}
1136
1137//static
1138LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
1139{
1140 LLString name = "flyout_button";
1141 node->getAttributeString("name", name);
1142
1143 LLString label("");
1144 node->getAttributeString("label", label);
1145
1146 LLRect rect;
1147 createRect(node, rect, parent, LLRect());
1148
1149 LLUICtrlCallback callback = NULL;
1150
1151 LLFlyoutButton* flyout_button = new LLFlyoutButton(name,
1152 rect,
1153 label,
1154 callback,
1155 NULL);
1156
1157 LLString list_position;
1158 node->getAttributeString("list_position", list_position);
1159 if (list_position == "below")
1160 {
1161 flyout_button->mListPosition = BELOW;
1162 }
1163 else if (list_position == "above")
1164 {
1165 flyout_button->mListPosition = ABOVE;
1166 }
1167
1168
1169 flyout_button->initFromXML(node, parent);
1170
1171 LLXMLNodePtr child;
1172 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
1173 {
1174 if (child->hasName("flyout_button_item"))
1175 {
1176 LLString label = child->getTextContents();
1177
1178 LLString value = label;
1179 child->getAttributeString("value", value);
1180
1181 flyout_button->add(label, LLSD(value) );
1182 }
1183 }
1184
1185 flyout_button->updateLayout();
1186
1187 return flyout_button;
1188}
1189
1190void LLFlyoutButton::updateLayout()
1191{
1192 LLComboBox::updateLayout();
1193
1194 mButton->setOrigin(mRect.getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0);
1195 mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, mRect.getHeight());
1196 mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
1197 mButton->setTabStop(FALSE);
1198 mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT);
1199
1200 mActionButton->setOrigin(0, 0);
1201 mActionButton->reshape(mRect.getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, mRect.getHeight());
1202}
1203
1204//static
1205void LLFlyoutButton::onActionButtonClick(void *user_data)
1206{
1207 LLFlyoutButton* buttonp = (LLFlyoutButton*)user_data;
1208 // remember last list selection?
1209 buttonp->mList->deselect();
1210 buttonp->onCommit();
1211}
1212
1213void LLFlyoutButton::draw()
1214{
1215 mActionButton->setToggleState(mToggleState);
1216 mButton->setToggleState(mToggleState);
1217
1218 //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or
1219 // the label reflects the last selected item, for now we have to manually remove the label
1220 mButton->setLabel(LLString::null);
1221 LLComboBox::draw();
1222}
1223
1224void LLFlyoutButton::setEnabled(BOOL enabled)
1225{
1226 mActionButton->setEnabled(enabled);
1227 LLComboBox::setEnabled(enabled);
1228}
1229
1230
1231void LLFlyoutButton::setToggleState(BOOL state)
1232{
1233 mToggleState = state;
1234}
1235
diff --git a/linden/indra/llui/llcombobox.h b/linden/indra/llui/llcombobox.h
index 6e5e4ab..2a70db2 100644
--- a/linden/indra/llui/llcombobox.h
+++ b/linden/indra/llui/llcombobox.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -80,6 +80,7 @@ public:
80 80
81 virtual void draw(); 81 virtual void draw();
82 virtual void onFocusLost(); 82 virtual void onFocusLost();
83 virtual void onLostTop();
83 84
84 virtual void setEnabled(BOOL enabled); 85 virtual void setEnabled(BOOL enabled);
85 86
@@ -107,21 +108,22 @@ public:
107 void setAllowTextEntry(BOOL allow, S32 max_chars = 50, BOOL make_tentative = TRUE); 108 void setAllowTextEntry(BOOL allow, S32 max_chars = 50, BOOL make_tentative = TRUE);
108 void setTextEntry(const LLStringExplicit& text); 109 void setTextEntry(const LLStringExplicit& text);
109 110
110 void add(const LLString& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu 111 LLScrollListItem* add(const LLString& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu
111 void add(const LLString& name, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); 112 LLScrollListItem* add(const LLString& name, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
112 void add(const LLString& name, void* userdata, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); 113 LLScrollListItem* add(const LLString& name, void* userdata, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
113 void add(const LLString& name, LLSD value, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); 114 LLScrollListItem* add(const LLString& name, LLSD value, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
115 LLScrollListItem* addSeparator(EAddPosition pos = ADD_BOTTOM);
114 BOOL remove( S32 index ); // remove item by index, return TRUE if found and removed 116 BOOL remove( S32 index ); // remove item by index, return TRUE if found and removed
115 void removeall() { clearRows(); } 117 void removeall() { clearRows(); }
116 118
117 void sortByName(); // Sort the entries in the combobox by name 119 void sortByName(); // Sort the entries in the combobox by name
118 120
119 // Select current item by name using selectSimpleItem. Returns FALSE if not found. 121 // Select current item by name using selectItemByLabel. Returns FALSE if not found.
120 BOOL setSimple(const LLStringExplicit& name); 122 BOOL setSimple(const LLStringExplicit& name);
121 // Get name of current item. Returns an empty string if not found. 123 // Get name of current item. Returns an empty string if not found.
122 const LLString& getSimple() const; 124 const LLString getSimple() const;
123 // Get contents of column x of selected row 125 // Get contents of column x of selected row
124 const LLString& getSimpleSelectedItem(S32 column = 0) const; 126 const LLString getSelectedItemLabel(S32 column = 0) const;
125 127
126 // Sets the label, which doesn't have to exist in the label. 128 // Sets the label, which doesn't have to exist in the label.
127 // This is probably a UI abuse. 129 // This is probably a UI abuse.
@@ -132,6 +134,8 @@ public:
132 BOOL setCurrentByIndex( S32 index ); 134 BOOL setCurrentByIndex( S32 index );
133 S32 getCurrentIndex() const; 135 S32 getCurrentIndex() const;
134 136
137 virtual void updateLayout();
138
135 //======================================================================== 139 //========================================================================
136 LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; }; 140 LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; };
137 LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)this; }; 141 LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)this; };
@@ -156,7 +160,7 @@ public:
156 virtual BOOL setCurrentByID( const LLUUID& id ); 160 virtual BOOL setCurrentByID( const LLUUID& id );
157 virtual LLUUID getCurrentID(); // LLUUID::null if no items in menu 161 virtual LLUUID getCurrentID(); // LLUUID::null if no items in menu
158 virtual BOOL setSelectedByValue(LLSD value, BOOL selected); 162 virtual BOOL setSelectedByValue(LLSD value, BOOL selected);
159 virtual LLSD getSimpleSelectedValue(); 163 virtual LLSD getSelectedValue();
160 virtual BOOL isSelected(LLSD value); 164 virtual BOOL isSelected(LLSD value);
161 virtual BOOL operateOnSelection(EOperation op); 165 virtual BOOL operateOnSelection(EOperation op);
162 virtual BOOL operateOnAll(EOperation op); 166 virtual BOOL operateOnAll(EOperation op);
@@ -172,7 +176,6 @@ public:
172 176
173 static void onButtonDown(void *userdata); 177 static void onButtonDown(void *userdata);
174 static void onItemSelected(LLUICtrl* item, void *userdata); 178 static void onItemSelected(LLUICtrl* item, void *userdata);
175 static void onListFocusChanged(LLUICtrl* item, void *userdata);
176 static void onTextEntry(LLLineEditor* line_editor, void* user_data); 179 static void onTextEntry(LLLineEditor* line_editor, void* user_data);
177 static void onTextCommit(LLUICtrl* caller, void* user_data); 180 static void onTextCommit(LLUICtrl* caller, void* user_data);
178 181
@@ -183,12 +186,10 @@ public:
183protected: 186protected:
184 LLButton* mButton; 187 LLButton* mButton;
185 LLScrollListCtrl* mList; 188 LLScrollListCtrl* mList;
189 S32 mButtonPadding;
186 LLViewBorder* mBorder; 190 LLViewBorder* mBorder;
187 BOOL mKeyboardFocusOnClick;
188 BOOL mDrawArrow;
189 LLLineEditor* mTextEntry; 191 LLLineEditor* mTextEntry;
190 LLPointer<LLImageGL> mArrowImage; 192 LLPointer<LLImageGL> mArrowImage;
191 S32 mArrowImageWidth;
192 BOOL mAllowTextEntry; 193 BOOL mAllowTextEntry;
193 S32 mMaxChars; 194 S32 mMaxChars;
194 BOOL mTextEntryTentative; 195 BOOL mTextEntryTentative;
@@ -197,4 +198,36 @@ protected:
197 void (*mTextEntryCallback)(LLLineEditor*, void*); 198 void (*mTextEntryCallback)(LLLineEditor*, void*);
198}; 199};
199 200
201class LLFlyoutButton : public LLComboBox
202{
203public:
204 LLFlyoutButton(
205 const LLString& name,
206 const LLRect &rect,
207 const LLString& label,
208 void (*commit_callback)(LLUICtrl*, void*) = NULL,
209 void *callback_userdata = NULL);
210
211 virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_FLYOUT_BUTTON; }
212 virtual LLString getWidgetTag() const { return LL_FLYOUT_BUTTON_TAG; }
213
214 virtual void updateLayout();
215 virtual void draw();
216 virtual void setEnabled(BOOL enabled);
217
218 void setToggleState(BOOL state);
219
220 static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
221 static void onActionButtonClick(void *userdata);
222 static void onSelectAction(LLUICtrl* ctrl, void *userdata);
223
224protected:
225 LLButton* mActionButton;
226 LLPointer<LLUIImage> mActionButtonImage;
227 LLPointer<LLUIImage> mExpanderButtonImage;
228 LLPointer<LLUIImage> mActionButtonImageSelected;
229 LLPointer<LLUIImage> mExpanderButtonImageSelected;
230 BOOL mToggleState;
231};
232
200#endif 233#endif
diff --git a/linden/indra/llui/llctrlselectioninterface.cpp b/linden/indra/llui/llctrlselectioninterface.cpp
index 6fb5df3..996f5b3 100644
--- a/linden/indra/llui/llctrlselectioninterface.cpp
+++ b/linden/indra/llui/llctrlselectioninterface.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llctrlselectioninterface.h b/linden/indra/llui/llctrlselectioninterface.h
index 20caa1e..121d971 100644
--- a/linden/indra/llui/llctrlselectioninterface.h
+++ b/linden/indra/llui/llctrlselectioninterface.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -68,7 +68,7 @@ public:
68 BOOL selectByValue(LLSD value); 68 BOOL selectByValue(LLSD value);
69 BOOL deselectByValue(LLSD value); 69 BOOL deselectByValue(LLSD value);
70 virtual BOOL setSelectedByValue(LLSD value, BOOL selected) = 0; 70 virtual BOOL setSelectedByValue(LLSD value, BOOL selected) = 0;
71 virtual LLSD getSimpleSelectedValue() = 0; 71 virtual LLSD getSelectedValue() = 0;
72 72
73 virtual BOOL isSelected(LLSD value) = 0; 73 virtual BOOL isSelected(LLSD value) = 0;
74 74
diff --git a/linden/indra/llui/lldraghandle.cpp b/linden/indra/llui/lldraghandle.cpp
index fb91201..032cb91 100644
--- a/linden/indra/llui/lldraghandle.cpp
+++ b/linden/indra/llui/lldraghandle.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lldraghandle.h b/linden/indra/llui/lldraghandle.h
index c085991..a48c0f7 100644
--- a/linden/indra/llui/lldraghandle.h
+++ b/linden/indra/llui/lldraghandle.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -54,7 +54,6 @@ public:
54 54
55 virtual void setTitle( const LLString& title ) = 0; 55 virtual void setTitle( const LLString& title ) = 0;
56 virtual const LLString& getTitle() const = 0; 56 virtual const LLString& getTitle() const = 0;
57 virtual void draw() = 0;
58 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) = 0; 57 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) = 0;
59 58
60 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 59 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
diff --git a/linden/indra/llui/lleditmenuhandler.cpp b/linden/indra/llui/lleditmenuhandler.cpp
index b359098..6291088 100644
--- a/linden/indra/llui/lleditmenuhandler.cpp
+++ b/linden/indra/llui/lleditmenuhandler.cpp
@@ -12,12 +12,12 @@
12* ("GPL"), unless you have obtained a separate licensing agreement 12* ("GPL"), unless you have obtained a separate licensing agreement
13* ("Other License"), formally executed by you and Linden Lab. Terms of 13* ("Other License"), formally executed by you and Linden Lab. Terms of
14* the GPL can be found in doc/GPL-license.txt in this distribution, or 14* the GPL can be found in doc/GPL-license.txt in this distribution, or
15* online at http://secondlife.com/developers/opensource/gplv2 15* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16* 16*
17* There are special exceptions to the terms and conditions of the GPL as 17* There are special exceptions to the terms and conditions of the GPL as
18* it is applied to this Source Code. View the full text of the exception 18* it is applied to this Source Code. View the full text of the exception
19* in the file doc/FLOSS-exception.txt in this software distribution, or 19* in the file doc/FLOSS-exception.txt in this software distribution, or
20* online at http://secondlife.com/developers/opensource/flossexception 20* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21* 21*
22* By copying, modifying or distributing this software, you acknowledge 22* By copying, modifying or distributing this software, you acknowledge
23* that you have read and understood your obligations described above, 23* that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lleditmenuhandler.h b/linden/indra/llui/lleditmenuhandler.h
index 394d27c..ef9b1dd 100644
--- a/linden/indra/llui/lleditmenuhandler.h
+++ b/linden/indra/llui/lleditmenuhandler.h
@@ -12,12 +12,12 @@
12* ("GPL"), unless you have obtained a separate licensing agreement 12* ("GPL"), unless you have obtained a separate licensing agreement
13* ("Other License"), formally executed by you and Linden Lab. Terms of 13* ("Other License"), formally executed by you and Linden Lab. Terms of
14* the GPL can be found in doc/GPL-license.txt in this distribution, or 14* the GPL can be found in doc/GPL-license.txt in this distribution, or
15* online at http://secondlife.com/developers/opensource/gplv2 15* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16* 16*
17* There are special exceptions to the terms and conditions of the GPL as 17* There are special exceptions to the terms and conditions of the GPL as
18* it is applied to this Source Code. View the full text of the exception 18* it is applied to this Source Code. View the full text of the exception
19* in the file doc/FLOSS-exception.txt in this software distribution, or 19* in the file doc/FLOSS-exception.txt in this software distribution, or
20* online at http://secondlife.com/developers/opensource/flossexception 20* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21* 21*
22* By copying, modifying or distributing this software, you acknowledge 22* By copying, modifying or distributing this software, you acknowledge
23* that you have read and understood your obligations described above, 23* that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp
index 8ff3c48..1500f9f 100644
--- a/linden/indra/llui/llfloater.cpp
+++ b/linden/indra/llui/llfloater.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -128,7 +128,11 @@ LLFloater::handle_map_t LLFloater::sFloaterMap;
128 128
129LLFloaterView* gFloaterView = NULL; 129LLFloaterView* gFloaterView = NULL;
130 130
131LLFloater::LLFloater() 131LLFloater::LLFloater() :
132 //FIXME: we should initialize *all* member variables here
133 mResizable(FALSE),
134 mDragOnLeft(FALSE)
135
132{ 136{
133 // automatically take focus when opened 137 // automatically take focus when opened
134 mAutoFocus = TRUE; 138 mAutoFocus = TRUE;
@@ -215,9 +219,14 @@ void LLFloater::init(const LLString& title,
215 } 219 }
216 mButtonScale = 1.f; 220 mButtonScale = 1.f;
217 221
218 LLPanel::deleteAllChildren(); 222 BOOL need_border = mBorder != NULL;
223
224 // this will delete mBorder too
225 deleteAllChildren();
226 // make sure we don't have a pointer to an old, deleted border
227 mBorder = NULL;
219 //sjb: HACK! we had a border which was just deleted, so re-create it 228 //sjb: HACK! we had a border which was just deleted, so re-create it
220 if (mBorder != NULL) 229 if (need_border)
221 { 230 {
222 addBorder(); 231 addBorder();
223 } 232 }
@@ -609,7 +618,7 @@ void LLFloater::releaseFocus()
609 618
610 if( gFocusMgr.childHasKeyboardFocus( this ) ) 619 if( gFocusMgr.childHasKeyboardFocus( this ) )
611 { 620 {
612 gFocusMgr.setKeyboardFocus(NULL, NULL); 621 gFocusMgr.setKeyboardFocus(NULL);
613 } 622 }
614 623
615 if( gFocusMgr.childHasMouseCapture( this ) ) 624 if( gFocusMgr.childHasMouseCapture( this ) )
@@ -1026,13 +1035,10 @@ void LLFloater::setHost(LLMultiFloater* host)
1026 { 1035 {
1027 mButtonsEnabled[BUTTON_TEAR_OFF] = TRUE; 1036 mButtonsEnabled[BUTTON_TEAR_OFF] = TRUE;
1028 } 1037 }
1029
1030 mIsFocusRoot = FALSE;
1031 } 1038 }
1032 else if (!mHostHandle.isDead() && !host) 1039 else if (!mHostHandle.isDead() && !host)
1033 { 1040 {
1034 mButtonScale = 1.f; 1041 mButtonScale = 1.f;
1035 mIsFocusRoot = TRUE;
1036 //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; 1042 //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;
1037 } 1043 }
1038 updateButtons(); 1044 updateButtons();
@@ -1260,6 +1266,7 @@ void LLFloater::show(LLFloater* floaterp)
1260{ 1266{
1261 if (floaterp) 1267 if (floaterp)
1262 { 1268 {
1269 gFocusMgr.triggerFocusFlash();
1263 floaterp->open(); 1270 floaterp->open();
1264 if (floaterp->getHost()) 1271 if (floaterp->getHost())
1265 { 1272 {
@@ -2245,7 +2252,8 @@ void LLFloaterView::refresh()
2245 LLFloater* floaterp = (LLFloater*)*child_it; 2252 LLFloater* floaterp = (LLFloater*)*child_it;
2246 if( floaterp->getVisible() ) 2253 if( floaterp->getVisible() )
2247 { 2254 {
2248 adjustToFitScreen(floaterp, TRUE); 2255 // minimized floaters are kept fully onscreen
2256 adjustToFitScreen(floaterp, !floaterp->isMinimized());
2249 } 2257 }
2250 } 2258 }
2251} 2259}
@@ -2605,9 +2613,9 @@ void LLMultiFloater::draw()
2605 for (S32 i = 0; i < mTabContainer->getTabCount(); i++) 2613 for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
2606 { 2614 {
2607 LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i); 2615 LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
2608 if (floaterp->getTitle() != mTabContainer->getPanelTitle(i)) 2616 if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
2609 { 2617 {
2610 mTabContainer->setPanelTitle(i, floaterp->getTitle()); 2618 mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
2611 } 2619 }
2612 } 2620 }
2613 LLFloater::draw(); 2621 LLFloater::draw();
@@ -2725,7 +2733,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
2725 2733
2726 if ( select_added_floater ) 2734 if ( select_added_floater )
2727 { 2735 {
2728 mTabContainer->selectLastTab(); 2736 mTabContainer->selectTabPanel(floaterp);
2729 } 2737 }
2730 2738
2731 floaterp->setHost(this); 2739 floaterp->setHost(this);
@@ -2970,8 +2978,9 @@ void LLMultiFloater::updateResizeLimits()
2970 // make sure upper left corner doesn't move 2978 // make sure upper left corner doesn't move
2971 translate(0, cur_height - mRect.getHeight()); 2979 translate(0, cur_height - mRect.getHeight());
2972 2980
2973 // Try to keep whole view onscreen, don't allow partial offscreen. 2981 // make sure this window is visible on screen when it has been modified
2974 gFloaterView->adjustToFitScreen(this, FALSE); 2982 // (tab added, etc)
2983 gFloaterView->adjustToFitScreen(this, TRUE);
2975 } 2984 }
2976} 2985}
2977 2986
diff --git a/linden/indra/llui/llfloater.h b/linden/indra/llui/llfloater.h
index 3a34057..56b0e6e 100644
--- a/linden/indra/llui/llfloater.h
+++ b/linden/indra/llui/llfloater.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp
index 065c206..efca3d8 100644
--- a/linden/indra/llui/llfocusmgr.cpp
+++ b/linden/indra/llui/llfocusmgr.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -42,11 +42,10 @@ LLFocusMgr gFocusMgr;
42LLFocusMgr::LLFocusMgr() 42LLFocusMgr::LLFocusMgr()
43 : 43 :
44 mLockedView( NULL ), 44 mLockedView( NULL ),
45 mKeyboardLockedFocusLostCallback( NULL ),
46 mMouseCaptor( NULL ), 45 mMouseCaptor( NULL ),
47 mKeyboardFocus( NULL ), 46 mKeyboardFocus( NULL ),
47 mLastKeyboardFocus( NULL ),
48 mDefaultKeyboardFocus( NULL ), 48 mDefaultKeyboardFocus( NULL ),
49 mKeyboardFocusLostCallback( NULL ),
50 mTopCtrl( NULL ), 49 mTopCtrl( NULL ),
51 mFocusWeight(0.f), 50 mFocusWeight(0.f),
52 mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true 51 mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true
@@ -75,12 +74,11 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
75 if (view == mLockedView) 74 if (view == mLockedView)
76 { 75 {
77 mLockedView = NULL; 76 mLockedView = NULL;
78 mKeyboardLockedFocusLostCallback = NULL; 77 setKeyboardFocus( NULL );
79 setKeyboardFocus( NULL, NULL );
80 } 78 }
81 else 79 else
82 { 80 {
83 setKeyboardFocus( mLockedView, mKeyboardLockedFocusLostCallback ); 81 setKeyboardFocus( mLockedView );
84 } 82 }
85 } 83 }
86 84
@@ -91,7 +89,7 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
91} 89}
92 90
93 91
94void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focus_lost, BOOL lock) 92void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock)
95{ 93{
96 if (mLockedView && 94 if (mLockedView &&
97 (new_focus == NULL || 95 (new_focus == NULL ||
@@ -101,28 +99,27 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu
101 // or one of its descendants 99 // or one of its descendants
102 return; 100 return;
103 } 101 }
104 FocusLostCallback old_callback = mKeyboardFocusLostCallback;
105 mKeyboardFocusLostCallback = on_focus_lost;
106 102
107 //llinfos << "Keyboard focus handled by " << (new_focus ? new_focus->getName() : "nothing") << llendl; 103 //llinfos << "Keyboard focus handled by " << (new_focus ? new_focus->getName() : "nothing") << llendl;
108 104
109 if( new_focus != mKeyboardFocus ) 105 if( new_focus != mKeyboardFocus )
110 { 106 {
111 LLUICtrl* old_focus = mKeyboardFocus; 107 mLastKeyboardFocus = mKeyboardFocus;
112 mKeyboardFocus = new_focus; 108 mKeyboardFocus = new_focus;
113 109
110 if( mLastKeyboardFocus )
111 {
112 mLastKeyboardFocus->onFocusLost();
113 }
114
114 // clear out any existing flash 115 // clear out any existing flash
115 if (new_focus) 116 if (new_focus)
116 { 117 {
117 mFocusWeight = 0.f; 118 mFocusWeight = 0.f;
119 new_focus->onFocusReceived();
118 } 120 }
119 mFocusTimer.reset(); 121 mFocusTimer.reset();
120 122
121 if( old_callback )
122 {
123 old_callback( old_focus );
124 }
125
126 #ifdef _DEBUG 123 #ifdef _DEBUG
127 mKeyboardFocusName = new_focus ? new_focus->getName() : "none"; 124 mKeyboardFocusName = new_focus ? new_focus->getName() : "none";
128 #endif 125 #endif
@@ -204,13 +201,11 @@ void LLFocusMgr::removeKeyboardFocusWithoutCallback( LLView* focus )
204 if (focus == mLockedView) 201 if (focus == mLockedView)
205 { 202 {
206 mLockedView = NULL; 203 mLockedView = NULL;
207 mKeyboardLockedFocusLostCallback = NULL;
208 } 204 }
209 205
210 if( mKeyboardFocus == focus ) 206 if( mKeyboardFocus == focus )
211 { 207 {
212 mKeyboardFocus = NULL; 208 mKeyboardFocus = NULL;
213 mKeyboardFocusLostCallback = NULL;
214 #ifdef _DEBUG 209 #ifdef _DEBUG
215 mKeyboardFocusName = "none"; 210 mKeyboardFocusName = "none";
216 #endif 211 #endif
@@ -293,13 +288,19 @@ BOOL LLFocusMgr::childIsTopCtrl( LLView* parent )
293// set new_top = NULL to release top_view. 288// set new_top = NULL to release top_view.
294void LLFocusMgr::setTopCtrl( LLUICtrl* new_top ) 289void LLFocusMgr::setTopCtrl( LLUICtrl* new_top )
295{ 290{
296 if( new_top != mTopCtrl ) 291 LLUICtrl* old_top = mTopCtrl;
292 if( new_top != old_top )
297 { 293 {
298 mTopCtrl = new_top; 294 mTopCtrl = new_top;
299 295
300 #ifdef _DEBUG 296 #ifdef _DEBUG
301 mTopCtrlName = new_top ? new_top->getName() : "none"; 297 mTopCtrlName = new_top ? new_top->getName() : "none";
302 #endif 298 #endif
299
300 if (old_top)
301 {
302 old_top->onLostTop();
303 }
303 } 304 }
304} 305}
305 306
@@ -317,13 +318,11 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( LLUICtrl* top_view )
317void LLFocusMgr::lockFocus() 318void LLFocusMgr::lockFocus()
318{ 319{
319 mLockedView = mKeyboardFocus; 320 mLockedView = mKeyboardFocus;
320 mKeyboardLockedFocusLostCallback = mKeyboardFocusLostCallback;
321} 321}
322 322
323void LLFocusMgr::unlockFocus() 323void LLFocusMgr::unlockFocus()
324{ 324{
325 mLockedView = NULL; 325 mLockedView = NULL;
326 mKeyboardLockedFocusLostCallback = NULL;
327} 326}
328 327
329F32 LLFocusMgr::getFocusFlashAmt() 328F32 LLFocusMgr::getFocusFlashAmt()
@@ -356,9 +355,9 @@ void LLFocusMgr::setAppHasFocus(BOOL focus)
356 } 355 }
357 356
358 // release focus from "top ctrl"s, which generally hides them 357 // release focus from "top ctrl"s, which generally hides them
359 if (!focus && mTopCtrl && mTopCtrl->hasFocus()) 358 if (!focus && mTopCtrl)
360 { 359 {
361 mTopCtrl->setFocus(FALSE); 360 setTopCtrl(NULL);
362 } 361 }
363 mAppHasFocus = focus; 362 mAppHasFocus = focus;
364} 363}
diff --git a/linden/indra/llui/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h
index 02f588e..3bd5b35 100644
--- a/linden/indra/llui/llfocusmgr.h
+++ b/linden/indra/llui/llfocusmgr.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -44,8 +44,6 @@ class LLMouseHandler;
44class LLFocusMgr 44class LLFocusMgr
45{ 45{
46public: 46public:
47 typedef void (*FocusLostCallback)(LLUICtrl*);
48
49 LLFocusMgr(); 47 LLFocusMgr();
50 ~LLFocusMgr(); 48 ~LLFocusMgr();
51 49
@@ -56,11 +54,11 @@ public:
56 BOOL childHasMouseCapture( LLView* parent ); 54 BOOL childHasMouseCapture( LLView* parent );
57 55
58 // Keyboard Focus 56 // Keyboard Focus
59 void setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focus_lost, BOOL lock = FALSE); // new_focus = NULL to release the focus. 57 void setKeyboardFocus(LLUICtrl* new_focus, BOOL lock = FALSE); // new_focus = NULL to release the focus.
60 LLUICtrl* getKeyboardFocus() const { return mKeyboardFocus; } 58 LLUICtrl* getKeyboardFocus() const { return mKeyboardFocus; }
59 LLUICtrl* getLastKeyboardFocus() const { return mLastKeyboardFocus; }
61 BOOL childHasKeyboardFocus( const LLView* parent ) const; 60 BOOL childHasKeyboardFocus( const LLView* parent ) const;
62 void removeKeyboardFocusWithoutCallback( LLView* focus ); 61 void removeKeyboardFocusWithoutCallback( LLView* focus );
63 FocusLostCallback getFocusCallback() { return mKeyboardFocusLostCallback; }
64 F32 getFocusTime() const { return mFocusTimer.getElapsedTimeF32(); } 62 F32 getFocusTime() const { return mFocusTimer.getElapsedTimeF32(); }
65 F32 getFocusFlashAmt(); 63 F32 getFocusFlashAmt();
66 LLColor4 getFocusColor(); 64 LLColor4 getFocusColor();
@@ -90,15 +88,14 @@ public:
90 88
91protected: 89protected:
92 LLUICtrl* mLockedView; 90 LLUICtrl* mLockedView;
93 FocusLostCallback mKeyboardLockedFocusLostCallback;
94 91
95 // Mouse Captor 92 // Mouse Captor
96 LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object 93 LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object
97 94
98 // Keyboard Focus 95 // Keyboard Focus
99 LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object 96 LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object
97 LLUICtrl* mLastKeyboardFocus; // who last had focus
100 LLUICtrl* mDefaultKeyboardFocus; 98 LLUICtrl* mDefaultKeyboardFocus;
101 FocusLostCallback mKeyboardFocusLostCallback; // The object to which keyboard events are routed is called before another object takes its place
102 99
103 // Top View 100 // Top View
104 LLUICtrl* mTopCtrl; 101 LLUICtrl* mTopCtrl;
diff --git a/linden/indra/llui/llhtmlhelp.h b/linden/indra/llui/llhtmlhelp.h
index 36324d0..d4ec9e3 100644
--- a/linden/indra/llui/llhtmlhelp.h
+++ b/linden/indra/llui/llhtmlhelp.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -37,7 +37,6 @@ class LLHtmlHelp
37public: 37public:
38 virtual ~LLHtmlHelp() {} 38 virtual ~LLHtmlHelp() {}
39 virtual void show(std::string start_url, std::string title) = 0; 39 virtual void show(std::string start_url, std::string title) = 0;
40 virtual BOOL getFloaterOpened()=0;
41}; 40};
42 41
43#endif // LL_LLFLOATERHTMLHELP_H 42#endif // LL_LLFLOATERHTMLHELP_H
diff --git a/linden/indra/llui/lliconctrl.cpp b/linden/indra/llui/lliconctrl.cpp
index 40272ee..79982c6 100644
--- a/linden/indra/llui/lliconctrl.cpp
+++ b/linden/indra/llui/lliconctrl.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -88,18 +88,11 @@ void LLIconCtrl::draw()
88{ 88{
89 if( getVisible() ) 89 if( getVisible() )
90 { 90 {
91 // Border 91 if( mImagep.notNull() )
92 BOOL has_image = !mImageID.isNull();
93
94 if( has_image )
95 { 92 {
96 if( mImagep.notNull() ) 93 mImagep->draw(0, 0,
97 { 94 mRect.getWidth(), mRect.getHeight(),
98 gl_draw_scaled_image(0, 0, 95 mColor );
99 mRect.getWidth(), mRect.getHeight(),
100 mImagep,
101 mColor );
102 }
103 } 96 }
104 97
105 LLUICtrl::draw(); 98 LLUICtrl::draw();
@@ -154,6 +147,7 @@ LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
154 LLUICtrlFactory::getAttributeColor(node,"color", color); 147 LLUICtrlFactory::getAttributeColor(node,"color", color);
155 148
156 LLIconCtrl* icon = new LLIconCtrl(name, rect, image_id); 149 LLIconCtrl* icon = new LLIconCtrl(name, rect, image_id);
150
157 icon->setColor(color); 151 icon->setColor(color);
158 152
159 icon->initFromXML(node, parent); 153 icon->initFromXML(node, parent);
diff --git a/linden/indra/llui/lliconctrl.h b/linden/indra/llui/lliconctrl.h
index 0cd43bb..f767b3c 100644
--- a/linden/indra/llui/lliconctrl.h
+++ b/linden/indra/llui/lliconctrl.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -73,7 +73,7 @@ protected:
73 LLColor4 mColor; 73 LLColor4 mColor;
74 LLString mImageName; 74 LLString mImageName;
75 LLUUID mImageID; 75 LLUUID mImageID;
76 LLPointer<LLImageGL> mImagep; 76 LLPointer<LLUIImage> mImagep;
77}; 77};
78 78
79#endif 79#endif
diff --git a/linden/indra/llui/llkeywords.cpp b/linden/indra/llui/llkeywords.cpp
index 3adde76..1d157d2 100644
--- a/linden/indra/llui/llkeywords.cpp
+++ b/linden/indra/llui/llkeywords.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -233,7 +233,7 @@ LLColor3 LLKeywords::readColor( const LLString& s )
233 233
234// Walk through a string, applying the rules specified by the keyword token list and 234// Walk through a string, applying the rules specified by the keyword token list and
235// create a list of color segments. 235// create a list of color segments.
236void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWString& wtext) 236void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWString& wtext, const LLColor4 &defaultColor)
237{ 237{
238 std::for_each(seg_list->begin(), seg_list->end(), DeletePointer()); 238 std::for_each(seg_list->begin(), seg_list->end(), DeletePointer());
239 seg_list->clear(); 239 seg_list->clear();
@@ -245,7 +245,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
245 245
246 S32 text_len = wtext.size(); 246 S32 text_len = wtext.size();
247 247
248 seg_list->push_back( new LLTextSegment( LLColor3(0,0,0), 0, text_len ) ); 248 seg_list->push_back( new LLTextSegment( LLColor3(defaultColor), 0, text_len ) );
249 249
250 const llwchar* base = wtext.c_str(); 250 const llwchar* base = wtext.c_str();
251 const llwchar* cur = base; 251 const llwchar* cur = base;
@@ -299,7 +299,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
299 //llinfos << "Seg: [" << (char*)LLString( base, seg_start, seg_end-seg_start) << "]" << llendl; 299 //llinfos << "Seg: [" << (char*)LLString( base, seg_start, seg_end-seg_start) << "]" << llendl;
300 LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); 300 LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end );
301 text_segment->setToken( cur_token ); 301 text_segment->setToken( cur_token );
302 insertSegment( seg_list, text_segment, text_len); 302 insertSegment( seg_list, text_segment, text_len, defaultColor);
303 line_done = TRUE; // to break out of second loop. 303 line_done = TRUE; // to break out of second loop.
304 break; 304 break;
305 } 305 }
@@ -409,7 +409,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
409 //llinfos << "Seg: [" << (char*)LLString( base, seg_start, seg_end-seg_start ) << "]" << llendl; 409 //llinfos << "Seg: [" << (char*)LLString( base, seg_start, seg_end-seg_start ) << "]" << llendl;
410 LLTextSegment* text_segment = new LLTextSegment( cur_delimiter->getColor(), seg_start, seg_end ); 410 LLTextSegment* text_segment = new LLTextSegment( cur_delimiter->getColor(), seg_start, seg_end );
411 text_segment->setToken( cur_delimiter ); 411 text_segment->setToken( cur_delimiter );
412 insertSegment( seg_list, text_segment, text_len); 412 insertSegment( seg_list, text_segment, text_len, defaultColor);
413 413
414 // Note: we don't increment cur, since the end of one delimited seg may be immediately 414 // Note: we don't increment cur, since the end of one delimited seg may be immediately
415 // followed by the start of another one. 415 // followed by the start of another one.
@@ -442,7 +442,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
442 442
443 LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); 443 LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end );
444 text_segment->setToken( cur_token ); 444 text_segment->setToken( cur_token );
445 insertSegment( seg_list, text_segment, text_len); 445 insertSegment( seg_list, text_segment, text_len, defaultColor);
446 } 446 }
447 cur += seg_len; 447 cur += seg_len;
448 continue; 448 continue;
@@ -457,7 +457,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
457 } 457 }
458} 458}
459 459
460void LLKeywords::insertSegment(std::vector<LLTextSegment*>* seg_list, LLTextSegment* new_segment, S32 text_len ) 460void LLKeywords::insertSegment(std::vector<LLTextSegment*>* seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor )
461{ 461{
462 LLTextSegment* last = seg_list->back(); 462 LLTextSegment* last = seg_list->back();
463 S32 new_seg_end = new_segment->getEnd(); 463 S32 new_seg_end = new_segment->getEnd();
@@ -475,7 +475,7 @@ void LLKeywords::insertSegment(std::vector<LLTextSegment*>* seg_list, LLTextSegm
475 475
476 if( new_seg_end < text_len ) 476 if( new_seg_end < text_len )
477 { 477 {
478 seg_list->push_back( new LLTextSegment( LLColor3(0,0,0), new_seg_end, text_len ) ); 478 seg_list->push_back( new LLTextSegment( defaultColor, new_seg_end, text_len ) );
479 } 479 }
480} 480}
481 481
diff --git a/linden/indra/llui/llkeywords.h b/linden/indra/llui/llkeywords.h
index e6ff029..d5d7302 100644
--- a/linden/indra/llui/llkeywords.h
+++ b/linden/indra/llui/llkeywords.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -84,7 +84,7 @@ public:
84 BOOL loadFromFile(const LLString& filename); 84 BOOL loadFromFile(const LLString& filename);
85 BOOL isLoaded() { return mLoaded; } 85 BOOL isLoaded() { return mLoaded; }
86 86
87 void findSegments(std::vector<LLTextSegment *> *seg_list, const LLWString& text ); 87 void findSegments(std::vector<LLTextSegment *> *seg_list, const LLWString& text, const LLColor4 &defaultColor );
88 88
89#ifdef _DEBUG 89#ifdef _DEBUG
90 void dump(); 90 void dump();
@@ -98,7 +98,7 @@ public:
98 98
99private: 99private:
100 LLColor3 readColor(const LLString& s); 100 LLColor3 readColor(const LLString& s);
101 void insertSegment(std::vector<LLTextSegment *> *seg_list, LLTextSegment* new_segment, S32 text_len); 101 void insertSegment(std::vector<LLTextSegment *> *seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor);
102 102
103private: 103private:
104 BOOL mLoaded; 104 BOOL mLoaded;
diff --git a/linden/indra/llui/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp
index 2851beb..88c8d75 100644
--- a/linden/indra/llui/lllineeditor.cpp
+++ b/linden/indra/llui/lllineeditor.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -72,6 +72,15 @@ const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing
72const F32 AUTO_SCROLL_TIME = 0.05f; 72const F32 AUTO_SCROLL_TIME = 0.05f;
73const F32 LABEL_HPAD = 5.f; 73const F32 LABEL_HPAD = 5.f;
74 74
75const F32 PREEDIT_MARKER_BRIGHTNESS = 0.4f;
76const S32 PREEDIT_MARKER_GAP = 1;
77const S32 PREEDIT_MARKER_POSITION = 2;
78const S32 PREEDIT_MARKER_THICKNESS = 1;
79const F32 PREEDIT_STANDOUT_BRIGHTNESS = 0.6f;
80const S32 PREEDIT_STANDOUT_GAP = 1;
81const S32 PREEDIT_STANDOUT_POSITION = 2;
82const S32 PREEDIT_STANDOUT_THICKNESS = 2;
83
75// This is a friend class of and is only used by LLLineEditor 84// This is a friend class of and is only used by LLLineEditor
76class LLLineEditorRollback 85class LLLineEditorRollback
77{ 86{
@@ -119,7 +128,7 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
119 S32 max_length_bytes, 128 S32 max_length_bytes,
120 void (*commit_callback)(LLUICtrl* caller, void* user_data ), 129 void (*commit_callback)(LLUICtrl* caller, void* user_data ),
121 void (*keystroke_callback)(LLLineEditor* caller, void* user_data ), 130 void (*keystroke_callback)(LLLineEditor* caller, void* user_data ),
122 void (*focus_lost_callback)(LLUICtrl* caller, void* user_data ), 131 void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data ),
123 void* userdata, 132 void* userdata,
124 LLLinePrevalidateFunc prevalidate_func, 133 LLLinePrevalidateFunc prevalidate_func,
125 LLViewBorder::EBevel border_bevel, 134 LLViewBorder::EBevel border_bevel,
@@ -127,7 +136,6 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect,
127 S32 border_thickness) 136 S32 border_thickness)
128 : 137 :
129 LLUICtrl( name, rect, TRUE, commit_callback, userdata, FOLLOWS_TOP | FOLLOWS_LEFT ), 138 LLUICtrl( name, rect, TRUE, commit_callback, userdata, FOLLOWS_TOP | FOLLOWS_LEFT ),
130 mMaxLengthChars(max_length_bytes),
131 mMaxLengthBytes(max_length_bytes), 139 mMaxLengthBytes(max_length_bytes),
132 mCursorPos( 0 ), 140 mCursorPos( 0 ),
133 mScrollHPos( 0 ), 141 mScrollHPos( 0 ),
@@ -223,12 +231,19 @@ LLString LLLineEditor::getWidgetTag() const
223 return LL_LINE_EDITOR_TAG; 231 return LL_LINE_EDITOR_TAG;
224} 232}
225 233
226void LLLineEditor::onFocusLost() 234void LLLineEditor::onFocusReceived()
227{ 235{
228 // Need to notify early when loosing focus. 236 LLUICtrl::onFocusReceived();
229 getWindow()->allowLanguageTextInput(FALSE); 237 updateAllowingLanguageInput();
238}
230 239
231 LLUICtrl::onFocusLost(); 240void LLLineEditor::onFocusLost()
241{
242 // The call to updateAllowLanguageInput()
243 // when loosing the keyboard focus *may*
244 // indirectly invoke handleUnicodeCharHere(),
245 // so it must be called before onCommit.
246 updateAllowingLanguageInput();
232 247
233 if( mCommitOnFocusLost && mText.getString() != mPrevText) 248 if( mCommitOnFocusLost && mText.getString() != mPrevText)
234 { 249 {
@@ -241,6 +256,8 @@ void LLLineEditor::onFocusLost()
241 } 256 }
242 257
243 getWindow()->showCursorFromMouseMove(); 258 getWindow()->showCursorFromMouseMove();
259
260 LLUICtrl::onFocusLost();
244} 261}
245 262
246void LLLineEditor::onCommit() 263void LLLineEditor::onCommit()
@@ -301,6 +318,7 @@ void LLLineEditor::setEnabled(BOOL enabled)
301{ 318{
302 mReadOnly = !enabled; 319 mReadOnly = !enabled;
303 setTabStop(!mReadOnly); 320 setTabStop(!mReadOnly);
321 updateAllowingLanguageInput();
304} 322}
305 323
306 324
@@ -308,7 +326,6 @@ void LLLineEditor::setMaxTextLength(S32 max_text_length)
308{ 326{
309 S32 max_len = llmax(0, max_text_length); 327 S32 max_len = llmax(0, max_text_length);
310 mMaxLengthBytes = max_len; 328 mMaxLengthBytes = max_len;
311 mMaxLengthChars = max_len;
312} 329}
313 330
314void LLLineEditor::setBorderWidth(S32 left, S32 right) 331void LLLineEditor::setBorderWidth(S32 left, S32 right)
@@ -334,18 +351,22 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
334 351
335 // Check to see if entire field is selected. 352 // Check to see if entire field is selected.
336 S32 len = mText.length(); 353 S32 len = mText.length();
337 BOOL allSelected = (len > 0) && (( mSelectionStart == 0 && mSelectionEnd == len ) 354 BOOL all_selected = (len > 0)
338 || ( mSelectionStart == len && mSelectionEnd == 0 )); 355 && (( mSelectionStart == 0 && mSelectionEnd == len )
356 || ( mSelectionStart == len && mSelectionEnd == 0 ));
357
358 // Do safe truncation so we don't split multi-byte characters
359 // also consider entire string selected when mSelectAllonFocusReceived is set on an empty, focused line editor
360 all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);
339 361
340 LLString truncated_utf8 = new_text; 362 LLString truncated_utf8 = new_text;
341 if (truncated_utf8.size() > (U32)mMaxLengthBytes) 363 if (truncated_utf8.size() > (U32)mMaxLengthBytes)
342 { 364 {
343 utf8str_truncate(truncated_utf8, mMaxLengthBytes); 365 truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes);
344 } 366 }
345 mText.assign(truncated_utf8); 367 mText.assign(truncated_utf8);
346 mText.truncate(mMaxLengthChars);
347 368
348 if (allSelected) 369 if (all_selected)
349 { 370 {
350 // ...keep whole thing selected 371 // ...keep whole thing selected
351 selectAll(); 372 selectAll();
@@ -735,17 +756,12 @@ void LLLineEditor::addChar(const llwchar uni_char)
735 mText.erase(getCursor(), 1); 756 mText.erase(getCursor(), 1);
736 } 757 }
737 758
738 S32 length_chars = mText.length(); 759 S32 cur_bytes = mText.getString().size();
739 S32 cur_bytes = mText.getString().size();;
740 S32 new_bytes = wchar_utf8_length(new_c); 760 S32 new_bytes = wchar_utf8_length(new_c);
741 761
742 BOOL allow_char = TRUE; 762 BOOL allow_char = TRUE;
743 763
744 // Inserting character 764 // Check byte length limit
745 if (length_chars == mMaxLengthChars)
746 {
747 allow_char = FALSE;
748 }
749 if ((new_bytes + cur_bytes) > mMaxLengthBytes) 765 if ((new_bytes + cur_bytes) > mMaxLengthBytes)
750 { 766 {
751 allow_char = FALSE; 767 allow_char = FALSE;
@@ -794,6 +810,12 @@ void LLLineEditor::setSelection(S32 start, S32 end)
794 setCursor(start); 810 setCursor(start);
795} 811}
796 812
813void LLLineEditor::setDrawAsterixes(BOOL b)
814{
815 mDrawAsterixes = b;
816 updateAllowingLanguageInput();
817}
818
797S32 LLLineEditor::prevWordPos(S32 cursorPos) const 819S32 LLLineEditor::prevWordPos(S32 cursorPos) const
798{ 820{
799 const LLWString& wtext = mText.getWString(); 821 const LLWString& wtext = mText.getWString();
@@ -1022,13 +1044,11 @@ void LLLineEditor::paste()
1022 1044
1023 // Insert the string 1045 // Insert the string
1024 1046
1025 //check to see that the size isn't going to be larger than the 1047 // Check to see that the size isn't going to be larger than the max number of bytes
1026 //max number of characters or bytes
1027 U32 available_bytes = mMaxLengthBytes - wstring_utf8_length(mText); 1048 U32 available_bytes = mMaxLengthBytes - wstring_utf8_length(mText);
1028 size_t available_chars = mMaxLengthChars - mText.length();
1029 1049
1030 if ( available_bytes < (U32) wstring_utf8_length(clean_string) ) 1050 if ( available_bytes < (U32) wstring_utf8_length(clean_string) )
1031 { 1051 { // Doesn't all fit
1032 llwchar current_symbol = clean_string[0]; 1052 llwchar current_symbol = clean_string[0];
1033 U32 wchars_that_fit = 0; 1053 U32 wchars_that_fit = 0;
1034 U32 total_bytes = wchar_utf8_length(current_symbol); 1054 U32 total_bytes = wchar_utf8_length(current_symbol);
@@ -1043,20 +1063,13 @@ void LLLineEditor::paste()
1043 current_symbol = clean_string[++wchars_that_fit]; 1063 current_symbol = clean_string[++wchars_that_fit];
1044 total_bytes += wchar_utf8_length(current_symbol); 1064 total_bytes += wchar_utf8_length(current_symbol);
1045 } 1065 }
1046 1066 // Truncate the clean string at the limit of what will fit
1047 clean_string = clean_string.substr(0, wchars_that_fit); 1067 clean_string = clean_string.substr(0, wchars_that_fit);
1048 reportBadKeystroke(); 1068 reportBadKeystroke();
1049 } 1069 }
1050 else if (available_chars < clean_string.length())
1051 {
1052 // We can't insert all the characters. Insert as many as possible
1053 // but make a noise to alert the user. JC
1054 clean_string = clean_string.substr(0, available_chars);
1055 reportBadKeystroke();
1056 }
1057 1070
1058 mText.insert(getCursor(), clean_string); 1071 mText.insert(getCursor(), clean_string);
1059 setCursor(llmin(mMaxLengthChars, getCursor() + (S32)clean_string.length())); 1072 setCursor( getCursor() + (S32)clean_string.length() );
1060 deselect(); 1073 deselect();
1061 1074
1062 // Validate new string and rollback the if needed. 1075 // Validate new string and rollback the if needed.
@@ -1523,6 +1536,41 @@ void LLLineEditor::draw()
1523 } 1536 }
1524 LLColor4 label_color = mTentativeFgColor; 1537 LLColor4 label_color = mTentativeFgColor;
1525 1538
1539 if (hasPreeditString())
1540 {
1541 // Draw preedit markers. This needs to be before drawing letters.
1542 for (U32 i = 0; i < mPreeditStandouts.size(); i++)
1543 {
1544 const S32 preedit_left = mPreeditPositions[i];
1545 const S32 preedit_right = mPreeditPositions[i + 1];
1546 if (preedit_right > mScrollHPos)
1547 {
1548 S32 preedit_pixels_left = findPixelNearestPos(llmax(preedit_left, mScrollHPos) - getCursor());
1549 S32 preedit_pixels_right = llmin(findPixelNearestPos(preedit_right - getCursor()), background.mRight);
1550 if (preedit_pixels_left >= background.mRight)
1551 {
1552 break;
1553 }
1554 if (mPreeditStandouts[i])
1555 {
1556 gl_rect_2d(preedit_pixels_left + PREEDIT_STANDOUT_GAP,
1557 background.mBottom + PREEDIT_STANDOUT_POSITION,
1558 preedit_pixels_right - PREEDIT_STANDOUT_GAP - 1,
1559 background.mBottom + PREEDIT_STANDOUT_POSITION - PREEDIT_STANDOUT_THICKNESS,
1560 (text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
1561 }
1562 else
1563 {
1564 gl_rect_2d(preedit_pixels_left + PREEDIT_MARKER_GAP,
1565 background.mBottom + PREEDIT_MARKER_POSITION,
1566 preedit_pixels_right - PREEDIT_MARKER_GAP - 1,
1567 background.mBottom + PREEDIT_MARKER_POSITION - PREEDIT_MARKER_THICKNESS,
1568 (text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
1569 }
1570 }
1571 }
1572 }
1573
1526 S32 rendered_text = 0; 1574 S32 rendered_text = 0;
1527 F32 rendered_pixels_right = (F32)mMinHPixels; 1575 F32 rendered_pixels_right = (F32)mMinHPixels;
1528 F32 text_bottom = (F32)background.mBottom + (F32)UI_LINEEDITOR_V_PAD; 1576 F32 text_bottom = (F32)background.mBottom + (F32)UI_LINEEDITOR_V_PAD;
@@ -1677,7 +1725,7 @@ void LLLineEditor::draw()
1677 1725
1678 1726
1679// Returns the local screen space X coordinate associated with the text cursor position. 1727// Returns the local screen space X coordinate associated with the text cursor position.
1680S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) 1728S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const
1681{ 1729{
1682 S32 dpos = getCursor() - mScrollHPos + cursor_offset; 1730 S32 dpos = getCursor() - mScrollHPos + cursor_offset;
1683 S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mMinHPixels; 1731 S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mMinHPixels;
@@ -1715,7 +1763,7 @@ void LLLineEditor::setFocus( BOOL new_state )
1715 1763
1716 if (!new_state) 1764 if (!new_state)
1717 { 1765 {
1718 getWindow()->allowLanguageTextInput(FALSE); 1766 getWindow()->allowLanguageTextInput(this, FALSE);
1719 } 1767 }
1720 1768
1721 1769
@@ -1757,7 +1805,7 @@ void LLLineEditor::setFocus( BOOL new_state )
1757 // fine on 1.15.0.2, since all prevalidate func reject any 1805 // fine on 1.15.0.2, since all prevalidate func reject any
1758 // non-ASCII characters. I'm not sure on future versions, 1806 // non-ASCII characters. I'm not sure on future versions,
1759 // however. 1807 // however.
1760 getWindow()->allowLanguageTextInput(mPrevalidateFunc == NULL); 1808 getWindow()->allowLanguageTextInput(this, mPrevalidateFunc == NULL);
1761 } 1809 }
1762} 1810}
1763 1811
@@ -1776,6 +1824,12 @@ void LLLineEditor::setRect(const LLRect& rect)
1776 } 1824 }
1777} 1825}
1778 1826
1827void LLLineEditor::setPrevalidate(BOOL (*func)(const LLWString &))
1828{
1829 mPrevalidateFunc = func;
1830 updateAllowingLanguageInput();
1831}
1832
1779// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. 1833// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
1780// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for 1834// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
1781// the simple reasons that intermediate states may be invalid even if the final result is valid. 1835// the simple reasons that intermediate states may be invalid even if the final result is valid.
@@ -2336,6 +2390,239 @@ BOOL LLLineEditor::setLabelArg( const LLString& key, const LLStringExplicit& tex
2336 return TRUE; 2390 return TRUE;
2337} 2391}
2338 2392
2393
2394void LLLineEditor::updateAllowingLanguageInput()
2395{
2396 // Allow Language Text Input only when this LineEditor has
2397 // no prevalidate function attached (as long as other criteria
2398 // common to LLTextEditor). This criterion works
2399 // fine on 1.15.0.2, since all prevalidate func reject any
2400 // non-ASCII characters. I'm not sure on future versions,
2401 // however...
2402 if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL)
2403 {
2404 getWindow()->allowLanguageTextInput(this, TRUE);
2405 }
2406 else
2407 {
2408 getWindow()->allowLanguageTextInput(this, FALSE);
2409 }
2410}
2411
2412BOOL LLLineEditor::hasPreeditString() const
2413{
2414 return (mPreeditPositions.size() > 1);
2415}
2416
2417void LLLineEditor::resetPreedit()
2418{
2419 if (hasPreeditString())
2420 {
2421 const S32 preedit_pos = mPreeditPositions.front();
2422 mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
2423 mText.insert(preedit_pos, mPreeditOverwrittenWString);
2424 setCursor(preedit_pos);
2425
2426 mPreeditWString.clear();
2427 mPreeditOverwrittenWString.clear();
2428 mPreeditPositions.clear();
2429
2430 mKeystrokeTimer.reset();
2431 if (mKeystrokeCallback)
2432 {
2433 mKeystrokeCallback(this, mCallbackUserData);
2434 }
2435 }
2436}
2437
2438void LLLineEditor::updatePreedit(const LLWString &preedit_string,
2439 const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position)
2440{
2441 // Just in case.
2442 if (mReadOnly)
2443 {
2444 return;
2445 }
2446
2447 if (hasSelection())
2448 {
2449 if (hasPreeditString())
2450 {
2451 llwarns << "Preedit and selection!" << llendl;
2452 deselect();
2453 }
2454 else
2455 {
2456 deleteSelection();
2457 }
2458 }
2459
2460 S32 insert_preedit_at = getCursor();
2461 if (hasPreeditString())
2462 {
2463 insert_preedit_at = mPreeditPositions.front();
2464 //mText.replace(insert_preedit_at, mPreeditPositions.back() - insert_preedit_at, mPreeditOverwrittenWString);
2465 mText.erase(insert_preedit_at, mPreeditPositions.back() - insert_preedit_at);
2466 mText.insert(insert_preedit_at, mPreeditOverwrittenWString);
2467 }
2468
2469 mPreeditWString = preedit_string;
2470 mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
2471 S32 position = insert_preedit_at;
2472 for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++)
2473 {
2474 mPreeditPositions[i] = position;
2475 position += preedit_segment_lengths[i];
2476 }
2477 mPreeditPositions.back() = position;
2478 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
2479 {
2480 mPreeditOverwrittenWString.assign( LLWString( mText, insert_preedit_at, mPreeditWString.length() ) );
2481 mText.erase(insert_preedit_at, mPreeditWString.length());
2482 }
2483 else
2484 {
2485 mPreeditOverwrittenWString.clear();
2486 }
2487 mText.insert(insert_preedit_at, mPreeditWString);
2488
2489 mPreeditStandouts = preedit_standouts;
2490
2491 setCursor(position);
2492 setCursor(mPreeditPositions.front() + caret_position);
2493
2494 // Update of the preedit should be caused by some key strokes.
2495 mKeystrokeTimer.reset();
2496 if( mKeystrokeCallback )
2497 {
2498 mKeystrokeCallback( this, mCallbackUserData );
2499 }
2500}
2501
2502BOOL LLLineEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const
2503{
2504 if (control)
2505 {
2506 LLRect control_rect_screen;
2507 localRectToScreen(mRect, &control_rect_screen);
2508 LLUI::screenRectToGL(control_rect_screen, control);
2509 }
2510
2511 S32 preedit_left_column, preedit_right_column;
2512 if (hasPreeditString())
2513 {
2514 preedit_left_column = mPreeditPositions.front();
2515 preedit_right_column = mPreeditPositions.back();
2516 }
2517 else
2518 {
2519 preedit_left_column = preedit_right_column = getCursor();
2520 }
2521 if (preedit_right_column < mScrollHPos)
2522 {
2523 // This should not occure...
2524 return FALSE;
2525 }
2526
2527 const S32 query = (query_offset >= 0 ? preedit_left_column + query_offset : getCursor());
2528 if (query < mScrollHPos || query < preedit_left_column || query > preedit_right_column)
2529 {
2530 return FALSE;
2531 }
2532
2533 if (coord)
2534 {
2535 S32 query_local = findPixelNearestPos(query - getCursor());
2536 S32 query_screen_x, query_screen_y;
2537 localPointToScreen(query_local, mRect.getHeight() / 2, &query_screen_x, &query_screen_y);
2538 LLUI::screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
2539 }
2540
2541 if (bounds)
2542 {
2543 S32 preedit_left_local = findPixelNearestPos(llmax(preedit_left_column, mScrollHPos) - getCursor());
2544 S32 preedit_right_local = llmin(findPixelNearestPos(preedit_right_column - getCursor()), mRect.getWidth() - mBorderThickness);
2545 if (preedit_left_local > preedit_right_local)
2546 {
2547 // Is this condition possible?
2548 preedit_right_local = preedit_left_local;
2549 }
2550
2551 LLRect preedit_rect_local(preedit_left_local, mRect.getHeight(), preedit_right_local, 0);
2552 LLRect preedit_rect_screen;
2553 localRectToScreen(preedit_rect_local, &preedit_rect_screen);
2554 LLUI::screenRectToGL(preedit_rect_screen, bounds);
2555 }
2556
2557 return TRUE;
2558}
2559
2560void LLLineEditor::getPreeditRange(S32 *position, S32 *length) const
2561{
2562 if (hasPreeditString())
2563 {
2564 *position = mPreeditPositions.front();
2565 *length = mPreeditPositions.back() - mPreeditPositions.front();
2566 }
2567 else
2568 {
2569 *position = mCursorPos;
2570 *length = 0;
2571 }
2572}
2573
2574void LLLineEditor::getSelectionRange(S32 *position, S32 *length) const
2575{
2576 if (hasSelection())
2577 {
2578 *position = llmin(mSelectionStart, mSelectionEnd);
2579 *length = llabs(mSelectionStart - mSelectionEnd);
2580 }
2581 else
2582 {
2583 *position = mCursorPos;
2584 *length = 0;
2585 }
2586}
2587
2588void LLLineEditor::markAsPreedit(S32 position, S32 length)
2589{
2590 deselect();
2591 setCursor(position);
2592 if (hasPreeditString())
2593 {
2594 llwarns << "markAsPreedit invoked when hasPreeditString is true." << llendl;
2595 }
2596 mPreeditWString.assign( LLWString( mText.getWString(), position, length ) );
2597 if (length > 0)
2598 {
2599 mPreeditPositions.resize(2);
2600 mPreeditPositions[0] = position;
2601 mPreeditPositions[1] = position + length;
2602 mPreeditStandouts.resize(1);
2603 mPreeditStandouts[0] = FALSE;
2604 }
2605 else
2606 {
2607 mPreeditPositions.clear();
2608 mPreeditStandouts.clear();
2609 }
2610 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
2611 {
2612 mPreeditOverwrittenWString = mPreeditWString;
2613 }
2614 else
2615 {
2616 mPreeditOverwrittenWString.clear();
2617 }
2618}
2619
2620S32 LLLineEditor::getPreeditFontSize() const
2621{
2622 return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
2623}
2624
2625
2339LLSearchEditor::LLSearchEditor(const LLString& name, 2626LLSearchEditor::LLSearchEditor(const LLString& name,
2340 const LLRect& rect, 2627 const LLRect& rect,
2341 S32 max_length_bytes, 2628 S32 max_length_bytes,
diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h
index d4ebe3c..6d328e5 100644
--- a/linden/indra/llui/lllineeditor.h
+++ b/linden/indra/llui/lllineeditor.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -53,6 +53,8 @@
53#include "lluistring.h" 53#include "lluistring.h"
54#include "llviewborder.h" 54#include "llviewborder.h"
55 55
56#include "llpreeditor.h"
57
56class LLFontGL; 58class LLFontGL;
57class LLLineEditorRollback; 59class LLLineEditorRollback;
58class LLButton; 60class LLButton;
@@ -63,7 +65,7 @@ typedef BOOL (*LLLinePrevalidateFunc)(const LLWString &wstr);
63// Classes 65// Classes
64// 66//
65class LLLineEditor 67class LLLineEditor
66: public LLUICtrl, public LLEditMenuHandler 68: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor
67{ 69{
68 friend class LLLineEditorRollback; 70 friend class LLLineEditorRollback;
69 71
@@ -75,7 +77,7 @@ public:
75 S32 max_length_bytes = 254, 77 S32 max_length_bytes = 254,
76 void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL, 78 void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL,
77 void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL, 79 void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL,
78 void (*focus_lost_callback)(LLUICtrl* caller, void* user_data) = NULL, 80 void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data) = NULL,
79 void* userdata = NULL, 81 void* userdata = NULL,
80 LLLinePrevalidateFunc prevalidate_func = NULL, 82 LLLinePrevalidateFunc prevalidate_func = NULL,
81 LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN, 83 LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN,
@@ -120,6 +122,7 @@ public:
120 // view overrides 122 // view overrides
121 virtual void draw(); 123 virtual void draw();
122 virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE); 124 virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE);
125 virtual void onFocusReceived();
123 virtual void onFocusLost(); 126 virtual void onFocusLost();
124 virtual void setEnabled(BOOL enabled); 127 virtual void setEnabled(BOOL enabled);
125 128
@@ -146,7 +149,7 @@ public:
146 const LLWString& getWText() const { return mText.getWString(); } 149 const LLWString& getWText() const { return mText.getWString(); }
147 S32 getLength() const { return mText.length(); } 150 S32 getLength() const { return mText.length(); }
148 151
149 S32 getCursor() { return mCursorPos; } 152 S32 getCursor() const { return mCursorPos; }
150 void setCursor( S32 pos ); 153 void setCursor( S32 pos );
151 void setCursorToEnd(); 154 void setCursorToEnd();
152 155
@@ -177,13 +180,13 @@ public:
177 void setIgnoreTab(BOOL b) { mIgnoreTab = b; } 180 void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
178 void setPassDelete(BOOL b) { mPassDelete = b; } 181 void setPassDelete(BOOL b) { mPassDelete = b; }
179 182
180 void setDrawAsterixes(BOOL b) { mDrawAsterixes = b; } 183 void setDrawAsterixes(BOOL b);
181 184
182 // get the cursor position of the beginning/end of the prev/next word in the text 185 // get the cursor position of the beginning/end of the prev/next word in the text
183 S32 prevWordPos(S32 cursorPos) const; 186 S32 prevWordPos(S32 cursorPos) const;
184 S32 nextWordPos(S32 cursorPos) const; 187 S32 nextWordPos(S32 cursorPos) const;
185 188
186 BOOL hasSelection() { return (mSelectionStart != mSelectionEnd); } 189 BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); }
187 void startSelection(); 190 void startSelection();
188 void endSelection(); 191 void endSelection();
189 void extendSelection(S32 new_cursor_pos); 192 void extendSelection(S32 new_cursor_pos);
@@ -199,7 +202,7 @@ public:
199 202
200 static BOOL isPartOfWord(llwchar c); 203 static BOOL isPartOfWord(llwchar c);
201 // Prevalidation controls which keystrokes can affect the editor 204 // Prevalidation controls which keystrokes can affect the editor
202 void setPrevalidate( BOOL (*func)(const LLWString &) ) { mPrevalidateFunc = func; } 205 void setPrevalidate( BOOL (*func)(const LLWString &) );
203 static BOOL prevalidateFloat(const LLWString &str ); 206 static BOOL prevalidateFloat(const LLWString &str );
204 static BOOL prevalidateInt(const LLWString &str ); 207 static BOOL prevalidateInt(const LLWString &str );
205 static BOOL prevalidatePositiveS32(const LLWString &str); 208 static BOOL prevalidatePositiveS32(const LLWString &str);
@@ -221,7 +224,7 @@ protected:
221 void addChar(const llwchar c); 224 void addChar(const llwchar c);
222 void setCursorAtLocalPos(S32 local_mouse_x); 225 void setCursorAtLocalPos(S32 local_mouse_x);
223 226
224 S32 findPixelNearestPos(S32 cursor_offset = 0); 227 S32 findPixelNearestPos(S32 cursor_offset = 0) const;
225 void reportBadKeystroke(); 228 void reportBadKeystroke();
226 229
227 BOOL handleSpecialKey(KEY key, MASK mask); 230 BOOL handleSpecialKey(KEY key, MASK mask);
@@ -230,6 +233,19 @@ protected:
230 S32 handleCommitKey(KEY key, MASK mask); 233 S32 handleCommitKey(KEY key, MASK mask);
231 234
232protected: 235protected:
236 void updateAllowingLanguageInput();
237 BOOL hasPreeditString() const;
238 // Implementation (overrides) of LLPreeditor
239 virtual void resetPreedit();
240 virtual void updatePreedit(const LLWString &preedit_string,
241 const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position);
242 virtual void markAsPreedit(S32 position, S32 length);
243 virtual void getPreeditRange(S32 *position, S32 *length) const;
244 virtual void getSelectionRange(S32 *position, S32 *length) const;
245 virtual BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
246 virtual S32 getPreeditFontSize() const;
247
248protected:
233 LLUIString mText; // The string being edited. 249 LLUIString mText; // The string being edited.
234 LLString mPrevText; // Saved string for 'ESC' revert 250 LLString mPrevText; // Saved string for 'ESC' revert
235 LLUIString mLabel; // text label that is visible when no user text provided 251 LLUIString mLabel; // text label that is visible when no user text provided
@@ -241,8 +257,7 @@ protected:
241 257
242 LLViewBorder* mBorder; 258 LLViewBorder* mBorder;
243 const LLFontGL* mGLFont; 259 const LLFontGL* mGLFont;
244 S32 mMaxLengthChars; // Max number of characters 260 S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes
245 S32 mMaxLengthBytes; // Max length of the UTF8 string.
246 S32 mCursorPos; // I-beam is just after the mCursorPos-th character. 261 S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
247 S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling. 262 S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling.
248 LLFrameTimer mScrollTimer; 263 LLFrameTimer mScrollTimer;
@@ -288,6 +303,11 @@ protected:
288 BOOL mPassDelete; 303 BOOL mPassDelete;
289 304
290 BOOL mReadOnly; 305 BOOL mReadOnly;
306
307 LLWString mPreeditWString;
308 LLWString mPreeditOverwrittenWString;
309 std::vector<S32> mPreeditPositions;
310 LLPreeditor::standouts_t mPreeditStandouts;
291}; 311};
292 312
293 313
diff --git a/linden/indra/llui/llmemberlistener.h b/linden/indra/llui/llmemberlistener.h
index b4ee2f1..02aff17 100644
--- a/linden/indra/llui/llmemberlistener.h
+++ b/linden/indra/llui/llmemberlistener.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llmenugl.cpp b/linden/indra/llui/llmenugl.cpp
index 4afa6b9..a56b090 100644
--- a/linden/indra/llui/llmenugl.cpp
+++ b/linden/indra/llui/llmenugl.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -632,7 +632,7 @@ public:
632}; 632};
633 633
634LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const LLString &name ) : 634LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const LLString &name ) :
635 LLMenuItemGL( SEPARATOR_NAME, SEPARATOR_LABEL ) 635 LLMenuItemGL( name, SEPARATOR_LABEL )
636{ 636{
637} 637}
638 638
@@ -2832,7 +2832,7 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
2832 while(1) 2832 while(1)
2833 { 2833 {
2834 // skip separators and disabled items 2834 // skip separators and disabled items
2835 if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getName() != SEPARATOR_NAME) 2835 if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getType() != SEPARATOR_NAME)
2836 { 2836 {
2837 if (cur_item) 2837 if (cur_item)
2838 { 2838 {
@@ -4514,7 +4514,7 @@ BOOL LLMenuHolderGL::hideMenus()
4514 } 4514 }
4515 //if (gFocusMgr.childHasKeyboardFocus(this)) 4515 //if (gFocusMgr.childHasKeyboardFocus(this))
4516 //{ 4516 //{
4517 // gFocusMgr.setKeyboardFocus(NULL, NULL); 4517 // gFocusMgr.setKeyboardFocus(NULL);
4518 //} 4518 //}
4519 4519
4520 return menu_visible; 4520 return menu_visible;
@@ -4599,6 +4599,7 @@ void LLTearOffMenu::onFocusReceived()
4599 break; 4599 break;
4600 } 4600 }
4601 } 4601 }
4602 LLFloater::onFocusReceived();
4602} 4603}
4603 4604
4604void LLTearOffMenu::onFocusLost() 4605void LLTearOffMenu::onFocusLost()
diff --git a/linden/indra/llui/llmenugl.h b/linden/indra/llui/llmenugl.h
index 21594f6..9274101 100644
--- a/linden/indra/llui/llmenugl.h
+++ b/linden/indra/llui/llmenugl.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llmodaldialog.cpp b/linden/indra/llui/llmodaldialog.cpp
index 72a7fcb..ff4858f 100644
--- a/linden/indra/llui/llmodaldialog.cpp
+++ b/linden/indra/llui/llmodaldialog.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -70,6 +70,16 @@ LLModalDialog::~LLModalDialog()
70 } 70 }
71} 71}
72 72
73// virtual
74void LLModalDialog::open() /* Flawfinder: ignore */
75{
76 // SJB: Hack! Make sure we don't ever host a modal dialog
77 LLMultiFloater* thost = LLFloater::sHostp;
78 LLFloater::sHostp = NULL;
79 LLFloater::open();
80 LLFloater::sHostp = thost;
81}
82
73void LLModalDialog::reshape(S32 width, S32 height, BOOL called_from_parent) 83void LLModalDialog::reshape(S32 width, S32 height, BOOL called_from_parent)
74{ 84{
75 LLFloater::reshape(width, height, called_from_parent); 85 LLFloater::reshape(width, height, called_from_parent);
@@ -287,7 +297,7 @@ void LLModalDialog::onAppFocusLost()
287 297
288 if( gFocusMgr.childHasKeyboardFocus( instance ) ) 298 if( gFocusMgr.childHasKeyboardFocus( instance ) )
289 { 299 {
290 gFocusMgr.setKeyboardFocus( NULL, NULL ); 300 gFocusMgr.setKeyboardFocus( NULL );
291 } 301 }
292 } 302 }
293} 303}
diff --git a/linden/indra/llui/llmodaldialog.h b/linden/indra/llui/llmodaldialog.h
index 1529ac3..342a0f6 100644
--- a/linden/indra/llui/llmodaldialog.h
+++ b/linden/indra/llui/llmodaldialog.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -47,6 +47,8 @@ public:
47 LLModalDialog( const LLString& title, S32 width, S32 height, BOOL modal = true ); 47 LLModalDialog( const LLString& title, S32 width, S32 height, BOOL modal = true );
48 /*virtual*/ ~LLModalDialog(); 48 /*virtual*/ ~LLModalDialog();
49 49
50 /*virtual*/ void open(); /* Flawfinder: ignore */
51
50 /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = 1); 52 /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = 1);
51 53
52 /*virtual*/ void startModal(); 54 /*virtual*/ void startModal();
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp
index 2c37dfd..af8aa21 100644
--- a/linden/indra/llui/llpanel.cpp
+++ b/linden/indra/llui/llpanel.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -64,7 +64,6 @@ LLPanel::panel_map_t LLPanel::sPanelMap;
64LLPanel::alert_queue_t LLPanel::sAlertQueue; 64LLPanel::alert_queue_t LLPanel::sAlertQueue;
65 65
66const S32 RESIZE_BAR_OVERLAP = 1; 66const S32 RESIZE_BAR_OVERLAP = 1;
67const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT;
68 67
69void LLPanel::init() 68void LLPanel::init()
70{ 69{
@@ -88,6 +87,7 @@ LLPanel::LLPanel()
88: mRectControl() 87: mRectControl()
89{ 88{
90 init(); 89 init();
90 setName("panel");
91} 91}
92 92
93LLPanel::LLPanel(const LLString& name) 93LLPanel::LLPanel(const LLString& name)
@@ -124,6 +124,7 @@ LLPanel::LLPanel(const LLString& name, const LLString& rect_control, BOOL border
124void LLPanel::addBorder(LLViewBorder::EBevel border_bevel, 124void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
125 LLViewBorder::EStyle border_style, S32 border_thickness) 125 LLViewBorder::EStyle border_style, S32 border_thickness)
126{ 126{
127 removeBorder();
127 mBorder = new LLViewBorder( "panel border", 128 mBorder = new LLViewBorder( "panel border",
128 LLRect(0, mRect.getHeight(), mRect.getWidth(), 0), 129 LLRect(0, mRect.getHeight(), mRect.getWidth(), 0),
129 border_bevel, border_style, border_thickness ); 130 border_bevel, border_style, border_thickness );
@@ -339,11 +340,6 @@ void LLPanel::addCtrl( LLUICtrl* ctrl, S32 tab_group)
339 mLastTabGroup = tab_group; 340 mLastTabGroup = tab_group;
340 341
341 LLView::addCtrl(ctrl, tab_group); 342 LLView::addCtrl(ctrl, tab_group);
342 // propagate chrome to children only if they have not been flagged as chrome
343 if (!ctrl->getIsChrome())
344 {
345 ctrl->setIsChrome(getIsChrome());
346 }
347} 343}
348 344
349void LLPanel::addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group) 345void LLPanel::addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group)
@@ -351,22 +347,12 @@ void LLPanel::addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group)
351 mLastTabGroup = tab_group; 347 mLastTabGroup = tab_group;
352 348
353 LLView::addCtrlAtEnd(ctrl, tab_group); 349 LLView::addCtrlAtEnd(ctrl, tab_group);
354 if (!ctrl->getIsChrome())
355 {
356 ctrl->setIsChrome(getIsChrome());
357 }
358} 350}
359 351
360BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) 352BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
361{ 353{
362 BOOL handled = FALSE; 354 BOOL handled = FALSE;
363 355
364 if( getVisible() && getEnabled() && gFocusMgr.childHasKeyboardFocus(this) && KEY_ESCAPE == key )
365 {
366 gFocusMgr.setKeyboardFocus(NULL, NULL);
367 return TRUE;
368 }
369
370 if( getVisible() && getEnabled() && 356 if( getVisible() && getEnabled() &&
371 gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent ) 357 gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent )
372 { 358 {
@@ -472,7 +458,7 @@ void LLPanel::setFocus(BOOL b)
472 { 458 {
473 if( this == gFocusMgr.getKeyboardFocus() ) 459 if( this == gFocusMgr.getKeyboardFocus() )
474 { 460 {
475 gFocusMgr.setKeyboardFocus( NULL, NULL ); 461 gFocusMgr.setKeyboardFocus( NULL );
476 } 462 }
477 else 463 else
478 { 464 {
@@ -595,7 +581,8 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
595 { 581 {
596 LLRect rect; 582 LLRect rect;
597 createRect(node, rect, parent, LLRect()); 583 createRect(node, rect, parent, LLRect());
598 panelp = new LLPanel(name, rect); 584 // create a new panel without a border, by default
585 panelp = new LLPanel(name, rect, FALSE);
599 panelp->initPanelXML(node, parent, factory); 586 panelp->initPanelXML(node, parent, factory);
600 // preserve panel's width and height, but override the location 587 // preserve panel's width and height, but override the location
601 const LLRect& panelrect = panelp->getRect(); 588 const LLRect& panelrect = panelp->getRect();
@@ -608,12 +595,13 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
608 { 595 {
609 panelp->initPanelXML(node, parent, factory); 596 panelp->initPanelXML(node, parent, factory);
610 } 597 }
598
611 return panelp; 599 return panelp;
612} 600}
613 601
614BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) 602BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
615{ 603{
616 LLString name("panel"); 604 LLString name = getName();
617 node->getAttributeString("name", name); 605 node->getAttributeString("name", name);
618 setName(name); 606 setName(name);
619 607
@@ -628,13 +616,15 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
628 616
629 if (!xml_filename.empty()) 617 if (!xml_filename.empty())
630 { 618 {
631 // Preserve postion of embedded panel but allow panel to dictate width/height
632 LLRect rect(getRect());
633 didPost = factory->buildPanel(this, xml_filename, NULL); 619 didPost = factory->buildPanel(this, xml_filename, NULL);
634 S32 w = getRect().getWidth(); 620
635 S32 h = getRect().getHeight(); 621 LLRect new_rect = getRect();
636 rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h); 622 // override rectangle with embedding parameters as provided
637 setRect(rect); 623 createRect(node, new_rect, parent);
624 setOrigin(new_rect.mLeft, new_rect.mBottom);
625 reshape(new_rect.getWidth(), new_rect.getHeight());
626 // optionally override follows flags from including nodes
627 parseFollowsFlags(node);
638 } 628 }
639 else 629 else
640 { 630 {
@@ -678,7 +668,7 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
678 initFromXML(node, parent); 668 initFromXML(node, parent);
679 669
680 /////// Border attributes /////// 670 /////// Border attributes ///////
681 BOOL border = FALSE; 671 BOOL border = mBorder != NULL;
682 node->getAttributeBOOL("border", border); 672 node->getAttributeBOOL("border", border);
683 if (border) 673 if (border)
684 { 674 {
@@ -706,24 +696,24 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
706 } 696 }
707 697
708 /////// Background attributes /////// 698 /////// Background attributes ///////
709 BOOL background_visible = FALSE; 699 BOOL background_visible = mBgVisible;
710 node->getAttributeBOOL("background_visible", background_visible); 700 node->getAttributeBOOL("background_visible", background_visible);
711 setBackgroundVisible(background_visible); 701 setBackgroundVisible(background_visible);
712 702
713 BOOL background_opaque = FALSE; 703 BOOL background_opaque = mBgOpaque;
714 node->getAttributeBOOL("background_opaque", background_opaque); 704 node->getAttributeBOOL("background_opaque", background_opaque);
715 setBackgroundOpaque(background_opaque); 705 setBackgroundOpaque(background_opaque);
716 706
717 LLColor4 color; 707 LLColor4 color;
718 color = LLUI::sColorsGroup->getColor( "FocusBackgroundColor" ); 708 color = mBgColorOpaque;
719 LLUICtrlFactory::getAttributeColor(node,"bg_opaque_color", color); 709 LLUICtrlFactory::getAttributeColor(node,"bg_opaque_color", color);
720 setBackgroundColor(color); 710 setBackgroundColor(color);
721 711
722 color = LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" ); 712 color = mBgColorAlpha;
723 LLUICtrlFactory::getAttributeColor(node,"bg_alpha_color", color); 713 LLUICtrlFactory::getAttributeColor(node,"bg_alpha_color", color);
724 setTransparentColor(color); 714 setTransparentColor(color);
725 715
726 LLString label; 716 LLString label = getLabel();
727 node->getAttributeString("label", label); 717 node->getAttributeString("label", label);
728 setLabel(label); 718 setLabel(label);
729} 719}
@@ -853,12 +843,12 @@ BOOL LLPanel::childHasFocus(const LLString& id)
853} 843}
854 844
855 845
856void LLPanel::childSetFocusChangedCallback(const LLString& id, void (*cb)(LLUICtrl*, void*)) 846void LLPanel::childSetFocusChangedCallback(const LLString& id, void (*cb)(LLFocusableElement*, void*), void* user_data)
857{ 847{
858 LLUICtrl* child = (LLUICtrl*)getChildByName(id, true); 848 LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
859 if (child) 849 if (child)
860 { 850 {
861 child->setFocusChangedCallback(cb); 851 child->setFocusChangedCallback(cb, user_data);
862 } 852 }
863} 853}
864 854
@@ -1165,11 +1155,12 @@ void LLPanel::storeRectControl()
1165// 1155//
1166struct LLLayoutStack::LLEmbeddedPanel 1156struct LLLayoutStack::LLEmbeddedPanel
1167{ 1157{
1168 LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize) : 1158 LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) :
1169 mPanel(panelp), 1159 mPanel(panelp),
1170 mMinWidth(min_width), 1160 mMinWidth(min_width),
1171 mMinHeight(min_height), 1161 mMinHeight(min_height),
1172 mAutoResize(auto_resize), 1162 mAutoResize(auto_resize),
1163 mUserResize(user_resize),
1173 mOrientation(orientation), 1164 mOrientation(orientation),
1174 mVisibleAmt(1.f) // default to fully visible 1165 mVisibleAmt(1.f) // default to fully visible
1175 { 1166 {
@@ -1194,10 +1185,18 @@ struct LLLayoutStack::LLEmbeddedPanel
1194 } 1185 }
1195 } 1186 }
1196 1187
1188 ~LLEmbeddedPanel()
1189 {
1190 // probably not necessary, but...
1191 delete mResizeBar;
1192 mResizeBar = NULL;
1193 }
1194
1197 LLPanel* mPanel; 1195 LLPanel* mPanel;
1198 S32 mMinWidth; 1196 S32 mMinWidth;
1199 S32 mMinHeight; 1197 S32 mMinHeight;
1200 BOOL mAutoResize; 1198 BOOL mAutoResize;
1199 BOOL mUserResize;
1201 LLResizeBar* mResizeBar; 1200 LLResizeBar* mResizeBar;
1202 eLayoutOrientation mOrientation; 1201 eLayoutOrientation mOrientation;
1203 F32 mVisibleAmt; 1202 F32 mVisibleAmt;
@@ -1206,36 +1205,40 @@ struct LLLayoutStack::LLEmbeddedPanel
1206LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) : 1205LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
1207 mOrientation(orientation), 1206 mOrientation(orientation),
1208 mMinWidth(0), 1207 mMinWidth(0),
1209 mMinHeight(0) 1208 mMinHeight(0),
1209 mPanelSpacing(RESIZE_BAR_HEIGHT)
1210{ 1210{
1211} 1211}
1212 1212
1213LLLayoutStack::~LLLayoutStack() 1213LLLayoutStack::~LLLayoutStack()
1214{ 1214{
1215 std::for_each(mPanels.begin(), mPanels.end(), DeletePointer());
1215} 1216}
1216 1217
1217void LLLayoutStack::draw() 1218void LLLayoutStack::draw()
1218{ 1219{
1219 updateLayout(); 1220 updateLayout();
1220 { 1221 {
1221 // clip if outside nominal bounds
1222 LLLocalClipRect clip(getLocalRect(), mRect.getWidth() > mMinWidth || mRect.getHeight() > mMinHeight);
1223 e_panel_list_t::iterator panel_it; 1222 e_panel_list_t::iterator panel_it;
1224 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) 1223 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1225 { 1224 {
1225 // clip to layout rectangle, not bounding rectangle
1226 LLRect clip_rect = (*panel_it)->mPanel->getRect(); 1226 LLRect clip_rect = (*panel_it)->mPanel->getRect();
1227 // scale clipping rectangle by visible amount 1227 // scale clipping rectangle by visible amount
1228 if (mOrientation == HORIZONTAL) 1228 if (mOrientation == HORIZONTAL)
1229 { 1229 {
1230 clip_rect.mRight = clip_rect.mLeft + llround(clip_rect.getWidth() * (*panel_it)->mVisibleAmt); 1230 clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
1231 } 1231 }
1232 else 1232 else
1233 { 1233 {
1234 clip_rect.mBottom = clip_rect.mTop - llround(clip_rect.getHeight() * (*panel_it)->mVisibleAmt); 1234 clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
1235 } 1235 }
1236 LLLocalClipRect clip(clip_rect, (*panel_it)->mVisibleAmt < 1.f); 1236
1237 LLPanel* panelp = (*panel_it)->mPanel;
1238
1239 LLLocalClipRect clip(clip_rect);
1237 // only force drawing invisible children if visible amount is non-zero 1240 // only force drawing invisible children if visible amount is non-zero
1238 drawChild((*panel_it)->mPanel, 0, 0, (*panel_it)->mVisibleAmt > 0.f); 1241 drawChild(panelp, 0, 0, !clip_rect.isNull());
1239 } 1242 }
1240 } 1243 }
1241} 1244}
@@ -1250,17 +1253,13 @@ void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
1250 delete embedded_panelp; 1253 delete embedded_panelp;
1251 } 1254 }
1252 1255
1256 // need to update resizebars
1257
1253 calcMinExtents(); 1258 calcMinExtents();
1254 1259
1255 LLView::removeCtrl(ctrl); 1260 LLView::removeCtrl(ctrl);
1256} 1261}
1257 1262
1258void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
1259{
1260 LLView::reshape(width, height, called_from_parent);
1261 //updateLayout();
1262}
1263
1264LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const 1263LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
1265{ 1264{
1266 LLXMLNodePtr node = LLView::getXML(); 1265 LLXMLNodePtr node = LLView::getXML();
@@ -1290,6 +1289,14 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
1290 1289
1291 LLLayoutStack* layout_stackp = new LLLayoutStack(orientation); 1290 LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
1292 1291
1292 node->getAttributeS32("border_size", layout_stackp->mPanelSpacing);
1293 // don't allow negative spacing values
1294 layout_stackp->mPanelSpacing = llmax(layout_stackp->mPanelSpacing, 0);
1295
1296 LLString name("stack");
1297 node->getAttributeString("name", name);
1298
1299 layout_stackp->setName(name);
1293 layout_stackp->initFromXML(node, parent); 1300 layout_stackp->initFromXML(node, parent);
1294 1301
1295 LLXMLNodePtr child; 1302 LLXMLNodePtr child;
@@ -1300,16 +1307,18 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
1300 S32 min_width = 0; 1307 S32 min_width = 0;
1301 S32 min_height = 0; 1308 S32 min_height = 0;
1302 BOOL auto_resize = TRUE; 1309 BOOL auto_resize = TRUE;
1310 BOOL user_resize = TRUE;
1303 1311
1304 child->getAttributeS32("min_width", min_width); 1312 child->getAttributeS32("min_width", min_width);
1305 child->getAttributeS32("min_height", min_height); 1313 child->getAttributeS32("min_height", min_height);
1306 child->getAttributeBOOL("auto_resize", auto_resize); 1314 child->getAttributeBOOL("auto_resize", auto_resize);
1315 child->getAttributeBOOL("user_resize", user_resize);
1307 1316
1308 LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory); 1317 LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
1309 if (panelp) 1318 if (panelp)
1310 { 1319 {
1311 panelp->setFollowsNone(); 1320 panelp->setFollowsNone();
1312 layout_stackp->addPanel(panelp, min_width, min_height, auto_resize); 1321 layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
1313 } 1322 }
1314 } 1323 }
1315 } 1324 }
@@ -1327,11 +1336,36 @@ S32 LLLayoutStack::getMinHeight()
1327 return mMinHeight; 1336 return mMinHeight;
1328} 1337}
1329 1338
1330void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index) 1339S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
1340{
1341 // if we are spanning our children (crude upward propagation of size)
1342 // then don't enforce our size on our children
1343 if (mOrientation == HORIZONTAL)
1344 {
1345 cur_height = llmax(mMinHeight, mRect.getHeight());
1346 }
1347
1348 return cur_height;
1349}
1350
1351S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
1331{ 1352{
1332 LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize); 1353 // if we are spanning our children (crude upward propagation of size)
1354 // then don't enforce our size on our children
1355 if (mOrientation == VERTICAL)
1356 {
1357 cur_width = llmax(mMinWidth, mRect.getWidth());
1358 }
1359
1360 return cur_width;
1361}
1362
1363void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index)
1364{
1365 LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
1333 1366
1334 mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel); 1367 mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
1368
1335 addChild(panel); 1369 addChild(panel);
1336 addChild(embedded_panel->mResizeBar); 1370 addChild(embedded_panel->mResizeBar);
1337 1371
@@ -1339,29 +1373,15 @@ void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL
1339 // with a bit of overlap 1373 // with a bit of overlap
1340 for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) 1374 for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1341 { 1375 {
1342 e_panel_list_t::iterator next_it = panel_it;
1343 ++next_it;
1344
1345 LLResizeBar* resize_barp = (*panel_it)->mResizeBar; 1376 LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
1346 sendChildToFront(resize_barp); 1377 sendChildToFront(resize_barp);
1347 // last resize bar is disabled, since its not between any two panels
1348 if ( next_it == mPanels.end() )
1349 {
1350 resize_barp->setEnabled(FALSE);
1351 }
1352 else
1353 {
1354 resize_barp->setEnabled(TRUE);
1355 }
1356 } 1378 }
1357 1379
1358 //updateLayout();
1359} 1380}
1360 1381
1361void LLLayoutStack::removePanel(LLPanel* panel) 1382void LLLayoutStack::removePanel(LLPanel* panel)
1362{ 1383{
1363 removeChild(panel); 1384 removeChild(panel);
1364 //updateLayout();
1365} 1385}
1366 1386
1367void LLLayoutStack::updateLayout(BOOL force_resize) 1387void LLLayoutStack::updateLayout(BOOL force_resize)
@@ -1369,11 +1389,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1369 calcMinExtents(); 1389 calcMinExtents();
1370 1390
1371 // calculate current extents 1391 // calculate current extents
1372 S32 cur_width = 0; 1392 S32 total_width = 0;
1373 S32 cur_height = 0; 1393 S32 total_height = 0;
1374 1394
1375 const F32 ANIM_OPEN_TIME = 0.02f; 1395 const F32 ANIM_OPEN_TIME = 0.02f;
1376 const F32 ANIM_CLOSE_TIME = 0.02f; 1396 const F32 ANIM_CLOSE_TIME = 0.03f;
1377 1397
1378 e_panel_list_t::iterator panel_it; 1398 e_panel_list_t::iterator panel_it;
1379 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) 1399 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
@@ -1395,23 +1415,22 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1395 (*panel_it)->mVisibleAmt = 0.f; 1415 (*panel_it)->mVisibleAmt = 0.f;
1396 } 1416 }
1397 } 1417 }
1418
1398 if (mOrientation == HORIZONTAL) 1419 if (mOrientation == HORIZONTAL)
1399 { 1420 {
1400 // all panels get expanded to max of all the minimum dimensions 1421 total_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
1401 cur_height = llmax(mMinHeight, panelp->getRect().getHeight()); 1422 // want n-1 panel gaps for n panels
1402 cur_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt); 1423 if (panel_it != mPanels.begin())
1403 if (panel_it != mPanels.end())
1404 { 1424 {
1405 cur_width += PANEL_STACK_GAP; 1425 total_width += mPanelSpacing;
1406 } 1426 }
1407 } 1427 }
1408 else //VERTICAL 1428 else //VERTICAL
1409 { 1429 {
1410 cur_width = llmax(mMinWidth, panelp->getRect().getWidth()); 1430 total_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
1411 cur_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt); 1431 if (panel_it != mPanels.begin())
1412 if (panel_it != mPanels.end())
1413 { 1432 {
1414 cur_height += PANEL_STACK_GAP; 1433 total_height += mPanelSpacing;
1415 } 1434 }
1416 } 1435 }
1417 } 1436 }
@@ -1457,11 +1476,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1457 S32 pixels_to_distribute; 1476 S32 pixels_to_distribute;
1458 if (mOrientation == HORIZONTAL) 1477 if (mOrientation == HORIZONTAL)
1459 { 1478 {
1460 pixels_to_distribute = mRect.getWidth() - cur_width; 1479 pixels_to_distribute = mRect.getWidth() - total_width;
1461 } 1480 }
1462 else //VERTICAL 1481 else //VERTICAL
1463 { 1482 {
1464 pixels_to_distribute = mRect.getHeight() - cur_height; 1483 pixels_to_distribute = mRect.getHeight() - total_height;
1465 } 1484 }
1466 1485
1467 S32 cur_x = 0; 1486 S32 cur_x = 0;
@@ -1474,7 +1493,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1474 S32 cur_width = panelp->getRect().getWidth(); 1493 S32 cur_width = panelp->getRect().getWidth();
1475 S32 cur_height = panelp->getRect().getHeight(); 1494 S32 cur_height = panelp->getRect().getHeight();
1476 S32 new_width = llmax((*panel_it)->mMinWidth, cur_width); 1495 S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
1477 S32 new_height = llmax((*panel_it)->mMinHeight, cur_height); 1496 S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
1478 1497
1479 S32 delta_size = 0; 1498 S32 delta_size = 0;
1480 1499
@@ -1494,11 +1513,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1494 // grow all elements equally 1513 // grow all elements equally
1495 delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels); 1514 delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
1496 } 1515 }
1497 new_width = llmax((*panel_it)->mMinWidth, panelp->getRect().getWidth() + delta_size); 1516 new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
1498 } 1517 }
1499 else 1518 else
1500 { 1519 {
1501 new_width = llmax(mMinWidth, mRect.getWidth()); 1520 new_width = getDefaultWidth(new_width);
1502 } 1521 }
1503 1522
1504 if (mOrientation == VERTICAL) 1523 if (mOrientation == VERTICAL)
@@ -1512,22 +1531,22 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1512 { 1531 {
1513 delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels); 1532 delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
1514 } 1533 }
1515 new_height = llmax((*panel_it)->mMinHeight, panelp->getRect().getHeight() + delta_size); 1534 new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
1516 } 1535 }
1517 else 1536 else
1518 { 1537 {
1519 new_height = llmax(mMinHeight, mRect.getHeight()); 1538 new_height = getDefaultHeight(new_height);
1520 } 1539 }
1521 } 1540 }
1522 else // don't resize 1541 else
1523 { 1542 {
1524 if (mOrientation == HORIZONTAL) 1543 if (mOrientation == HORIZONTAL)
1525 { 1544 {
1526 new_height = llmax(mMinHeight, mRect.getHeight()); 1545 new_height = getDefaultHeight(new_height);
1527 } 1546 }
1528 else // VERTICAL 1547 else // VERTICAL
1529 { 1548 {
1530 new_width = llmax(mMinWidth, mRect.getWidth()); 1549 new_width = getDefaultWidth(new_width);
1531 } 1550 }
1532 } 1551 }
1533 1552
@@ -1542,22 +1561,22 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1542 if (mOrientation == HORIZONTAL) 1561 if (mOrientation == HORIZONTAL)
1543 { 1562 {
1544 resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP; 1563 resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
1545 resize_bar_rect.mRight = panel_rect.mRight + PANEL_STACK_GAP + RESIZE_BAR_OVERLAP; 1564 resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + RESIZE_BAR_OVERLAP;
1546 } 1565 }
1547 else 1566 else
1548 { 1567 {
1549 resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP; 1568 resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
1550 resize_bar_rect.mBottom = panel_rect.mBottom - PANEL_STACK_GAP - RESIZE_BAR_OVERLAP; 1569 resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - RESIZE_BAR_OVERLAP;
1551 } 1570 }
1552 (*panel_it)->mResizeBar->setRect(resize_bar_rect); 1571 (*panel_it)->mResizeBar->setRect(resize_bar_rect);
1553 1572
1554 if (mOrientation == HORIZONTAL) 1573 if (mOrientation == HORIZONTAL)
1555 { 1574 {
1556 cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP; 1575 cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + mPanelSpacing;
1557 } 1576 }
1558 else //VERTICAL 1577 else //VERTICAL
1559 { 1578 {
1560 cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP; 1579 cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + mPanelSpacing;
1561 } 1580 }
1562 } 1581 }
1563 1582
@@ -1569,29 +1588,38 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1569 1588
1570 if (mOrientation == HORIZONTAL) 1589 if (mOrientation == HORIZONTAL)
1571 { 1590 {
1572 (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinWidth, (*panel_it)->mMinWidth + shrink_headroom_total); 1591 (*panel_it)->mResizeBar->setResizeLimits(
1592 (*panel_it)->mMinWidth,
1593 (*panel_it)->mMinWidth + shrink_headroom_total);
1573 } 1594 }
1574 else //VERTICAL 1595 else //VERTICAL
1575 { 1596 {
1576 (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinHeight, (*panel_it)->mMinHeight + shrink_headroom_total); 1597 (*panel_it)->mResizeBar->setResizeLimits(
1598 (*panel_it)->mMinHeight,
1599 (*panel_it)->mMinHeight + shrink_headroom_total);
1577 } 1600 }
1578 // hide resize bars for invisible panels 1601
1579 (*panel_it)->mResizeBar->setVisible(panelp->getVisible()); 1602 // toggle resize bars based on panel visibility, resizability, etc
1580 if (panelp->getVisible()) 1603 BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
1604 (*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
1605
1606 if (resize_bar_enabled)
1581 { 1607 {
1582 last_resize_bar = (*panel_it)->mResizeBar; 1608 last_resize_bar = (*panel_it)->mResizeBar;
1583 } 1609 }
1584 } 1610 }
1585 1611
1586 // hide last resize bar as there is nothing past it 1612 // hide last resize bar as there is nothing past it
1613 // resize bars need to be in between two resizable panels
1587 if (last_resize_bar) 1614 if (last_resize_bar)
1588 { 1615 {
1589 last_resize_bar->setVisible(FALSE); 1616 last_resize_bar->setVisible(FALSE);
1590 } 1617 }
1591 1618
1592 // not enough room to fit existing contents 1619 // not enough room to fit existing contents
1593 if (!force_resize && 1620 if (!force_resize
1594 ((cur_y != -PANEL_STACK_GAP) || (cur_x != mRect.getWidth() + PANEL_STACK_GAP))) 1621 && ((cur_y != -mPanelSpacing)
1622 || (cur_x != mRect.getWidth() + mPanelSpacing)))
1595 { 1623 {
1596 // do another layout pass with all stacked elements contributing 1624 // do another layout pass with all stacked elements contributing
1597 // even those that don't usually resize 1625 // even those that don't usually resize
@@ -1623,20 +1651,22 @@ void LLLayoutStack::calcMinExtents()
1623 { 1651 {
1624 if (mOrientation == HORIZONTAL) 1652 if (mOrientation == HORIZONTAL)
1625 { 1653 {
1626 mMinHeight = llmax(mMinHeight, (*panel_it)->mMinHeight); 1654 mMinHeight = llmax( mMinHeight,
1655 (*panel_it)->mMinHeight);
1627 mMinWidth += (*panel_it)->mMinWidth; 1656 mMinWidth += (*panel_it)->mMinWidth;
1628 if (panel_it != mPanels.begin()) 1657 if (panel_it != mPanels.begin())
1629 { 1658 {
1630 mMinWidth += PANEL_STACK_GAP; 1659 mMinWidth += mPanelSpacing;
1631 } 1660 }
1632 } 1661 }
1633 else //VERTICAL 1662 else //VERTICAL
1634 { 1663 {
1635 mMinWidth = llmax(mMinWidth, (*panel_it)->mMinWidth); 1664 mMinWidth = llmax( mMinWidth,
1665 (*panel_it)->mMinWidth);
1636 mMinHeight += (*panel_it)->mMinHeight; 1666 mMinHeight += (*panel_it)->mMinHeight;
1637 if (panel_it != mPanels.begin()) 1667 if (panel_it != mPanels.begin())
1638 { 1668 {
1639 mMinHeight += PANEL_STACK_GAP; 1669 mMinHeight += mPanelSpacing;
1640 } 1670 }
1641 } 1671 }
1642 } 1672 }
diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h
index d706fc8..bcbda2c 100644
--- a/linden/indra/llui/llpanel.h
+++ b/linden/indra/llui/llpanel.h
@@ -13,12 +13,12 @@
13 * ("GPL"), unless you have obtained a separate licensing agreement 13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of 14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or 15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2 16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 * 17 *
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at http://secondlife.com/developers/opensource/flossexception 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * 22 *
23 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -173,7 +173,7 @@ public:
173 // LLUICtrl 173 // LLUICtrl
174 void childSetFocus(const LLString& id, BOOL focus = TRUE); 174 void childSetFocus(const LLString& id, BOOL focus = TRUE);
175 BOOL childHasFocus(const LLString& id); 175 BOOL childHasFocus(const LLString& id);
176 void childSetFocusChangedCallback(const LLString& id, void (*cb)(LLUICtrl*, void*)); 176 void childSetFocusChangedCallback(const LLString& id, void (*cb)(LLFocusableElement*, void*), void* user_data = NULL);
177 177
178 void childSetCommitCallback(const LLString& id, void (*cb)(LLUICtrl*, void*), void* userdata = NULL ); 178 void childSetCommitCallback(const LLString& id, void (*cb)(LLUICtrl*, void*), void* userdata = NULL );
179 void childSetDoubleClickCallback(const LLString& id, void (*cb)(void*), void* userdata = NULL ); 179 void childSetDoubleClickCallback(const LLString& id, void (*cb)(void*), void* userdata = NULL );
@@ -277,9 +277,9 @@ public:
277 virtual ~LLLayoutStack(); 277 virtual ~LLLayoutStack();
278 278
279 /*virtual*/ void draw(); 279 /*virtual*/ void draw();
280 /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
281 /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const; 280 /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
282 /*virtual*/ void removeCtrl(LLUICtrl* ctrl); 281 /*virtual*/ void removeCtrl(LLUICtrl* ctrl);
282
283 virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LAYOUT_STACK; } 283 virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LAYOUT_STACK; }
284 virtual LLString getWidgetTag() const { return LL_LAYOUT_STACK_TAG; } 284 virtual LLString getWidgetTag() const { return LL_LAYOUT_STACK_TAG; }
285 285
@@ -288,7 +288,7 @@ public:
288 S32 getMinWidth(); 288 S32 getMinWidth();
289 S32 getMinHeight(); 289 S32 getMinHeight();
290 290
291 void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index = S32_MAX); 291 void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index = S32_MAX);
292 void removePanel(LLPanel* panel); 292 void removePanel(LLPanel* panel);
293 void updateLayout(BOOL force_resize = FALSE); 293 void updateLayout(BOOL force_resize = FALSE);
294 294
@@ -299,6 +299,8 @@ protected:
299 void calcMinExtents(); 299 void calcMinExtents();
300 S32 getMinStackSize(); 300 S32 getMinStackSize();
301 S32 getCurStackSize(); 301 S32 getCurStackSize();
302 S32 getDefaultHeight(S32 cur_height);
303 S32 getDefaultWidth(S32 cur_width);
302 304
303protected: 305protected:
304 eLayoutOrientation mOrientation; 306 eLayoutOrientation mOrientation;
@@ -308,6 +310,7 @@ protected:
308 310
309 S32 mMinWidth; 311 S32 mMinWidth;
310 S32 mMinHeight; 312 S32 mMinHeight;
313 S32 mPanelSpacing;
311}; 314};
312 315
313#endif 316#endif
diff --git a/linden/indra/llui/llradiogroup.cpp b/linden/indra/llui/llradiogroup.cpp
index cfb11cd..dad1941 100644
--- a/linden/indra/llui/llradiogroup.cpp
+++ b/linden/indra/llui/llradiogroup.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -473,7 +473,7 @@ BOOL LLRadioGroup::setSelectedByValue(LLSD value, BOOL selected)
473 return FALSE; 473 return FALSE;
474} 474}
475 475
476LLSD LLRadioGroup::getSimpleSelectedValue() 476LLSD LLRadioGroup::getSelectedValue()
477{ 477{
478 return getValue(); 478 return getValue();
479} 479}
diff --git a/linden/indra/llui/llradiogroup.h b/linden/indra/llui/llradiogroup.h
index 1eb6bb7..e0a4168 100644
--- a/linden/indra/llui/llradiogroup.h
+++ b/linden/indra/llui/llradiogroup.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -122,7 +122,7 @@ public:
122 /*virtual*/ BOOL setCurrentByID( const LLUUID& id ); 122 /*virtual*/ BOOL setCurrentByID( const LLUUID& id );
123 /*virtual*/ LLUUID getCurrentID(); // LLUUID::null if no items in menu 123 /*virtual*/ LLUUID getCurrentID(); // LLUUID::null if no items in menu
124 /*virtual*/ BOOL setSelectedByValue(LLSD value, BOOL selected); 124 /*virtual*/ BOOL setSelectedByValue(LLSD value, BOOL selected);
125 /*virtual*/ LLSD getSimpleSelectedValue(); 125 /*virtual*/ LLSD getSelectedValue();
126 /*virtual*/ BOOL isSelected(LLSD value); 126 /*virtual*/ BOOL isSelected(LLSD value);
127 /*virtual*/ BOOL operateOnSelection(EOperation op); 127 /*virtual*/ BOOL operateOnSelection(EOperation op);
128 /*virtual*/ BOOL operateOnAll(EOperation op); 128 /*virtual*/ BOOL operateOnAll(EOperation op);
diff --git a/linden/indra/llui/llresizebar.cpp b/linden/indra/llui/llresizebar.cpp
index 8ac165c..e6ce03b 100644
--- a/linden/indra/llui/llresizebar.cpp
+++ b/linden/indra/llui/llresizebar.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llresizebar.h b/linden/indra/llui/llresizebar.h
index b9ad124..11fca9d 100644
--- a/linden/indra/llui/llresizebar.h
+++ b/linden/indra/llui/llresizebar.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llresizehandle.cpp b/linden/indra/llui/llresizehandle.cpp
index 36eb3b1..739d583 100644
--- a/linden/indra/llui/llresizehandle.cpp
+++ b/linden/indra/llui/llresizehandle.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -60,7 +60,7 @@ LLResizeHandle::LLResizeHandle( const LLString& name, const LLRect& rect, S32 mi
60 if( RIGHT_BOTTOM == mCorner) 60 if( RIGHT_BOTTOM == mCorner)
61 { 61 {
62 LLUUID image_id(LLUI::sConfigGroup->getString("UIImgResizeBottomRightUUID")); 62 LLUUID image_id(LLUI::sConfigGroup->getString("UIImgResizeBottomRightUUID"));
63 mImage = LLUI::sImageProvider->getUIImageByID(image_id); 63 mImage = LLUI::sImageProvider->getImageByID(image_id);
64 } 64 }
65 65
66 switch( mCorner ) 66 switch( mCorner )
diff --git a/linden/indra/llui/llresizehandle.h b/linden/indra/llui/llresizehandle.h
index 90c96d7..863ce70 100644
--- a/linden/indra/llui/llresizehandle.h
+++ b/linden/indra/llui/llresizehandle.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llresmgr.cpp b/linden/indra/llui/llresmgr.cpp
index 1922f3f..83ad440 100644
--- a/linden/indra/llui/llresmgr.cpp
+++ b/linden/indra/llui/llresmgr.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llresmgr.h b/linden/indra/llui/llresmgr.h
index 9f29282..b851795 100644
--- a/linden/indra/llui/llresmgr.h
+++ b/linden/indra/llui/llresmgr.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llrootview.cpp b/linden/indra/llui/llrootview.cpp
index 57fe3ee..1580f99 100644
--- a/linden/indra/llui/llrootview.cpp
+++ b/linden/indra/llui/llrootview.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llrootview.h b/linden/indra/llui/llrootview.h
index 0b6fea3..13037f0 100644
--- a/linden/indra/llui/llrootview.h
+++ b/linden/indra/llui/llrootview.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llscrollbar.cpp b/linden/indra/llui/llscrollbar.cpp
index 34acf03..ec46551 100644
--- a/linden/indra/llui/llscrollbar.cpp
+++ b/linden/indra/llui/llscrollbar.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -159,30 +159,50 @@ void LLScrollbar::setDocParams( S32 size, S32 pos )
159 159
160void LLScrollbar::setDocPos(S32 pos) 160void LLScrollbar::setDocPos(S32 pos)
161{ 161{
162 mDocPos = llclamp( pos, 0, getDocPosMax() ); 162 if (pos != mDocPos)
163 mDocChanged = TRUE; 163 {
164 mDocPos = llclamp( pos, 0, getDocPosMax() );
165 mDocChanged = TRUE;
164 166
165 updateThumbRect(); 167 updateThumbRect();
168 }
166} 169}
167 170
168void LLScrollbar::setDocSize(S32 size) 171void LLScrollbar::setDocSize(S32 size)
169{ 172{
170 mDocSize = size; 173 if (size != mDocSize)
171 mDocPos = llclamp( mDocPos, 0, getDocPosMax() ); 174 {
172 mDocChanged = TRUE; 175 mDocSize = size;
176 mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
177 mDocChanged = TRUE;
173 178
174 updateThumbRect(); 179 updateThumbRect();
180 }
175} 181}
176 182
177void LLScrollbar::setPageSize( S32 page_size ) 183void LLScrollbar::setPageSize( S32 page_size )
178{ 184{
179 mPageSize = page_size; 185 if (page_size != mPageSize)
180 mDocPos = llclamp( mDocPos, 0, getDocPosMax() ); 186 {
181 mDocChanged = TRUE; 187 mPageSize = page_size;
188 mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
189 mDocChanged = TRUE;
182 190
183 updateThumbRect(); 191 updateThumbRect();
192 }
193}
194
195BOOL LLScrollbar::isAtBeginning()
196{
197 return mDocPos == 0;
198}
199
200BOOL LLScrollbar::isAtEnd()
201{
202 return mDocPos == getDocPosMax();
184} 203}
185 204
205
186void LLScrollbar::updateThumbRect() 206void LLScrollbar::updateThumbRect()
187{ 207{
188// llassert( 0 <= mDocSize ); 208// llassert( 0 <= mDocSize );
@@ -479,7 +499,7 @@ void LLScrollbar::draw()
479 // Draw background and thumb. 499 // Draw background and thumb.
480 LLUUID rounded_rect_image_id; 500 LLUUID rounded_rect_image_id;
481 rounded_rect_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga")); 501 rounded_rect_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
482 LLImageGL* rounded_rect_imagep = LLUI::sImageProvider->getUIImageByID(rounded_rect_image_id); 502 LLImageGL* rounded_rect_imagep = LLUI::sImageProvider->getImageByID(rounded_rect_image_id);
483 503
484 if (!rounded_rect_imagep) 504 if (!rounded_rect_imagep)
485 { 505 {
diff --git a/linden/indra/llui/llscrollbar.h b/linden/indra/llui/llscrollbar.h
index 1bfd0f6..464c9c1 100644
--- a/linden/indra/llui/llscrollbar.h
+++ b/linden/indra/llui/llscrollbar.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -88,6 +88,9 @@ public:
88 void setDocPos( S32 pos ); 88 void setDocPos( S32 pos );
89 S32 getDocPos() { return mDocPos; } 89 S32 getDocPos() { return mDocPos; }
90 90
91 BOOL isAtBeginning();
92 BOOL isAtEnd();
93
91 // How many "lines" of the "document" is can appear on a page. 94 // How many "lines" of the "document" is can appear on a page.
92 void setPageSize( S32 page_size ); 95 void setPageSize( S32 page_size );
93 S32 getPageSize() { return mPageSize; } 96 S32 getPageSize() { return mPageSize; }
diff --git a/linden/indra/llui/llscrollcontainer.cpp b/linden/indra/llui/llscrollcontainer.cpp
index 414a2d7..8c8b40c 100644
--- a/linden/indra/llui/llscrollcontainer.cpp
+++ b/linden/indra/llui/llscrollcontainer.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -394,33 +394,29 @@ BOOL LLScrollableContainerView::handleDragAndDrop(S32 x, S32 y, MASK mask,
394 394
395BOOL LLScrollableContainerView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect) 395BOOL LLScrollableContainerView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect)
396{ 396{
397 if( getVisible() && pointInView(x,y) ) 397 S32 local_x, local_y;
398 for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
398 { 399 {
399 S32 local_x, local_y; 400 local_x = x - mScrollbar[i]->getRect().mLeft;
400 for( S32 i = 0; i < SCROLLBAR_COUNT; i++ ) 401 local_y = y - mScrollbar[i]->getRect().mBottom;
402 if( mScrollbar[i]->handleToolTip(local_x, local_y, msg, sticky_rect) )
401 { 403 {
402 local_x = x - mScrollbar[i]->getRect().mLeft; 404 return TRUE;
403 local_y = y - mScrollbar[i]->getRect().mBottom;
404 if( mScrollbar[i]->handleToolTip(local_x, local_y, msg, sticky_rect) )
405 {
406 return TRUE;
407 }
408 } 405 }
409 // Handle 'child' view. 406 }
410 if( mScrolledView ) 407 // Handle 'child' view.
408 if( mScrolledView )
409 {
410 local_x = x - mScrolledView->getRect().mLeft;
411 local_y = y - mScrolledView->getRect().mBottom;
412 if( mScrolledView->handleToolTip(local_x, local_y, msg, sticky_rect) )
411 { 413 {
412 local_x = x - mScrolledView->getRect().mLeft; 414 return TRUE;
413 local_y = y - mScrolledView->getRect().mBottom;
414 if( mScrolledView->handleToolTip(local_x, local_y, msg, sticky_rect) )
415 {
416 return TRUE;
417 }
418 } 415 }
419
420 // Opaque
421 return TRUE;
422 } 416 }
423 return FALSE; 417
418 // Opaque
419 return TRUE;
424} 420}
425 421
426void LLScrollableContainerView::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) 422void LLScrollableContainerView::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar )
diff --git a/linden/indra/llui/llscrollcontainer.h b/linden/indra/llui/llscrollcontainer.h
index 682cade..fb7198c 100644
--- a/linden/indra/llui/llscrollcontainer.h
+++ b/linden/indra/llui/llscrollcontainer.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llscrollingpanellist.cpp b/linden/indra/llui/llscrollingpanellist.cpp
index 5f91644..a9d538e 100644
--- a/linden/indra/llui/llscrollingpanellist.cpp
+++ b/linden/indra/llui/llscrollingpanellist.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llscrollingpanellist.h b/linden/indra/llui/llscrollingpanellist.h
index 77002d0..84dc7f9 100644
--- a/linden/indra/llui/llscrollingpanellist.h
+++ b/linden/indra/llui/llscrollingpanellist.h
@@ -11,12 +11,12 @@
11 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of 12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or 13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2 14 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
15 * 15 *
16 * There are special exceptions to the terms and conditions of the GPL as 16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception 17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or 18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception 19 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20 * 20 *
21 * By copying, modifying or distributing this software, you acknowledge 21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above, 22 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp
index b80787f..d65ebd2 100644
--- a/linden/indra/llui/llscrolllistctrl.cpp
+++ b/linden/indra/llui/llscrolllistctrl.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -61,73 +61,101 @@ const S32 LIST_SNAP_PADDING = 5;
61// local structures & classes. 61// local structures & classes.
62struct SortScrollListItem 62struct SortScrollListItem
63{ 63{
64 SortScrollListItem(const S32 sort_col, BOOL sort_ascending) 64 SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders)
65 { 65 : mSortOrders(sort_orders)
66 mSortCol = sort_col; 66 {}
67 mSortAscending = sort_ascending;
68 }
69 67
70 bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2) 68 bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
71 { 69 {
72 const LLScrollListCell *cell1; 70 if ( mSortOrders.empty() ) return true;
73 const LLScrollListCell *cell2; 71
74 72 const LLScrollListCell *cell1 = NULL;
75 cell1 = i1->getColumn(mSortCol); 73 const LLScrollListCell *cell2 = NULL;
76 cell2 = i2->getColumn(mSortCol);
77 74
78 S32 order = 1; 75 sort_order_t::const_reverse_iterator end_it = mSortOrders.rend();
79 if (!mSortAscending) 76 sort_order_t::const_reverse_iterator it;
77
78 // sort over all columns in order specified by mSortOrders
79 S32 sort_result = 0;
80 for (it = mSortOrders.rbegin(); it != end_it; ++it)
80 { 81 {
81 order = -1; 82 S32 col_idx = it->first;
82 } 83 BOOL sort_ascending = it->second;
83 84
84 BOOL retval = FALSE; 85 cell1 = i1->getColumn(col_idx);
86 cell2 = i2->getColumn(col_idx);
87 // ascending or descending sort for this column?
88 S32 order = 1;
89 if (!sort_ascending)
90 {
91 order = -1;
92 }
85 93
86 if (cell1 && cell2) 94 if (cell1 && cell2)
87 { 95 {
88 retval = ((order * LLString::compareDict(cell1->getText(), cell2->getText())) < 0); 96 sort_result = (order * LLString::compareDict(cell1->getValue().asString(), cell2->getValue().asString()));
97 if (sort_result != 0)
98 {
99 // we have a sort order!
100 break;
101 }
102 }
89 } 103 }
90 104
91 return (retval ? TRUE : FALSE); 105 return sort_result < 0;
92 } 106 }
93 107
94protected: 108 typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
95 S32 mSortCol; 109 const sort_order_t& mSortOrders;
96 S32 mSortAscending;
97}; 110};
98 111
99 112
100
101// 113//
102// LLScrollListIcon 114// LLScrollListIcon
103// 115//
104LLScrollListIcon::LLScrollListIcon(LLImageGL* icon, S32 width, LLUUID image_id) 116LLScrollListIcon::LLScrollListIcon(const LLUUID& icon_id, S32 width)
105 : mIcon(icon), 117 : LLScrollListCell(width),
106 mImageUUID(image_id.asString()), 118 mColor(LLColor4::white),
107 mColor(LLColor4::white) 119 mImageUUID(icon_id)
108{ 120{
109 if (width) 121 // don't use default image specified by LLUUID::null, use no image in that case
110 { 122 mIcon = icon_id.isNull() ? NULL : LLUI::sImageProvider->getImageByID(icon_id);
111 mWidth = width;
112 }
113 else
114 {
115 mWidth = icon->getWidth();
116 }
117} 123}
118 124
119LLScrollListIcon::~LLScrollListIcon() 125LLScrollListIcon::~LLScrollListIcon()
120{ 126{
121} 127}
122 128
129void LLScrollListIcon::setValue(LLSD value)
130{
131 mImageUUID = value.asUUID();
132 // don't use default image specified by LLUUID::null, use no image in that case
133 mIcon = mImageUUID.isNull() ? NULL : LLUI::sImageProvider->getImageByID(mImageUUID);
134}
135
136
123void LLScrollListIcon::setColor(const LLColor4& color) 137void LLScrollListIcon::setColor(const LLColor4& color)
124{ 138{
125 mColor = color; 139 mColor = color;
126} 140}
127 141
128void LLScrollListIcon::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const 142S32 LLScrollListIcon::getWidth() const
143{
144 // if no specified fix width, use width of icon
145 if (mWidth == 0)
146 {
147 return mIcon->getWidth();
148 }
149 return mWidth;
150}
151
152
153void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_color) const
129{ 154{
130 gl_draw_image(0, 0, mIcon, mColor); 155 if (mIcon)
156 {
157 gl_draw_image(0, 0, mIcon, mColor);
158 }
131} 159}
132 160
133// 161//
@@ -155,32 +183,32 @@ LLScrollListCheck::~LLScrollListCheck()
155 delete mCheckBox; 183 delete mCheckBox;
156} 184}
157 185
158void LLScrollListCheck::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const 186void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const
159{ 187{
160 mCheckBox->draw(); 188 mCheckBox->draw();
161
162} 189}
163 190
164BOOL LLScrollListCheck::handleClick() 191BOOL LLScrollListCheck::handleClick()
165{ 192{
166 if ( mCheckBox->getEnabled() ) 193 if (mCheckBox->getEnabled())
167 { 194 {
168 LLCheckBoxCtrl::onButtonPress(mCheckBox); 195 mCheckBox->toggle();
169 } 196 }
197 // don't change selection when clicking on embedded checkbox
170 return TRUE; 198 return TRUE;
171} 199}
172 200
173// 201//
174// LLScrollListSeparator 202// LLScrollListSeparator
175// 203//
176LLScrollListSeparator::LLScrollListSeparator(S32 width) : mWidth(width) 204LLScrollListSeparator::LLScrollListSeparator(S32 width) : LLScrollListCell(width)
177{ 205{
178} 206}
179 207
180void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const 208void LLScrollListSeparator::draw(const LLColor4& color, const LLColor4& highlight_color) const
181{ 209{
182 //*FIXME: use dynamic item heights and make separators narrow, and inactive 210 //*FIXME: use dynamic item heights and make separators narrow, and inactive
183 gl_line_2d(5, 8, llmax(5, width - 5), 8, color); 211 gl_line_2d(5, 8, llmax(5, getWidth() - 5), 8, color);
184} 212}
185 213
186// 214//
@@ -189,11 +217,11 @@ void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const
189U32 LLScrollListText::sCount = 0; 217U32 LLScrollListText::sCount = 0;
190 218
191LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible) 219LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible)
192: mText( text ), 220: LLScrollListCell(width),
221 mText( text ),
193 mFont( font ), 222 mFont( font ),
194 mFontStyle( font_style ), 223 mFontStyle( font_style ),
195 mFontAlignment( font_alignment ), 224 mFontAlignment( font_alignment ),
196 mWidth( width ),
197 mVisible( visible ), 225 mVisible( visible ),
198 mHighlightCount( 0 ), 226 mHighlightCount( 0 ),
199 mHighlightOffset( 0 ) 227 mHighlightOffset( 0 )
@@ -213,7 +241,7 @@ LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font,
213 // initialize rounded rect image 241 // initialize rounded rect image
214 if (!mRoundedRectImage) 242 if (!mRoundedRectImage)
215 { 243 {
216 mRoundedRectImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("rounded_square.tga"))); 244 mRoundedRectImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("rounded_square.tga")));
217 } 245 }
218} 246}
219 247
@@ -223,6 +251,12 @@ LLScrollListText::~LLScrollListText()
223 delete mColor; 251 delete mColor;
224} 252}
225 253
254S32 LLScrollListText::getContentWidth() const
255{
256 return mFont->getWidth(mText.getString());
257}
258
259
226void LLScrollListText::setColor(const LLColor4& color) 260void LLScrollListText::setColor(const LLColor4& color)
227{ 261{
228 if (!mColor) 262 if (!mColor)
@@ -237,14 +271,8 @@ void LLScrollListText::setText(const LLStringExplicit& text)
237 mText = text; 271 mText = text;
238} 272}
239 273
240void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const 274void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_color) const
241{ 275{
242 // If the user has specified a small minimum width, use that.
243 if (mWidth > 0 && mWidth < width)
244 {
245 width = mWidth;
246 }
247
248 const LLColor4* display_color; 276 const LLColor4* display_color;
249 if (mColor) 277 if (mColor)
250 { 278 {
@@ -266,10 +294,10 @@ void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLCol
266 left = mFont->getWidth(mText.getString(), 0, mHighlightOffset); 294 left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
267 break; 295 break;
268 case LLFontGL::RIGHT: 296 case LLFontGL::RIGHT:
269 left = width - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX); 297 left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
270 break; 298 break;
271 case LLFontGL::HCENTER: 299 case LLFontGL::HCENTER:
272 left = (width - mFont->getWidth(mText.getString())) / 2; 300 left = (getWidth() - mFont->getWidth(mText.getString())) / 2;
273 break; 301 break;
274 } 302 }
275 gl_segmented_rect_2d_tex(left - 2, 303 gl_segmented_rect_2d_tex(left - 2,
@@ -291,10 +319,10 @@ void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLCol
291 start_x = 0.f; 319 start_x = 0.f;
292 break; 320 break;
293 case LLFontGL::RIGHT: 321 case LLFontGL::RIGHT:
294 start_x = (F32)width; 322 start_x = (F32)getWidth();
295 break; 323 break;
296 case LLFontGL::HCENTER: 324 case LLFontGL::HCENTER:
297 start_x = (F32)width * 0.5f; 325 start_x = (F32)getWidth() * 0.5f;
298 break; 326 break;
299 } 327 }
300 mFont->render(mText.getWString(), 0, 328 mFont->render(mText.getWString(), 0,
@@ -304,8 +332,10 @@ void LLScrollListText::drawToWidth(S32 width, const LLColor4& color, const LLCol
304 LLFontGL::BOTTOM, 332 LLFontGL::BOTTOM,
305 mFontStyle, 333 mFontStyle,
306 string_chars, 334 string_chars,
307 width, 335 getWidth(),
308 &right_x, FALSE, TRUE); 336 &right_x,
337 FALSE,
338 TRUE);
309} 339}
310 340
311 341
@@ -314,31 +344,6 @@ LLScrollListItem::~LLScrollListItem()
314 std::for_each(mColumns.begin(), mColumns.end(), DeletePointer()); 344 std::for_each(mColumns.begin(), mColumns.end(), DeletePointer());
315} 345}
316 346
317BOOL LLScrollListItem::handleClick(S32 x, S32 y, MASK mask)
318{
319 BOOL handled = FALSE;
320
321 S32 left = 0;
322 S32 right = 0;
323 S32 width = 0;
324
325 std::vector<LLScrollListCell *>::iterator iter = mColumns.begin();
326 std::vector<LLScrollListCell *>::iterator end = mColumns.end();
327 for ( ; iter != end; ++iter)
328 {
329 width = (*iter)->getWidth();
330 right += width;
331 if (left <= x && x < right )
332 {
333 handled = (*iter)->handleClick();
334 break;
335 }
336
337 left += width;
338 }
339 return handled;
340}
341
342void LLScrollListItem::setNumColumns(S32 columns) 347void LLScrollListItem::setNumColumns(S32 columns)
343{ 348{
344 S32 prev_columns = mColumns.size(); 349 S32 prev_columns = mColumns.size();
@@ -375,7 +380,7 @@ LLString LLScrollListItem::getContentsCSV()
375 S32 count = getNumColumns(); 380 S32 count = getNumColumns();
376 for (S32 i=0; i<count; ++i) 381 for (S32 i=0; i<count; ++i)
377 { 382 {
378 ret += getColumn(i)->getText(); 383 ret += getColumn(i)->getValue().asString();
379 if (i < count-1) 384 if (i < count-1)
380 { 385 {
381 ret += ", "; 386 ret += ", ";
@@ -385,17 +390,107 @@ LLString LLScrollListItem::getContentsCSV()
385 return ret; 390 return ret;
386} 391}
387 392
393void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
394{
395 // draw background rect
396 LLRect bg_rect = rect;
397 // pad background rectangle to separate it from contents
398 bg_rect.stretch(LIST_BORDER_PAD, 0);
399 {
400 LLGLSNoTexture no_texture;
401 glColor4fv(bg_color.mV);
402 gl_rect_2d( bg_rect );
403 }
404
405 S32 cur_x = rect.mLeft;
406 S32 num_cols = getNumColumns();
407 S32 cur_col = 0;
408
409 for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col))
410 {
411 // Two ways a cell could be hidden
412 if (cell->getWidth() < 0
413 || !cell->getVisible()) continue;
414
415 LLUI::pushMatrix();
416 {
417 LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f);
418
419 cell->draw( fg_color, highlight_color );
420 }
421 LLUI::popMatrix();
422
423 cur_x += cell->getWidth() + column_padding;
424 }
425}
426
427
388void LLScrollListItem::setEnabled(BOOL b) 428void LLScrollListItem::setEnabled(BOOL b)
389{ 429{
390 if (b != mEnabled) 430 mEnabled = b;
431}
432
433//---------------------------------------------------------------------------
434// LLScrollListItemComment
435//---------------------------------------------------------------------------
436LLScrollListItemComment::LLScrollListItemComment(const LLString& comment_string, const LLColor4& color)
437: LLScrollListItem(FALSE),
438 mColor(color)
439{
440 addColumn( comment_string, gResMgr->getRes( LLFONT_SANSSERIF_SMALL ) );
441}
442
443void LLScrollListItemComment::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
444{
445 LLScrollListCell* cell = getColumn(0);
446 if (cell)
447 {
448 // Two ways a cell could be hidden
449 if (cell->getWidth() < 0
450 || !cell->getVisible()) return;
451
452 LLUI::pushMatrix();
453 {
454 LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f);
455
456 // force first cell to be width of entire item
457 cell->setWidth(rect.getWidth());
458 cell->draw( mColor, highlight_color );
459 }
460 LLUI::popMatrix();
461 }
462}
463
464//---------------------------------------------------------------------------
465// LLScrollListItemSeparator
466//---------------------------------------------------------------------------
467LLScrollListItemSeparator::LLScrollListItemSeparator()
468: LLScrollListItem(FALSE)
469{
470 LLScrollListSeparator* cell = new LLScrollListSeparator(0);
471 setNumColumns(1);
472 setColumn(0, cell);
473}
474
475void LLScrollListItemSeparator::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
476{
477 //TODO* move LLScrollListSeparator::draw into here and get rid of it
478 LLScrollListCell* cell = getColumn(0);
479 if (cell)
391 { 480 {
392 std::vector<LLScrollListCell *>::iterator iter = mColumns.begin(); 481 // Two ways a cell could be hidden
393 std::vector<LLScrollListCell *>::iterator end = mColumns.end(); 482 if (cell->getWidth() < 0
394 for ( ; iter != end; ++iter) 483 || !cell->getVisible()) return;
484
485 LLUI::pushMatrix();
395 { 486 {
396 (*iter)->setEnabled(b); 487 LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f);
488
489 // force first cell to be width of entire item
490 cell->setWidth(rect.getWidth());
491 cell->draw( fg_color, highlight_color );
397 } 492 }
398 mEnabled = b; 493 LLUI::popMatrix();
399 } 494 }
400} 495}
401 496
@@ -423,10 +518,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
423 mNeedsScroll(FALSE), 518 mNeedsScroll(FALSE),
424 mCanSelect(TRUE), 519 mCanSelect(TRUE),
425 mDisplayColumnHeaders(FALSE), 520 mDisplayColumnHeaders(FALSE),
426 mCollapseEmptyColumns(FALSE),
427 mIsPopup(FALSE),
428 mMaxItemCount(INT_MAX), 521 mMaxItemCount(INT_MAX),
429 //mItemCount(0), 522 mMaxContentWidth(0),
430 mBackgroundVisible( TRUE ), 523 mBackgroundVisible( TRUE ),
431 mDrawStripes(TRUE), 524 mDrawStripes(TRUE),
432 mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ), 525 mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ),
@@ -443,12 +536,9 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
443 mOnSortChangedCallback( NULL ), 536 mOnSortChangedCallback( NULL ),
444 mHighlightedItem(-1), 537 mHighlightedItem(-1),
445 mBorder(NULL), 538 mBorder(NULL),
446 mDefaultColumn("SIMPLE"),
447 mSearchColumn(0), 539 mSearchColumn(0),
448 mNumDynamicWidthColumns(0), 540 mNumDynamicWidthColumns(0),
449 mTotalStaticColumnWidth(0), 541 mTotalStaticColumnWidth(0),
450 mSortColumn(-1),
451 mSortAscending(TRUE),
452 mSorted(TRUE), 542 mSorted(TRUE),
453 mDirty(FALSE), 543 mDirty(FALSE),
454 mOriginalSelection(-1), 544 mOriginalSelection(-1),
@@ -457,7 +547,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
457 mItemListRect.setOriginAndSize( 547 mItemListRect.setOriginAndSize(
458 mBorderThickness + LIST_BORDER_PAD, 548 mBorderThickness + LIST_BORDER_PAD,
459 mBorderThickness + LIST_BORDER_PAD, 549 mBorderThickness + LIST_BORDER_PAD,
460 mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE, 550 mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ),
461 mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) ); 551 mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) );
462 552
463 updateLineHeight(); 553 updateLineHeight();
@@ -481,7 +571,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
481 mScrollbar->setFollowsTop(); 571 mScrollbar->setFollowsTop();
482 mScrollbar->setFollowsBottom(); 572 mScrollbar->setFollowsBottom();
483 mScrollbar->setEnabled( TRUE ); 573 mScrollbar->setEnabled( TRUE );
484 mScrollbar->setVisible( TRUE ); 574 // scrollbar is visible only when needed
575 mScrollbar->setVisible(FALSE);
485 addChild(mScrollbar); 576 addChild(mScrollbar);
486 577
487 // Border 578 // Border
@@ -539,7 +630,8 @@ void LLScrollListCtrl::clearRows()
539 630
540 mScrollLines = 0; 631 mScrollLines = 0;
541 mLastSelected = NULL; 632 mLastSelected = NULL;
542 updateMaxContentWidth(NULL); 633 calcMaxContentWidth(NULL);
634 updateLayout();
543 mDirty = FALSE; 635 mDirty = FALSE;
544} 636}
545 637
@@ -620,38 +712,64 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const
620 return ret; 712 return ret;
621} 713}
622 714
715// returns first matching item
716LLScrollListItem* LLScrollListCtrl::getItem(const LLSD& sd) const
717{
718 LLString string_val = sd.asString();
719
720 item_list::const_iterator iter;
721 for(iter = mItemList.begin(); iter != mItemList.end(); iter++)
722 {
723 LLScrollListItem* item = *iter;
724 // assumes string representation is good enough for comparison
725 if (item->getValue().asString() == string_val)
726 {
727 return item;
728 }
729 }
730 return NULL;
731}
732
623 733
624void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) 734void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
625{ 735{
626 S32 old_height = mRect.getHeight();
627 LLUICtrl::reshape( width, height, called_from_parent ); 736 LLUICtrl::reshape( width, height, called_from_parent );
628 737
629 S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0); 738 updateLayout();
739}
630 740
741void LLScrollListCtrl::updateLayout()
742{
743 // reserve room for column headers, if needed
744 S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
631 mItemListRect.setOriginAndSize( 745 mItemListRect.setOriginAndSize(
632 mBorderThickness + LIST_BORDER_PAD, 746 mBorderThickness + LIST_BORDER_PAD,
633 mBorderThickness + LIST_BORDER_PAD, 747 mBorderThickness + LIST_BORDER_PAD,
634 mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE, 748 mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ),
635 mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) - heading_size ); 749 mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) - heading_size );
636 750
751 // how many lines of content in a single "page"
637 mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0; 752 mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0;
638 if(old_height < height && getScrollPos() == mScrollbar->getDocPosMax()) 753 BOOL scrollbar_visible = getItemCount() > mPageLines;
754 if (scrollbar_visible)
639 { 755 {
640 setScrollPos(mScrollbar->getDocPosMax()); 756 // provide space on the right for scrollbar
757 mItemListRect.mRight = mRect.getWidth() - ( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE;
641 } 758 }
642 mScrollbar->setVisible(mPageLines < getItemCount()); 759
760 mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
643 mScrollbar->setPageSize( mPageLines ); 761 mScrollbar->setPageSize( mPageLines );
644 762 mScrollbar->setDocSize( getItemCount() );
763 mScrollbar->setVisible(scrollbar_visible);
764
645 updateColumns(); 765 updateColumns();
646} 766}
647 767
648// Attempt to size the control to show all items. 768// Attempt to size the control to show all items.
649// Do not make larger than width or height. 769// Do not make larger than width or height.
650void LLScrollListCtrl::arrange(S32 max_width, S32 max_height) 770void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)
651{ 771{
652 S32 height = mLineHeight * (getItemCount() + 1); 772 S32 height = llmin( getRequiredRect().getHeight(), max_height );
653 height = llmin( height, max_height );
654
655 S32 width = mRect.getWidth(); 773 S32 width = mRect.getWidth();
656 774
657 reshape( width, height ); 775 reshape( width, height );
@@ -660,14 +778,17 @@ void LLScrollListCtrl::arrange(S32 max_width, S32 max_height)
660 778
661LLRect LLScrollListCtrl::getRequiredRect() 779LLRect LLScrollListCtrl::getRequiredRect()
662{ 780{
663 S32 height = mLineHeight * (getItemCount() + 1); 781 S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
782 S32 height = (mLineHeight * getItemCount())
783 + (2 * ( mBorderThickness + LIST_BORDER_PAD ))
784 + heading_size;
664 S32 width = mRect.getWidth(); 785 S32 width = mRect.getWidth();
665 786
666 return LLRect(0, height, width, 0); 787 return LLRect(0, height, width, 0);
667} 788}
668 789
669 790
670BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos ) 791BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL requires_column )
671{ 792{
672 BOOL not_too_big = getItemCount() < mMaxItemCount; 793 BOOL not_too_big = getItemCount() < mMaxItemCount;
673 if (not_too_big) 794 if (not_too_big)
@@ -680,15 +801,22 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
680 break; 801 break;
681 802
682 case ADD_SORTED: 803 case ADD_SORTED:
683 if (mSortColumn == -1)
684 { 804 {
685 mSortColumn = 0; 805 // sort by column 0, in ascending order
686 mSortAscending = TRUE; 806 std::vector<sort_column_t> single_sort_column;
687 } 807 single_sort_column.push_back(std::make_pair(0, TRUE));
688 mItemList.push_back(item); 808
689 std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); 809 mItemList.push_back(item);
690 break; 810 std::stable_sort(
691 811 mItemList.begin(),
812 mItemList.end(),
813 SortScrollListItem(single_sort_column));
814
815 // ADD_SORTED just sorts by first column...
816 // this might not match user sort criteria, so flag list as being in unsorted state
817 setSorted(FALSE);
818 break;
819 }
692 case ADD_BOTTOM: 820 case ADD_BOTTOM:
693 mItemList.push_back(item); 821 mItemList.push_back(item);
694 setSorted(FALSE); 822 setSorted(FALSE);
@@ -701,34 +829,42 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos )
701 break; 829 break;
702 } 830 }
703 831
704 updateLineHeightInsert(item); 832 // create new column on demand
705 mPageLines = mLineHeight ? mItemListRect.getHeight() / mLineHeight : 0; 833 if (mColumns.empty() && requires_column)
706 BOOL scrollbar_visible = mPageLines < getItemCount();
707
708 if (scrollbar_visible != mScrollbar->getVisible())
709 { 834 {
710 mScrollbar->setVisible(mPageLines < getItemCount()); 835 LLSD new_column;
711 updateColumns(); 836 new_column["name"] = "default_column";
837 new_column["label"] = "";
838 new_column["dynamicwidth"] = TRUE;
839 addColumn(new_column);
712 } 840 }
713 mScrollbar->setPageSize( mPageLines );
714
715 mScrollbar->setDocSize( getItemCount() );
716 841
717 updateMaxContentWidth(item); 842 updateLineHeightInsert(item);
843 calcMaxContentWidth(item);
844
845 updateLayout();
718 } 846 }
719 847
720 return not_too_big; 848 return not_too_big;
721} 849}
722 850
723void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item) 851void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item)
724{ 852{
725 const S32 HEADING_TEXT_PADDING = 30; 853 const S32 HEADING_TEXT_PADDING = 30;
726 const S32 COLUMN_TEXT_PADDING = 20; 854 const S32 COLUMN_TEXT_PADDING = 20;
727 855
728 std::map<LLString, LLScrollListColumn>::iterator column_itor; 856 if (added_item == NULL)
729 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
730 { 857 {
731 LLScrollListColumn* column = &column_itor->second; 858 mMaxContentWidth = 0;
859 }
860
861 S32 item_content_width = 0;
862
863 ordered_columns_t::iterator column_itor;
864 for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor)
865 {
866 LLScrollListColumn* column = *column_itor;
867 if (!column) continue;
732 868
733 if (!added_item) 869 if (!added_item)
734 { 870 {
@@ -740,7 +876,7 @@ void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item)
740 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); 876 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
741 if (!cellp) continue; 877 if (!cellp) continue;
742 878
743 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); 879 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
744 } 880 }
745 } 881 }
746 else 882 else
@@ -748,9 +884,13 @@ void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item)
748 LLScrollListCell* cellp = added_item->getColumn(column->mIndex); 884 LLScrollListCell* cellp = added_item->getColumn(column->mIndex);
749 if (!cellp) continue; 885 if (!cellp) continue;
750 886
751 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); 887 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
752 } 888 }
889
890 item_content_width += column->mMaxContentWidth;
753 } 891 }
892
893 mMaxContentWidth = llmax(mMaxContentWidth, item_content_width);
754} 894}
755 895
756const S32 SCROLL_LIST_ROW_PAD = 2; 896const S32 SCROLL_LIST_ROW_PAD = 2;
@@ -789,7 +929,6 @@ void LLScrollListCtrl::updateColumns()
789 mColumnsIndexed.resize(mColumns.size()); 929 mColumnsIndexed.resize(mColumns.size());
790 930
791 std::map<LLString, LLScrollListColumn>::iterator column_itor; 931 std::map<LLString, LLScrollListColumn>::iterator column_itor;
792 bool first_dynamic = true;
793 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) 932 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
794 { 933 {
795 LLScrollListColumn *column = &column_itor->second; 934 LLScrollListColumn *column = &column_itor->second;
@@ -801,11 +940,6 @@ void LLScrollListCtrl::updateColumns()
801 else if (column->mDynamicWidth) 940 else if (column->mDynamicWidth)
802 { 941 {
803 new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; 942 new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
804 if(first_dynamic)
805 {
806 first_dynamic = false;
807 new_width += (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE);
808 }
809 } 943 }
810 944
811 if (new_width != column->mWidth) 945 if (new_width != column->mWidth)
@@ -854,48 +988,38 @@ void LLScrollListCtrl::updateColumns()
854 } 988 }
855 right = llmax(left, llmin(mItemListRect.getWidth(), right)); 989 right = llmax(left, llmin(mItemListRect.getWidth(), right));
856 S32 header_width = right - left; 990 S32 header_width = right - left;
857 991
858 last_header->reshape(header_width, mHeadingHeight); 992 last_header->reshape(header_width, mHeadingHeight);
859 last_header->translate(left - last_header->getRect().mLeft, top - last_header->getRect().mBottom); 993 last_header->translate(
994 left - last_header->getRect().mLeft,
995 top - last_header->getRect().mBottom);
860 last_header->setVisible(mDisplayColumnHeaders && header_width > 0); 996 last_header->setVisible(mDisplayColumnHeaders && header_width > 0);
861 left = right; 997 left = right;
862 } 998 }
863 } 999 }
864 1000
865 // expand last column header we encountered to full list width 1001 // expand last column header we encountered to full list width
866
867 if (last_header) 1002 if (last_header)
868 { 1003 {
869 S32 header_strip_width = mItemListRect.getWidth() + (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE); 1004 S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft);
870 S32 new_width = llmax(0, mItemListRect.mLeft + header_strip_width - last_header->getRect().mLeft);
871 last_header->reshape(new_width, last_header->getRect().getHeight()); 1005 last_header->reshape(new_width, last_header->getRect().getHeight());
872 last_header->setVisible(mDisplayColumnHeaders && new_width > 0); 1006 last_header->setVisible(mDisplayColumnHeaders && new_width > 0);
873 } 1007 }
874
875} 1008}
876 1009
877void LLScrollListCtrl::setDisplayHeading(BOOL display) 1010void LLScrollListCtrl::setDisplayHeading(BOOL display)
878{ 1011{
879 mDisplayColumnHeaders = display; 1012 mDisplayColumnHeaders = display;
880 1013
881 updateColumns(); 1014 updateLayout();
882
883 setHeadingHeight(mHeadingHeight);
884} 1015}
885 1016
886void LLScrollListCtrl::setHeadingHeight(S32 heading_height) 1017void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
887{ 1018{
888 mHeadingHeight = heading_height; 1019 mHeadingHeight = heading_height;
889 1020
890 reshape(mRect.getWidth(), mRect.getHeight()); 1021 updateLayout();
891
892 // Resize
893 mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
894}
895 1022
896void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse)
897{
898 mCollapseEmptyColumns = collapse;
899} 1023}
900 1024
901BOOL LLScrollListCtrl::selectFirstItem() 1025BOOL LLScrollListCtrl::selectFirstItem()
@@ -934,6 +1058,8 @@ BOOL LLScrollListCtrl::selectFirstItem()
934 1058
935BOOL LLScrollListCtrl::selectNthItem( S32 target_index ) 1059BOOL LLScrollListCtrl::selectNthItem( S32 target_index )
936{ 1060{
1061 if (mItemList.empty()) return FALSE;
1062
937 // Deselects all other items 1063 // Deselects all other items
938 BOOL success = FALSE; 1064 BOOL success = FALSE;
939 S32 index = 0; 1065 S32 index = 0;
@@ -1012,7 +1138,32 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index)
1012 } 1138 }
1013 delete itemp; 1139 delete itemp;
1014 mItemList.erase(mItemList.begin() + target_index); 1140 mItemList.erase(mItemList.begin() + target_index);
1015 updateMaxContentWidth(NULL); 1141 calcMaxContentWidth(NULL);
1142}
1143
1144//FIXME: refactor item deletion
1145void LLScrollListCtrl::deleteItems(const LLSD& sd)
1146{
1147 item_list::iterator iter;
1148 for (iter = mItemList.begin(); iter < mItemList.end(); )
1149 {
1150 LLScrollListItem* itemp = *iter;
1151 if (itemp->getValue().asString() == sd.asString())
1152 {
1153 if (itemp == mLastSelected)
1154 {
1155 mLastSelected = NULL;
1156 }
1157 delete itemp;
1158 mItemList.erase(iter++);
1159 }
1160 else
1161 {
1162 iter++;
1163 }
1164 }
1165
1166 calcMaxContentWidth(NULL);
1016} 1167}
1017 1168
1018void LLScrollListCtrl::deleteSelectedItems() 1169void LLScrollListCtrl::deleteSelectedItems()
@@ -1032,7 +1183,7 @@ void LLScrollListCtrl::deleteSelectedItems()
1032 } 1183 }
1033 } 1184 }
1034 mLastSelected = NULL; 1185 mLastSelected = NULL;
1035 updateMaxContentWidth(NULL); 1186 calcMaxContentWidth(NULL);
1036} 1187}
1037 1188
1038void LLScrollListCtrl::highlightNthItem(S32 target_index) 1189void LLScrollListCtrl::highlightNthItem(S32 target_index)
@@ -1108,7 +1259,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
1108 1259
1109 if (!getFirstSelected()) 1260 if (!getFirstSelected())
1110 { 1261 {
1111 selectFirstItem(); 1262 // select last item
1263 selectNthItem(getItemCount() - 1);
1112 } 1264 }
1113 else 1265 else
1114 { 1266 {
@@ -1130,7 +1282,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
1130 break; 1282 break;
1131 } 1283 }
1132 1284
1133 prev_item = cur_item; 1285 // don't allow navigation to disabled elements
1286 prev_item = cur_item->getEnabled() ? cur_item : prev_item;
1134 } 1287 }
1135 } 1288 }
1136 1289
@@ -1145,32 +1298,34 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
1145 1298
1146void LLScrollListCtrl::selectNextItem( BOOL extend_selection) 1299void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
1147{ 1300{
1301 LLScrollListItem* next_item = NULL;
1302
1148 if (!getFirstSelected()) 1303 if (!getFirstSelected())
1149 { 1304 {
1150 selectFirstItem(); 1305 selectFirstItem();
1151 } 1306 }
1152 else 1307 else
1153 { 1308 {
1154 item_list::iterator iter; 1309 item_list::reverse_iterator iter;
1155 for (iter = mItemList.begin(); iter != mItemList.end(); iter++) 1310 for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++)
1156 { 1311 {
1157 LLScrollListItem* item = *iter; 1312 LLScrollListItem* cur_item = *iter;
1158 if (item->getSelected()) 1313
1314 if (cur_item->getSelected())
1159 { 1315 {
1160 if (++iter != mItemList.end()) 1316 if (next_item)
1161 { 1317 {
1162 LLScrollListItem *next_item = *iter; 1318 selectItem(next_item, !extend_selection);
1163 if (next_item) 1319 }
1164 { 1320 else
1165 selectItem(next_item, !extend_selection); 1321 {
1166 } 1322 reportInvalidInput();
1167 else
1168 {
1169 reportInvalidInput();
1170 }
1171 } 1323 }
1172 break; 1324 break;
1173 } 1325 }
1326
1327 // don't allow navigation to disabled items
1328 next_item = cur_item->getEnabled() ? cur_item : next_item;
1174 } 1329 }
1175 } 1330 }
1176 1331
@@ -1200,27 +1355,31 @@ void LLScrollListCtrl::deselectAllItems(BOOL no_commit_on_change)
1200} 1355}
1201 1356
1202/////////////////////////////////////////////////////////////////////////////////////////////////// 1357///////////////////////////////////////////////////////////////////////////////////////////////////
1203// "Simple" interface: use this when you're creating a list that contains only unique strings, only 1358// Use this to add comment text such as "Searching", which ignores column settings of list
1204// one of which can be selected at a time.
1205 1359
1206LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, EAddPosition pos, BOOL enabled) 1360LLScrollListItem* LLScrollListCtrl::addCommentText(const LLString& comment_text, EAddPosition pos)
1207{ 1361{
1208 LLScrollListItem* item = NULL; 1362 LLScrollListItem* item = NULL;
1209 if (getItemCount() < mMaxItemCount) 1363 if (getItemCount() < mMaxItemCount)
1210 { 1364 {
1211 // simple items have their LLSD data set to their label 1365 // simple items have their LLSD data set to their label
1212 item = new LLScrollListItem( LLSD(item_text) ); 1366 // always draw comment text with "enabled" color
1213 item->setEnabled(enabled); 1367 item = new LLScrollListItemComment( comment_text, mFgUnselectedColor );
1214 item->addColumn( item_text, gResMgr->getRes( LLFONT_SANSSERIF_SMALL ) ); 1368 addItem( item, pos, FALSE );
1215 addItem( item, pos );
1216 } 1369 }
1217 return item; 1370 return item;
1218} 1371}
1219 1372
1373LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)
1374{
1375 LLScrollListItem* item = new LLScrollListItemSeparator();
1376 addItem(item, pos, FALSE);
1377 return item;
1378}
1220 1379
1221// Selects first enabled item of the given name. 1380// Selects first enabled item of the given name.
1222// Returns false if item not found. 1381// Returns false if item not found.
1223BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensitive) 1382BOOL LLScrollListCtrl::selectItemByLabel(const LLString& label, BOOL case_sensitive)
1224{ 1383{
1225 //RN: assume no empty items 1384 //RN: assume no empty items
1226 if (label.empty()) 1385 if (label.empty())
@@ -1242,7 +1401,7 @@ BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensiti
1242 { 1401 {
1243 LLScrollListItem* item = *iter; 1402 LLScrollListItem* item = *iter;
1244 // Only select enabled items with matching names 1403 // Only select enabled items with matching names
1245 LLString item_text = item->getColumn(0)->getText(); 1404 LLString item_text = item->getColumn(0)->getValue().asString();
1246 if (!case_sensitive) 1405 if (!case_sensitive)
1247 { 1406 {
1248 LLString::toLower(item_text); 1407 LLString::toLower(item_text);
@@ -1265,14 +1424,14 @@ BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensiti
1265} 1424}
1266 1425
1267 1426
1268BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLString& target, BOOL case_sensitive) 1427BOOL LLScrollListCtrl::selectItemByPrefix(const LLString& target, BOOL case_sensitive)
1269{ 1428{
1270 return selectSimpleItemByPrefix(utf8str_to_wstring(target), case_sensitive); 1429 return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive);
1271} 1430}
1272 1431
1273// Selects first enabled item that has a name where the name's first part matched the target string. 1432// Selects first enabled item that has a name where the name's first part matched the target string.
1274// Returns false if item not found. 1433// Returns false if item not found.
1275BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL case_sensitive) 1434BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive)
1276{ 1435{
1277 BOOL found = FALSE; 1436 BOOL found = FALSE;
1278 1437
@@ -1288,7 +1447,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
1288 LLScrollListItem* item = *iter; 1447 LLScrollListItem* item = *iter;
1289 // Only select enabled items with matching names 1448 // Only select enabled items with matching names
1290 LLScrollListCell* cellp = item->getColumn(mSearchColumn); 1449 LLScrollListCell* cellp = item->getColumn(mSearchColumn);
1291 BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getText()[0]) : FALSE; 1450 BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
1292 if (select) 1451 if (select)
1293 { 1452 {
1294 selectItem(item); 1453 selectItem(item);
@@ -1315,7 +1474,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
1315 { 1474 {
1316 continue; 1475 continue;
1317 } 1476 }
1318 LLWString item_label = utf8str_to_wstring(cellp->getText()); 1477 LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
1319 if (!case_sensitive) 1478 if (!case_sensitive)
1320 { 1479 {
1321 LLWString::toLower(item_label); 1480 LLWString::toLower(item_label);
@@ -1346,14 +1505,14 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca
1346 return found; 1505 return found;
1347} 1506}
1348 1507
1349const LLString& LLScrollListCtrl::getSimpleSelectedItem(S32 column) const 1508const LLString LLScrollListCtrl::getSelectedItemLabel(S32 column) const
1350{ 1509{
1351 LLScrollListItem* item; 1510 LLScrollListItem* item;
1352 1511
1353 item = getFirstSelected(); 1512 item = getFirstSelected();
1354 if (item) 1513 if (item)
1355 { 1514 {
1356 return item->getColumn(column)->getText(); 1515 return item->getColumn(column)->getValue().asString();
1357 } 1516 }
1358 1517
1359 return LLString::null; 1518 return LLString::null;
@@ -1375,20 +1534,6 @@ LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const LLString& item_text,
1375 return item; 1534 return item;
1376} 1535}
1377 1536
1378LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, LLSD sd, EAddPosition pos, BOOL enabled, S32 column_width)
1379{
1380 LLScrollListItem* item = NULL;
1381 if (getItemCount() < mMaxItemCount)
1382 {
1383 item = new LLScrollListItem( sd );
1384 item->setEnabled(enabled);
1385 item->addColumn(item_text, gResMgr->getRes(LLFONT_SANSSERIF_SMALL), column_width);
1386 addItem( item, pos );
1387 }
1388 return item;
1389}
1390
1391
1392// Select the line or lines that match this UUID 1537// Select the line or lines that match this UUID
1393BOOL LLScrollListCtrl::selectByID( const LLUUID& id ) 1538BOOL LLScrollListCtrl::selectByID( const LLUUID& id )
1394{ 1539{
@@ -1454,7 +1599,7 @@ LLUUID LLScrollListCtrl::getStringUUIDSelectedItem()
1454 return LLUUID::null; 1599 return LLUUID::null;
1455} 1600}
1456 1601
1457LLSD LLScrollListCtrl::getSimpleSelectedValue() 1602LLSD LLScrollListCtrl::getSelectedValue()
1458{ 1603{
1459 LLScrollListItem* item = getFirstSelected(); 1604 LLScrollListItem* item = getFirstSelected();
1460 1605
@@ -1481,28 +1626,28 @@ void LLScrollListCtrl::drawItems()
1481 LLGLSUIDefault gls_ui; 1626 LLGLSUIDefault gls_ui;
1482 1627
1483 { 1628 {
1484 LLRect clip_rect = mItemListRect; 1629 LLLocalClipRect clip(mItemListRect);
1485 if(!mScrollbar->getVisible()) clip_rect.mRight += SCROLLBAR_SIZE;
1486 LLLocalClipRect clip(clip_rect);
1487 1630
1488 S32 cur_x = x;
1489 S32 cur_y = y; 1631 S32 cur_y = y;
1490 1632
1491 mDrewSelected = FALSE; 1633 mDrewSelected = FALSE;
1492 1634
1493 S32 line = 0; 1635 S32 line = 0;
1494 LLColor4 color;
1495 S32 max_columns = 0; 1636 S32 max_columns = 0;
1496 1637
1638 LLColor4 highlight_color = LLColor4::white;
1639 F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout");
1640 highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f);
1641
1497 item_list::iterator iter; 1642 item_list::iterator iter;
1498 for (iter = mItemList.begin(); iter != mItemList.end(); iter++) 1643 for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
1499 { 1644 {
1500 LLScrollListItem* item = *iter; 1645 LLScrollListItem* item = *iter;
1501 1646
1502 item_rect.setOriginAndSize( 1647 item_rect.setOriginAndSize(
1503 cur_x, 1648 x,
1504 cur_y, 1649 cur_y,
1505 mScrollbar->getVisible() ? mItemListRect.getWidth() : mItemListRect.getWidth() + SCROLLBAR_SIZE, 1650 mItemListRect.getWidth(),
1506 mLineHeight ); 1651 mLineHeight );
1507 1652
1508 //llinfos << item_rect.getWidth() << llendl; 1653 //llinfos << item_rect.getWidth() << llendl;
@@ -1514,85 +1659,37 @@ void LLScrollListCtrl::drawItems()
1514 1659
1515 max_columns = llmax(max_columns, item->getNumColumns()); 1660 max_columns = llmax(max_columns, item->getNumColumns());
1516 1661
1517 LLRect bg_rect = item_rect; 1662 LLColor4 fg_color;
1518 // pad background rectangle to separate it from contents 1663 LLColor4 bg_color(LLColor4::transparent);
1519 bg_rect.stretch(LIST_BORDER_PAD, 0);
1520 1664
1521 if( mScrollLines <= line && line < mScrollLines + num_page_lines ) 1665 if( mScrollLines <= line && line < mScrollLines + num_page_lines )
1522 { 1666 {
1667 fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
1523 if( item->getSelected() && mCanSelect) 1668 if( item->getSelected() && mCanSelect)
1524 { 1669 {
1525 // Draw background of selected item 1670 // Draw background of selected item
1526 LLGLSNoTexture no_texture; 1671 bg_color = mBgSelectedColor;
1527 glColor4fv(mBgSelectedColor.mV); 1672 fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor);
1528 gl_rect_2d( bg_rect );
1529
1530 color = mFgSelectedColor;
1531 } 1673 }
1532 else if (mHighlightedItem == line && mCanSelect) 1674 else if (mHighlightedItem == line && mCanSelect)
1533 { 1675 {
1534 LLGLSNoTexture no_texture; 1676 bg_color = mHighlightedColor;
1535 glColor4fv(mHighlightedColor.mV);
1536 gl_rect_2d( bg_rect );
1537 color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
1538 } 1677 }
1539 else 1678 else
1540 { 1679 {
1541 color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); 1680 if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
1542 if (mDrawStripes && (line%2 == 0) && (max_columns > 1))
1543 { 1681 {
1544 LLGLSNoTexture no_texture; 1682 bg_color = mBgStripeColor;
1545 glColor4fv(mBgStripeColor.mV);
1546 gl_rect_2d( bg_rect );
1547 } 1683 }
1548 } 1684 }
1549 1685
1550 S32 line_x = cur_x; 1686 if (!item->getEnabled())
1551 { 1687 {
1552 S32 num_cols = item->getNumColumns(); 1688 bg_color = mBgReadOnlyColor;
1553 S32 cur_col = 0; 1689 }
1554 S32 dynamic_width = 0;
1555 S32 dynamic_remainder = 0;
1556 bool first_dynamic = true;
1557 if(mNumDynamicWidthColumns > 0)
1558 {
1559 dynamic_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
1560 dynamic_remainder = (mItemListRect.getWidth() - mTotalStaticColumnWidth) % mNumDynamicWidthColumns;
1561 }
1562 1690
1563 for (LLScrollListCell* cell = item->getColumn(0); cur_col < num_cols; cell = item->getColumn(++cur_col)) 1691 item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding);
1564 {
1565 S32 cell_width = cell->getWidth();
1566
1567 if(mColumnsIndexed.size() > (U32)cur_col && mColumnsIndexed[cur_col] && mColumnsIndexed[cur_col]->mDynamicWidth)
1568 {
1569 cell_width = dynamic_width + (--dynamic_remainder ? 1 : 0);
1570 if(first_dynamic)
1571 {
1572 cell_width += mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE;
1573 first_dynamic = false;
1574 }
1575 cell->setWidth(cell_width);
1576 }
1577 // Two ways a cell could be hidden
1578 if (cell_width < 0
1579 || !cell->getVisible()) continue;
1580
1581 LLUI::pushMatrix();
1582 LLUI::translate((F32) cur_x, (F32) cur_y, 0.0f);
1583 S32 space_left = mItemListRect.mRight - cur_x;
1584 LLColor4 highlight_color = LLColor4::white;
1585 F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout");
1586
1587 highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f);
1588 cell->drawToWidth( space_left, color, highlight_color );
1589 LLUI::popMatrix();
1590
1591 cur_x += cell_width + mColumnPadding;
1592 1692
1593 }
1594 }
1595 cur_x = line_x;
1596 cur_y -= mLineHeight; 1693 cur_y -= mLineHeight;
1597 } 1694 }
1598 line++; 1695 line++;
@@ -1605,6 +1702,12 @@ void LLScrollListCtrl::draw()
1605{ 1702{
1606 if( getVisible() ) 1703 if( getVisible() )
1607 { 1704 {
1705 // if user specifies sort, make sure it is maintained
1706 if (needsSorting() && !isSorted())
1707 {
1708 sortItems();
1709 }
1710
1608 if (mNeedsScroll) 1711 if (mNeedsScroll)
1609 { 1712 {
1610 scrollToShowSelected(); 1713 scrollToShowSelected();
@@ -1645,6 +1748,54 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
1645 return handled; 1748 return handled;
1646} 1749}
1647 1750
1751BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
1752{
1753 S32 column_index = getColumnIndexFromOffset(x);
1754 LLScrollListColumn* columnp = getColumn(column_index);
1755
1756 if (columnp == NULL) return FALSE;
1757
1758 BOOL handled = FALSE;
1759 // show tooltip for full name of hovered item if it has been truncated
1760 LLScrollListItem* hit_item = hitItem(x, y);
1761 if (hit_item)
1762 {
1763 LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
1764 if (!hit_cell) return FALSE;
1765 S32 cell_required_width = hit_cell->getContentWidth();
1766 if (hit_cell
1767 && hit_cell->isText()
1768 && cell_required_width > columnp->mWidth)
1769 {
1770
1771 S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
1772 S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item));
1773 LLRect cell_rect;
1774 cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->mWidth, mLineHeight);
1775 // Convert rect local to screen coordinates
1776 localPointToScreen(
1777 cell_rect.mLeft, cell_rect.mBottom,
1778 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
1779 localPointToScreen(
1780 cell_rect.mRight, cell_rect.mTop,
1781 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
1782
1783 msg = hit_cell->getValue().asString();
1784 handled = TRUE;
1785 }
1786 }
1787
1788 // otherwise, look for a tooltip associated with this column
1789 LLColumnHeader* headerp = columnp->mHeader;
1790 if (headerp && !handled)
1791 {
1792 headerp->handleToolTip(x, y, msg, sticky_rect_screen);
1793 handled = !msg.empty();
1794 }
1795
1796 return handled;
1797}
1798
1648BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) 1799BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
1649{ 1800{
1650 if (!mCanSelect) return FALSE; 1801 if (!mCanSelect) return FALSE;
@@ -1652,6 +1803,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
1652 BOOL selection_changed = FALSE; 1803 BOOL selection_changed = FALSE;
1653 1804
1654 LLScrollListItem* hit_item = hitItem(x, y); 1805 LLScrollListItem* hit_item = hitItem(x, y);
1806
1655 if( hit_item ) 1807 if( hit_item )
1656 { 1808 {
1657 if( mAllowMultipleSelection ) 1809 if( mAllowMultipleSelection )
@@ -1686,6 +1838,11 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
1686 { 1838 {
1687 selectItem(item, FALSE); 1839 selectItem(item, FALSE);
1688 selecting = !selecting; 1840 selecting = !selecting;
1841 if (hit_item == lastSelected)
1842 {
1843 // stop selecting now, since we just clicked on our last selected item
1844 selecting = FALSE;
1845 }
1689 } 1846 }
1690 if (selecting) 1847 if (selecting)
1691 { 1848 {
@@ -1726,9 +1883,6 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
1726 selectItem(hit_item); 1883 selectItem(hit_item);
1727 } 1884 }
1728 1885
1729 hit_item->handleClick(x - mBorderThickness - LIST_BORDER_PAD,
1730 1, mask);
1731
1732 selection_changed = mSelectionChanged; 1886 selection_changed = mSelectionChanged;
1733 if (mCommitOnSelectionChange) 1887 if (mCommitOnSelectionChange)
1734 { 1888 {
@@ -1750,19 +1904,17 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
1750 1904
1751BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) 1905BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
1752{ 1906{
1753 BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; 1907 BOOL handled = childrenHandleMouseDown(x, y, mask) != NULL;
1754 1908
1755 if( !handled ) 1909 if( !handled )
1756 { 1910 {
1757 // set keyboard focus first, in case click action wants to move focus elsewhere 1911 // set keyboard focus first, in case click action wants to move focus elsewhere
1758 setFocus(TRUE); 1912 setFocus(TRUE);
1759 1913
1760 // clear selection changed flag so because user is starting a selection operation 1914 // clear selection changed flag because user is starting a selection operation
1761 mSelectionChanged = FALSE; 1915 mSelectionChanged = FALSE;
1762 1916
1763 gFocusMgr.setMouseCapture(this); 1917 handleClick(x, y, mask);
1764 selectItemAt(x, y, mask);
1765 mNeedsScroll = TRUE;
1766 } 1918 }
1767 1919
1768 return TRUE; 1920 return TRUE;
@@ -1798,19 +1950,79 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
1798 //BOOL handled = FALSE; 1950 //BOOL handled = FALSE;
1799 if(getVisible()) 1951 if(getVisible())
1800 { 1952 {
1801 // Offer the click to the children, even if we aren't enabled 1953 BOOL handled = handleClick(x, y, mask);
1802 // so the scroll bars will work. 1954
1803 if (NULL == LLView::childrenHandleDoubleClick(x, y, mask)) 1955 if (!handled)
1804 { 1956 {
1805 if( mCanSelect && mOnDoubleClickCallback ) 1957 // Offer the click to the children, even if we aren't enabled
1958 // so the scroll bars will work.
1959 if (NULL == LLView::childrenHandleDoubleClick(x, y, mask))
1806 { 1960 {
1807 mOnDoubleClickCallback( mCallbackUserData ); 1961 if( mCanSelect && mOnDoubleClickCallback )
1962 {
1963 mOnDoubleClickCallback( mCallbackUserData );
1964 }
1808 } 1965 }
1809 } 1966 }
1810 } 1967 }
1811 return TRUE; 1968 return TRUE;
1812} 1969}
1813 1970
1971BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask)
1972{
1973 // which row was clicked on?
1974 LLScrollListItem* hit_item = hitItem(x, y);
1975 if (!hit_item) return FALSE;
1976
1977 // get appropriate cell from that row
1978 S32 column_index = getColumnIndexFromOffset(x);
1979 LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
1980 if (!hit_cell) return FALSE;
1981
1982 // if cell handled click directly (i.e. clicked on an embedded checkbox)
1983 if (hit_cell->handleClick())
1984 {
1985 // if item not currently selected, select it
1986 if (!hit_item->getSelected())
1987 {
1988 selectItemAt(x, y, mask);
1989 gFocusMgr.setMouseCapture(this);
1990 mNeedsScroll = TRUE;
1991 }
1992 // otherwise we already have this item selected
1993 // so propagate state of cell to rest of selected column
1994 else
1995 {
1996 // propagate value of this cell to other selected items
1997 // and commit the respective widgets
1998 LLSD item_value = hit_cell->getValue();
1999 for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++)
2000 {
2001 LLScrollListItem* item = *iter;
2002 if (item->getSelected())
2003 {
2004 LLScrollListCell* cellp = item->getColumn(column_index);
2005 cellp->setValue(item_value);
2006 cellp->onCommit();
2007 }
2008 }
2009 //FIXME: find a better way to signal cell changes
2010 onCommit();
2011 }
2012 // eat click (e.g. do not trigger double click callback)
2013 return TRUE;
2014 }
2015 else
2016 {
2017 // treat this as a normal single item selection
2018 selectItemAt(x, y, mask);
2019 gFocusMgr.setMouseCapture(this);
2020 mNeedsScroll = TRUE;
2021 // do not eat click (allow double click callback)
2022 return FALSE;
2023 }
2024}
2025
1814LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) 2026LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
1815{ 2027{
1816 // Excludes disabled items. 2028 // Excludes disabled items.
@@ -1847,6 +2059,59 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
1847 return hit_item; 2059 return hit_item;
1848} 2060}
1849 2061
2062S32 LLScrollListCtrl::getColumnIndexFromOffset(S32 x)
2063{
2064 // which column did we hit?
2065 S32 left = 0;
2066 S32 right = 0;
2067 S32 width = 0;
2068 S32 column_index = 0;
2069
2070 ordered_columns_t::const_iterator iter = mColumnsIndexed.begin();
2071 ordered_columns_t::const_iterator end = mColumnsIndexed.end();
2072 for ( ; iter != end; ++iter)
2073 {
2074 width = (*iter)->mWidth + mColumnPadding;
2075 right += width;
2076 if (left <= x && x < right )
2077 {
2078 break;
2079 }
2080
2081 // set left for next column as right of current column
2082 left = right;
2083 column_index++;
2084 }
2085
2086 return llclamp(column_index, 0, getNumColumns() - 1);
2087}
2088
2089
2090S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index)
2091{
2092 S32 column_offset = 0;
2093 ordered_columns_t::const_iterator iter = mColumnsIndexed.begin();
2094 ordered_columns_t::const_iterator end = mColumnsIndexed.end();
2095 for ( ; iter != end; ++iter)
2096 {
2097 if (index-- <= 0)
2098 {
2099 return column_offset;
2100 }
2101 column_offset += (*iter)->mWidth + mColumnPadding;
2102 }
2103
2104 // when running off the end, return the rightmost pixel
2105 return mItemListRect.mRight;
2106}
2107
2108S32 LLScrollListCtrl::getRowOffsetFromIndex(S32 index)
2109{
2110 S32 row_bottom = ((mItemListRect.mTop - (index - mScrollLines)) * mLineHeight)
2111 - mLineHeight;
2112 return row_bottom;
2113}
2114
1850 2115
1851BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) 2116BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
1852{ 2117{
@@ -1860,7 +2125,8 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
1860 mNeedsScroll = TRUE; 2125 mNeedsScroll = TRUE;
1861 } 2126 }
1862 } 2127 }
1863 else if (mCanSelect) 2128 else
2129 if (mCanSelect)
1864 { 2130 {
1865 LLScrollListItem* item = hitItem(x, y); 2131 LLScrollListItem* item = hitItem(x, y);
1866 if (item) 2132 if (item)
@@ -1875,13 +2141,6 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
1875 2141
1876 handled = LLUICtrl::handleHover( x, y, mask ); 2142 handled = LLUICtrl::handleHover( x, y, mask );
1877 2143
1878 //if( !handled )
1879 //{
1880 // // Opaque
1881 // getWindow()->setCursor(UI_CURSOR_ARROW);
1882 // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
1883 // handled = TRUE;
1884 //}
1885 return handled; 2144 return handled;
1886} 2145}
1887 2146
@@ -1998,7 +2257,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
1998 } 2257 }
1999 } 2258 }
2000 } 2259 }
2001 else if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString), FALSE)) 2260 else if (selectItemByPrefix(wstring_to_utf8str(mSearchString), FALSE))
2002 { 2261 {
2003 mNeedsScroll = TRUE; 2262 mNeedsScroll = TRUE;
2004 // update search string only on successful match 2263 // update search string only on successful match
@@ -2037,7 +2296,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
2037 // type ahead search is case insensitive 2296 // type ahead search is case insensitive
2038 uni_char = LLStringOps::toLower((llwchar)uni_char); 2297 uni_char = LLStringOps::toLower((llwchar)uni_char);
2039 2298
2040 if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE)) 2299 if (selectItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE))
2041 { 2300 {
2042 // update search string only on successful match 2301 // update search string only on successful match
2043 mNeedsScroll = TRUE; 2302 mNeedsScroll = TRUE;
@@ -2082,7 +2341,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
2082 if (cellp) 2341 if (cellp)
2083 { 2342 {
2084 // Only select enabled items with matching first characters 2343 // Only select enabled items with matching first characters
2085 LLWString item_label = utf8str_to_wstring(cellp->getText()); 2344 LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
2086 if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char) 2345 if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
2087 { 2346 {
2088 selectItem(item); 2347 selectItem(item);
@@ -2176,7 +2435,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp)
2176 LLScrollListCell* cellp = itemp->getColumn(mSearchColumn); 2435 LLScrollListCell* cellp = itemp->getColumn(mSearchColumn);
2177 if (cellp) 2436 if (cellp)
2178 { 2437 {
2179 cellp->highlightText(0, 0); 2438 cellp->highlightText(0, 0);
2180 } 2439 }
2181 mSelectionChanged = TRUE; 2440 mSelectionChanged = TRUE;
2182 } 2441 }
@@ -2202,38 +2461,52 @@ BOOL LLScrollListCtrl::isSorted()
2202 return mSorted; 2461 return mSorted;
2203} 2462}
2204 2463
2205// Called by scrollbar 2464struct SameSortColumn
2206//static
2207void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
2208{ 2465{
2209 LLScrollListCtrl* self = (LLScrollListCtrl*) userdata; 2466 SameSortColumn(S32 column) : mColumn(column) {}
2210 self->mScrollLines = new_pos; 2467 S32 mColumn;
2211}
2212 2468
2469 bool operator()(std::pair<S32, BOOL> sort_column) { return sort_column.first == mColumn; }
2470};
2213 2471
2214// First column is column 0 2472BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending)
2215void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending)
2216{ 2473{
2217 if (!mSorted || mSortColumn != column) 2474 sort_column_t new_sort_column(column, ascending);
2475
2476 if (mSortColumns.empty())
2218 { 2477 {
2219 mSortColumn = column; 2478 mSortColumns.push_back(new_sort_column);
2220 std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); 2479 return TRUE;
2221 setSorted(TRUE);
2222 } 2480 }
2481 else
2482 {
2483 // grab current sort column
2484 sort_column_t cur_sort_column = mSortColumns.back();
2485
2486 // remove any existing sort criterion referencing this column
2487 // and add the new one
2488 mSortColumns.erase(remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column)), mSortColumns.end());
2489 mSortColumns.push_back(new_sort_column);
2223 2490
2224 // just reverse the list if changing sort order 2491 // did the sort criteria change?
2225 if(mSortAscending != ascending) 2492 return (cur_sort_column != new_sort_column);
2226 {
2227 std::reverse(mItemList.begin(), mItemList.end());
2228 mSortAscending = ascending;
2229 } 2493 }
2230} 2494}
2231 2495
2496// Called by scrollbar
2497//static
2498void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
2499{
2500 LLScrollListCtrl* self = (LLScrollListCtrl*) userdata;
2501 self->mScrollLines = new_pos;
2502}
2503
2504
2232void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending) 2505void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending)
2233{ 2506{
2234 if (name.empty()) 2507 if (name.empty())
2235 { 2508 {
2236 sortByColumn(mSortColumn, mSortAscending); 2509 sortItems();
2237 return; 2510 return;
2238 } 2511 }
2239 2512
@@ -2244,6 +2517,26 @@ void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending)
2244 } 2517 }
2245} 2518}
2246 2519
2520// First column is column 0
2521void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending)
2522{
2523 if (setSort(column, ascending))
2524 {
2525 sortItems();
2526 }
2527}
2528
2529void LLScrollListCtrl::sortItems()
2530{
2531 // do stable sort to preserve any previous sorts
2532 std::stable_sort(
2533 mItemList.begin(),
2534 mItemList.end(),
2535 SortScrollListItem(mSortColumns));
2536
2537 setSorted(TRUE);
2538}
2539
2247S32 LLScrollListCtrl::getScrollPos() 2540S32 LLScrollListCtrl::getScrollPos()
2248{ 2541{
2249 return mScrollbar->getDocPos(); 2542 return mScrollbar->getDocPos();
@@ -2431,9 +2724,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2431 BOOL draw_heading = FALSE; 2724 BOOL draw_heading = FALSE;
2432 node->getAttributeBOOL("draw_heading", draw_heading); 2725 node->getAttributeBOOL("draw_heading", draw_heading);
2433 2726
2434 BOOL collapse_empty_columns = FALSE;
2435 node->getAttributeBOOL("collapse_empty_columns", collapse_empty_columns);
2436
2437 S32 search_column = 0; 2727 S32 search_column = 0;
2438 node->getAttributeS32("search_column", search_column); 2728 node->getAttributeS32("search_column", search_column);
2439 2729
@@ -2454,7 +2744,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2454 node->getAttributeS32("heading_height", heading_height); 2744 node->getAttributeS32("heading_height", heading_height);
2455 scroll_list->setHeadingHeight(heading_height); 2745 scroll_list->setHeadingHeight(heading_height);
2456 } 2746 }
2457 scroll_list->setCollapseEmptyColumns(collapse_empty_columns);
2458 2747
2459 scroll_list->setScrollListParameters(node); 2748 scroll_list->setScrollListParameters(node);
2460 2749
@@ -2465,7 +2754,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2465 LLSD columns; 2754 LLSD columns;
2466 S32 index = 0; 2755 S32 index = 0;
2467 LLXMLNodePtr child; 2756 LLXMLNodePtr child;
2468 S32 total_static = 0, num_dynamic = 0; 2757 S32 total_static = 0;
2469 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) 2758 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
2470 { 2759 {
2471 if (child->hasName("column")) 2760 if (child->hasName("column"))
@@ -2491,8 +2780,10 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2491 S32 columnwidth = -1; 2780 S32 columnwidth = -1;
2492 child->getAttributeS32("width", columnwidth); 2781 child->getAttributeS32("width", columnwidth);
2493 2782
2494 if(!columndynamicwidth) total_static += columnwidth; 2783 LLString tooltip;
2495 else ++num_dynamic; 2784 child->getAttributeString("tool_tip", tooltip);
2785
2786 if(!columndynamicwidth) total_static += llmax(0, columnwidth);
2496 2787
2497 F32 columnrelwidth = 0.f; 2788 F32 columnrelwidth = 0.f;
2498 child->getAttributeF32("relwidth", columnrelwidth); 2789 child->getAttributeF32("relwidth", columnrelwidth);
@@ -2509,10 +2800,11 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2509 columns[index]["relwidth"] = columnrelwidth; 2800 columns[index]["relwidth"] = columnrelwidth;
2510 columns[index]["dynamicwidth"] = columndynamicwidth; 2801 columns[index]["dynamicwidth"] = columndynamicwidth;
2511 columns[index]["halign"] = (S32)h_align; 2802 columns[index]["halign"] = (S32)h_align;
2803 columns[index]["tool_tip"] = tooltip;
2804
2512 index++; 2805 index++;
2513 } 2806 }
2514 } 2807 }
2515 scroll_list->setNumDynamicColumns(num_dynamic);
2516 scroll_list->setTotalStaticColumnWidth(total_static); 2808 scroll_list->setTotalStaticColumnWidth(total_static);
2517 scroll_list->setColumnHeadings(columns); 2809 scroll_list->setColumnHeadings(columns);
2518 2810
@@ -2566,7 +2858,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2566 while(token_iter != tokens.end()) 2858 while(token_iter != tokens.end())
2567 { 2859 {
2568 const char* line = token_iter->c_str(); 2860 const char* line = token_iter->c_str();
2569 scroll_list->addSimpleItem(line); 2861 scroll_list->addSimpleElement(line);
2570 ++token_iter; 2862 ++token_iter;
2571 } 2863 }
2572 } 2864 }
@@ -2663,10 +2955,6 @@ BOOL LLScrollListCtrl::canDeselect()
2663void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) 2955void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
2664{ 2956{
2665 LLString name = column["name"].asString(); 2957 LLString name = column["name"].asString();
2666 if (mColumns.empty())
2667 {
2668 mDefaultColumn = 0;
2669 }
2670 // if no column name provided, just use ordinal as name 2958 // if no column name provided, just use ordinal as name
2671 if (name.empty()) 2959 if (name.empty())
2672 { 2960 {
@@ -2691,6 +2979,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
2691 } 2979 }
2692 else if(new_column->mDynamicWidth) 2980 else if(new_column->mDynamicWidth)
2693 { 2981 {
2982 mNumDynamicWidthColumns++;
2694 new_column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; 2983 new_column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
2695 } 2984 }
2696 S32 top = mItemListRect.mTop; 2985 S32 top = mItemListRect.mTop;
@@ -2724,19 +3013,19 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
2724 new_column->mHeader->setLabel(new_column->mLabel); 3013 new_column->mHeader->setLabel(new_column->mLabel);
2725 //new_column->mHeader->setLabel(new_column->mLabel); 3014 //new_column->mHeader->setLabel(new_column->mLabel);
2726 } 3015 }
3016
3017 new_column->mHeader->setToolTip(column["tool_tip"].asString());
3018
2727 //RN: although it might be useful to change sort order with the keyboard, 3019 //RN: although it might be useful to change sort order with the keyboard,
2728 // mixing tab stops on child items along with the parent item is not supported yet 3020 // mixing tab stops on child items along with the parent item is not supported yet
2729 new_column->mHeader->setTabStop(FALSE); 3021 new_column->mHeader->setTabStop(FALSE);
2730 addChild(new_column->mHeader); 3022 addChild(new_column->mHeader);
2731 new_column->mHeader->setVisible(mDisplayColumnHeaders); 3023 new_column->mHeader->setVisible(mDisplayColumnHeaders);
2732 3024
2733 3025 sendChildToFront(mScrollbar);
2734 // Move scroll to front
2735 removeChild(mScrollbar);
2736 addChild(mScrollbar);
2737
2738 } 3026 }
2739 } 3027 }
3028
2740 updateColumns(); 3029 updateColumns();
2741} 3030}
2742 3031
@@ -2753,18 +3042,18 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
2753 3042
2754 LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; 3043 LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
2755 bool ascending = column->mSortAscending; 3044 bool ascending = column->mSortAscending;
2756 if (column->mSortingColumn != column->mName) 3045 if (column->mSortingColumn != column->mName
3046 && parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end())
2757 { 3047 {
2758 if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) 3048 LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn];
2759 { 3049 column_index = info_redir.mIndex;
2760 LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn];
2761 column_index = info_redir.mIndex;
2762 }
2763 } 3050 }
2764 3051
2765 if (column_index == parent->mSortColumn) 3052 // if this column is the primary sort key, reverse the direction
3053 sort_column_t cur_sort_column;
3054 if (!parent->mSortColumns.empty() && parent->mSortColumns.back().first == column_index)
2766 { 3055 {
2767 ascending = !parent->mSortAscending; 3056 ascending = !parent->mSortColumns.back().second;
2768 } 3057 }
2769 3058
2770 parent->sortByColumn(column_index, ascending); 3059 parent->sortByColumn(column_index, ascending);
@@ -2777,12 +3066,17 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
2777 3066
2778std::string LLScrollListCtrl::getSortColumnName() 3067std::string LLScrollListCtrl::getSortColumnName()
2779{ 3068{
2780 LLScrollListColumn* column = mSortColumn >= 0 ? mColumnsIndexed[mSortColumn] : NULL; 3069 LLScrollListColumn* column = mSortColumns.empty() ? NULL : mColumnsIndexed[mSortColumns.back().first];
2781 3070
2782 if (column) return column->mName; 3071 if (column) return column->mName;
2783 else return ""; 3072 else return "";
2784} 3073}
2785 3074
3075BOOL LLScrollListCtrl::needsSorting()
3076{
3077 return !mSortColumns.empty();
3078}
3079
2786void LLScrollListCtrl::clearColumns() 3080void LLScrollListCtrl::clearColumns()
2787{ 3081{
2788 std::map<LLString, LLScrollListColumn>::iterator itor; 3082 std::map<LLString, LLScrollListColumn>::iterator itor;
@@ -2796,6 +3090,7 @@ void LLScrollListCtrl::clearColumns()
2796 } 3090 }
2797 } 3091 }
2798 mColumns.clear(); 3092 mColumns.clear();
3093 mSortColumns.clear();
2799} 3094}
2800 3095
2801void LLScrollListCtrl::setColumnLabel(const LLString& column, const LLString& label) 3096void LLScrollListCtrl::setColumnLabel(const LLString& column, const LLString& label)
@@ -2849,12 +3144,12 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2849 S32 col_index = 0 ; 3144 S32 col_index = 0 ;
2850 for (itor = columns.beginArray(); itor != columns.endArray(); ++itor) 3145 for (itor = columns.beginArray(); itor != columns.endArray(); ++itor)
2851 { 3146 {
2852 LLString column = (*itor)["column"].asString(); 3147 if (itor->isUndefined())
2853
2854 if (mColumns.size() == 0)
2855 { 3148 {
2856 mDefaultColumn = 0; 3149 // skip unused columns in item passed in
3150 continue;
2857 } 3151 }
3152 LLString column = (*itor)["column"].asString();
2858 3153
2859 LLScrollListColumn* columnp = NULL; 3154 LLScrollListColumn* columnp = NULL;
2860 3155
@@ -2879,9 +3174,18 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2879 LLSD new_column; 3174 LLSD new_column;
2880 new_column["name"] = column; 3175 new_column["name"] = column;
2881 new_column["label"] = column; 3176 new_column["label"] = column;
2882 new_column["width"] = (*itor)["width"]; 3177 // if width supplied for column, use it, otherwise
3178 // use adaptive width
3179 if (itor->has("width"))
3180 {
3181 new_column["width"] = (*itor)["width"];
3182 }
3183 else
3184 {
3185 new_column["dynamicwidth"] = true;
3186 }
2883 addColumn(new_column); 3187 addColumn(new_column);
2884 columnp = &mColumns.find(column)->second; 3188 columnp = &mColumns[column];
2885 new_item->setNumColumns(mColumns.size()); 3189 new_item->setNumColumns(mColumns.size());
2886 } 3190 }
2887 3191
@@ -2895,6 +3199,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2895 LLString type = (*itor)["type"].asString(); 3199 LLString type = (*itor)["type"].asString();
2896 BOOL has_color = (*itor).has("color"); 3200 BOOL has_color = (*itor).has("color");
2897 LLColor4 color = ((*itor)["color"]); 3201 LLColor4 color = ((*itor)["color"]);
3202 BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true;
2898 3203
2899 const LLFontGL *font = gResMgr->getRes(fontname); 3204 const LLFontGL *font = gResMgr->getRes(fontname);
2900 if (!font) 3205 if (!font)
@@ -2906,8 +3211,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2906 if (type == "icon") 3211 if (type == "icon")
2907 { 3212 {
2908 LLUUID image_id = value.asUUID(); 3213 LLUUID image_id = value.asUUID();
2909 LLImageGL* icon = LLUI::sImageProvider->getUIImageByID(image_id); 3214 LLScrollListIcon* cell = new LLScrollListIcon(value.asUUID(), width);
2910 LLScrollListIcon* cell = new LLScrollListIcon(icon, width, image_id);
2911 if (has_color) 3215 if (has_color)
2912 { 3216 {
2913 cell->setColor(color); 3217 cell->setColor(color);
@@ -2916,8 +3220,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
2916 } 3220 }
2917 else if (type == "checkbox") 3221 else if (type == "checkbox")
2918 { 3222 {
2919 LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl(value.asString(), 3223 LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl("check",
2920 LLRect(0, 0, width, width), "label"); 3224 LLRect(0, width, width, 0), " ");
3225 ctrl->setEnabled(enabled);
3226 ctrl->setValue(value);
2921 LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width); 3227 LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width);
2922 if (has_color) 3228 if (has_color)
2923 { 3229 {
@@ -3070,18 +3376,12 @@ void LLScrollListCtrl::onFocusReceived()
3070{ 3376{
3071 // forget latent selection changes when getting focus 3377 // forget latent selection changes when getting focus
3072 mSelectionChanged = FALSE; 3378 mSelectionChanged = FALSE;
3379 LLUICtrl::onFocusReceived();
3073} 3380}
3074 3381
3075//virtual 3382//virtual
3076void LLScrollListCtrl::onFocusLost() 3383void LLScrollListCtrl::onFocusLost()
3077{ 3384{
3078 if (mIsPopup)
3079 {
3080 if (getParent())
3081 {
3082 getParent()->onFocusLost();
3083 }
3084 }
3085 if (hasMouseCapture()) 3385 if (hasMouseCapture())
3086 { 3386 {
3087 gFocusMgr.setMouseCapture(NULL); 3387 gFocusMgr.setMouseCapture(NULL);
@@ -3133,11 +3433,11 @@ void LLColumnHeader::draw()
3133{ 3433{
3134 if( getVisible() ) 3434 if( getVisible() )
3135 { 3435 {
3136 mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; 3436 BOOL draw_arrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
3137 3437
3138 BOOL is_ascending = mColumn->mParentCtrl->getSortAscending(); 3438 BOOL is_ascending = mColumn->mParentCtrl->getSortAscending();
3139 mArrowImage = is_ascending ? LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("up_arrow.tga"))) 3439 mButton->setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent);
3140 : LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("down_arrow.tga"))); 3440 mArrowImage = mButton->getImageOverlay()->getImage();
3141 3441
3142 //BOOL clip = mRect.mRight > mColumn->mParentCtrl->getItemListRect().getWidth(); 3442 //BOOL clip = mRect.mRight > mColumn->mParentCtrl->getItemListRect().getWidth();
3143 //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE); 3443 //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE);
@@ -3237,11 +3537,11 @@ void LLColumnHeader::showList()
3237 { 3537 {
3238 if (mColumn->mParentCtrl->getSortAscending()) 3538 if (mColumn->mParentCtrl->getSortAscending())
3239 { 3539 {
3240 low_item_text = cell->getText(); 3540 low_item_text = cell->getValue().asString();
3241 } 3541 }
3242 else 3542 else
3243 { 3543 {
3244 high_item_text = cell->getText(); 3544 high_item_text = cell->getValue().asString();
3245 } 3545 }
3246 } 3546 }
3247 } 3547 }
@@ -3254,11 +3554,11 @@ void LLColumnHeader::showList()
3254 { 3554 {
3255 if (mColumn->mParentCtrl->getSortAscending()) 3555 if (mColumn->mParentCtrl->getSortAscending())
3256 { 3556 {
3257 high_item_text = cell->getText(); 3557 high_item_text = cell->getValue().asString();
3258 } 3558 }
3259 else 3559 else
3260 { 3560 {
3261 low_item_text = cell->getText(); 3561 low_item_text = cell->getValue().asString();
3262 } 3562 }
3263 } 3563 }
3264 } 3564 }
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h
index c548727..ada4f9b 100644
--- a/linden/indra/llui/llscrolllistctrl.h
+++ b/linden/indra/llui/llscrolllistctrl.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -56,20 +56,26 @@ class LLResizeBar;
56class LLScrollListCell 56class LLScrollListCell
57{ 57{
58public: 58public:
59 LLScrollListCell(S32 width = 0) : mWidth(width) {};
59 virtual ~LLScrollListCell() {}; 60 virtual ~LLScrollListCell() {};
60 virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const = 0; // truncate to given width, if possible 61 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const = 0; // truncate to given width, if possible
61 virtual S32 getWidth() const = 0; 62 virtual S32 getWidth() const {return mWidth;}
63 virtual S32 getContentWidth() const { return 0; }
62 virtual S32 getHeight() const = 0; 64 virtual S32 getHeight() const = 0;
63 virtual const LLString& getText() const { return LLString::null; } 65 virtual const LLSD getValue() const { return LLString::null; }
64 virtual const LLString& getTextLower() const { return LLString::null; } 66 virtual void setValue(LLSD value) { }
65 virtual BOOL getVisible() const { return TRUE; } 67 virtual BOOL getVisible() const { return TRUE; }
66 virtual void setWidth(S32 width) = 0; 68 virtual void setWidth(S32 width) { mWidth = width; }
67 virtual void highlightText(S32 offset, S32 num_chars) {} 69 virtual void highlightText(S32 offset, S32 num_chars) {}
68 virtual BOOL isText() = 0; 70 virtual BOOL isText() = 0;
69 virtual void setColor(const LLColor4&) = 0; 71 virtual void setColor(const LLColor4&) {}
72 virtual void onCommit() {};
70 73
71 virtual BOOL handleClick() { return FALSE; } 74 virtual BOOL handleClick() { return FALSE; }
72 virtual void setEnabled(BOOL enable) { } 75 virtual void setEnabled(BOOL enable) { }
76
77protected:
78 S32 mWidth;
73}; 79};
74 80
75class LLScrollListSeparator : public LLScrollListCell 81class LLScrollListSeparator : public LLScrollListCell
@@ -77,15 +83,9 @@ class LLScrollListSeparator : public LLScrollListCell
77public: 83public:
78 LLScrollListSeparator(S32 width); 84 LLScrollListSeparator(S32 width);
79 virtual ~LLScrollListSeparator() {}; 85 virtual ~LLScrollListSeparator() {};
80 virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible 86 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible
81 virtual S32 getWidth() const {return mWidth;}
82 virtual S32 getHeight() const { return 5; }; 87 virtual S32 getHeight() const { return 5; };
83 virtual void setWidth(S32 width) {mWidth = width; }
84 virtual void setColor(const LLColor4&) {};
85 virtual BOOL isText() { return FALSE; } 88 virtual BOOL isText() { return FALSE; }
86
87protected:
88 S32 mWidth;
89}; 89};
90 90
91class LLScrollListText : public LLScrollListCell 91class LLScrollListText : public LLScrollListCell
@@ -94,24 +94,25 @@ public:
94 LLScrollListText( const LLString& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE); 94 LLScrollListText( const LLString& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE);
95 /*virtual*/ ~LLScrollListText(); 95 /*virtual*/ ~LLScrollListText();
96 96
97 virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; 97 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
98 virtual S32 getWidth() const { return mWidth; } 98 virtual S32 getContentWidth() const;
99 virtual void setWidth(S32 width) { mWidth = width; }
100 virtual S32 getHeight() const { return llround(mFont->getLineHeight()); } 99 virtual S32 getHeight() const { return llround(mFont->getLineHeight()); }
101 virtual const LLString& getText() const { return mText.getString(); } 100 virtual const LLSD getValue() const { return LLSD(mText.getString()); }
102 virtual BOOL getVisible() const { return mVisible; } 101 virtual BOOL getVisible() const { return mVisible; }
103 virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;} 102 virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;}
104 void setText(const LLStringExplicit& text); 103
105 virtual void setColor(const LLColor4&); 104 virtual void setColor(const LLColor4&);
106 virtual BOOL isText() { return TRUE; } 105 virtual BOOL isText() { return TRUE; }
107 106
107 void setText(const LLStringExplicit& text);
108 void setFontStyle(const U8 font_style) { mFontStyle = font_style; }
109
108private: 110private:
109 LLUIString mText; 111 LLUIString mText;
110 const LLFontGL* mFont; 112 const LLFontGL* mFont;
111 LLColor4* mColor; 113 LLColor4* mColor;
112 const U8 mFontStyle; 114 U8 mFontStyle;
113 LLFontGL::HAlign mFontAlignment; 115 LLFontGL::HAlign mFontAlignment;
114 S32 mWidth;
115 BOOL mVisible; 116 BOOL mVisible;
116 S32 mHighlightCount; 117 S32 mHighlightCount;
117 S32 mHighlightOffset; 118 S32 mHighlightOffset;
@@ -124,21 +125,20 @@ private:
124class LLScrollListIcon : public LLScrollListCell 125class LLScrollListIcon : public LLScrollListCell
125{ 126{
126public: 127public:
127 LLScrollListIcon( LLImageGL* icon, S32 width = 0, LLUUID image_id = LLUUID::null); 128 LLScrollListIcon( const LLUUID& icon_id, S32 width = 0);
128 /*virtual*/ ~LLScrollListIcon(); 129 /*virtual*/ ~LLScrollListIcon();
129 virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; 130 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
130 virtual S32 getWidth() const { return mWidth; } 131 virtual S32 getWidth() const;
131 virtual S32 getHeight() const { return mIcon->getHeight(); } 132 virtual S32 getHeight() const { return mIcon ? mIcon->getHeight() : 0; }
132 virtual const LLString& getText() const { return mImageUUID; } 133 // used as sort criterion
133 virtual const LLString& getTextLower() const { return mImageUUID; } 134 virtual const LLSD getValue() const { return LLSD(mImageUUID); }
134 virtual void setWidth(S32 width) { mWidth = width; }
135 virtual void setColor(const LLColor4&); 135 virtual void setColor(const LLColor4&);
136 virtual BOOL isText() { return FALSE; } 136 virtual BOOL isText() { return FALSE; }
137 virtual void setValue(LLSD value);
137 138
138private: 139private:
139 LLPointer<LLImageGL> mIcon; 140 LLPointer<LLImageGL> mIcon;
140 LLString mImageUUID; 141 LLUUID mImageUUID;
141 S32 mWidth;
142 LLColor4 mColor; 142 LLColor4 mColor;
143}; 143};
144 144
@@ -147,21 +147,20 @@ class LLScrollListCheck : public LLScrollListCell
147public: 147public:
148 LLScrollListCheck( LLCheckBoxCtrl* check_box, S32 width = 0); 148 LLScrollListCheck( LLCheckBoxCtrl* check_box, S32 width = 0);
149 /*virtual*/ ~LLScrollListCheck(); 149 /*virtual*/ ~LLScrollListCheck();
150 virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; 150 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
151 virtual S32 getWidth() const { return mWidth; }
152 virtual S32 getHeight() const { return 0; } 151 virtual S32 getHeight() const { return 0; }
153 virtual void setWidth(S32 width) { mWidth = width; } 152 virtual const LLSD getValue() const { return mCheckBox->getValue(); }
153 virtual void setValue(LLSD value) { mCheckBox->setValue(value); }
154 virtual void onCommit() { mCheckBox->onCommit(); }
154 155
155 virtual BOOL handleClick(); 156 virtual BOOL handleClick();
156 virtual void setEnabled(BOOL enable) { if (mCheckBox) mCheckBox->setEnabled(enable); } 157 virtual void setEnabled(BOOL enable) { mCheckBox->setEnabled(enable); }
157 virtual void setColor(const LLColor4& color) {};
158 158
159 LLCheckBoxCtrl* getCheckBox() { return mCheckBox; } 159 LLCheckBoxCtrl* getCheckBox() { return mCheckBox; }
160 virtual BOOL isText() { return FALSE; } 160 virtual BOOL isText() { return FALSE; }
161 161
162private: 162private:
163 LLCheckBoxCtrl* mCheckBox; 163 LLCheckBoxCtrl* mCheckBox;
164 S32 mWidth;
165}; 164};
166 165
167class LLScrollListColumn 166class LLScrollListColumn
@@ -266,6 +265,7 @@ public:
266 265
267 /*virtual*/ void draw(); 266 /*virtual*/ void draw();
268 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); 267 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
268
269 /*virtual*/ void showList(); 269 /*virtual*/ void showList();
270 /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding); 270 /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding);
271 /*virtual*/ void userSetShape(const LLRect& new_rect); 271 /*virtual*/ void userSetShape(const LLRect& new_rect);
@@ -319,8 +319,8 @@ public:
319 void addColumn( const LLString& text, const LLFontGL* font, S32 width = 0 , U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, BOOL visible = TRUE) 319 void addColumn( const LLString& text, const LLFontGL* font, S32 width = 0 , U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, BOOL visible = TRUE)
320 { mColumns.push_back( new LLScrollListText(text, font, width, font_style, font_alignment, LLColor4::black, FALSE, visible) ); } 320 { mColumns.push_back( new LLScrollListText(text, font, width, font_style, font_alignment, LLColor4::black, FALSE, visible) ); }
321 321
322 void addColumn( LLImageGL* icon, S32 width = 0 ) 322 void addColumn( const LLUUID& icon_id, S32 width = 0 )
323 { mColumns.push_back( new LLScrollListIcon(icon, width) ); } 323 { mColumns.push_back( new LLScrollListIcon(icon_id, width) ); }
324 324
325 void addColumn( LLCheckBoxCtrl* check, S32 width = 0 ) 325 void addColumn( LLCheckBoxCtrl* check, S32 width = 0 )
326 { mColumns.push_back( new LLScrollListCheck(check,width) ); } 326 { mColumns.push_back( new LLScrollListCheck(check,width) ); }
@@ -333,10 +333,10 @@ public:
333 333
334 LLScrollListCell *getColumn(const S32 i) const { if (0 <= i && i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; } 334 LLScrollListCell *getColumn(const S32 i) const { if (0 <= i && i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; }
335 335
336 virtual BOOL handleClick(S32 x, S32 y, MASK mask);
337
338 LLString getContentsCSV(); 336 LLString getContentsCSV();
339 337
338 virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
339
340private: 340private:
341 BOOL mSelected; 341 BOOL mSelected;
342 BOOL mEnabled; 342 BOOL mEnabled;
@@ -345,6 +345,23 @@ private:
345 std::vector<LLScrollListCell *> mColumns; 345 std::vector<LLScrollListCell *> mColumns;
346}; 346};
347 347
348class LLScrollListItemComment : public LLScrollListItem
349{
350public:
351 LLScrollListItemComment(const LLString& comment_string, const LLColor4& color);
352
353 /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
354private:
355 LLColor4 mColor;
356};
357
358class LLScrollListItemSeparator : public LLScrollListItem
359{
360public:
361 LLScrollListItemSeparator();
362
363 /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
364};
348 365
349class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, 366class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
350 public LLCtrlListInterface, public LLCtrlScrollInterface 367 public LLCtrlListInterface, public LLCtrlScrollInterface
@@ -370,9 +387,8 @@ public:
370 void deleteAllItems() { clearRows(); } 387 void deleteAllItems() { clearRows(); }
371 388
372 // Sets an array of column descriptors 389 // Sets an array of column descriptors
373 void setColumnHeadings(LLSD headings); 390 void setColumnHeadings(LLSD headings);
374 // Numerical based sort by column function (used by LLComboBox) 391 void sortByColumn(U32 column, BOOL ascending);
375 void sortByColumn(U32 column, BOOL ascending);
376 392
377 // LLCtrlListInterface functions 393 // LLCtrlListInterface functions
378 virtual S32 getItemCount() const; 394 virtual S32 getItemCount() const;
@@ -390,7 +406,6 @@ public:
390 virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); 406 virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
391 // Simple add element. Takes a single array of: 407 // Simple add element. Takes a single array of:
392 // [ "value" => value, "font" => font, "font-style" => style ] 408 // [ "value" => value, "font" => font, "font-style" => style ]
393 virtual LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
394 virtual void clearRows(); // clears all elements 409 virtual void clearRows(); // clears all elements
395 virtual void sortByColumn(LLString name, BOOL ascending); 410 virtual void sortByColumn(LLString name, BOOL ascending);
396 411
@@ -421,18 +436,20 @@ public:
421 BOOL isSorted(); 436 BOOL isSorted();
422 437
423 virtual BOOL isSelected(LLSD value); 438 virtual BOOL isSelected(LLSD value);
424 439
440 BOOL handleClick(S32 x, S32 y, MASK mask);
425 BOOL selectFirstItem(); 441 BOOL selectFirstItem();
426 BOOL selectNthItem( S32 index ); 442 BOOL selectNthItem( S32 index );
427 BOOL selectItemAt(S32 x, S32 y, MASK mask); 443 BOOL selectItemAt(S32 x, S32 y, MASK mask);
428 444
429 void deleteSingleItem( S32 index ) ; 445 void deleteSingleItem( S32 index );
446 void deleteItems(const LLSD& sd);
430 void deleteSelectedItems(); 447 void deleteSelectedItems();
431 void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change 448 void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change
432 449
433 void highlightNthItem( S32 index ); 450 void highlightNthItem( S32 index );
434 void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; } 451 void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; }
435 void setMaxiumumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; } 452 void setMaximumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; }
436 void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; } 453 void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; }
437 454
438 void swapWithNext(S32 index); 455 void swapWithNext(S32 index);
@@ -444,19 +461,21 @@ public:
444 S32 getItemIndex( LLScrollListItem* item ); 461 S32 getItemIndex( LLScrollListItem* item );
445 S32 getItemIndex( LLUUID& item_id ); 462 S32 getItemIndex( LLUUID& item_id );
446 463
464 LLScrollListItem* addCommentText( const LLString& comment_text, EAddPosition pos = ADD_BOTTOM);
465 LLScrollListItem* addSeparator(EAddPosition pos);
466
447 // "Simple" interface: use this when you're creating a list that contains only unique strings, only 467 // "Simple" interface: use this when you're creating a list that contains only unique strings, only
448 // one of which can be selected at a time. 468 // one of which can be selected at a time.
449 LLScrollListItem* addSimpleItem( const LLString& item_text, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE ); 469 virtual LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
450 // Add an item with an associated LLSD 470
451 LLScrollListItem* addSimpleItem(const LLString& item_text, LLSD sd, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0 );
452 471
453 BOOL selectSimpleItem( const LLString& item, BOOL case_sensitive = TRUE ); // FALSE if item not found 472 BOOL selectItemByLabel( const LLString& item, BOOL case_sensitive = TRUE ); // FALSE if item not found
454 BOOL selectSimpleItemByPrefix(const LLString& target, BOOL case_sensitive); 473 BOOL selectItemByPrefix(const LLString& target, BOOL case_sensitive = TRUE);
455 BOOL selectSimpleItemByPrefix(const LLWString& target, BOOL case_sensitive); 474 BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
456 const LLString& getSimpleSelectedItem(S32 column = 0) const; 475 const LLString getSelectedItemLabel(S32 column = 0) const;
457 LLSD getSimpleSelectedValue(); 476 LLSD getSelectedValue();
458 477
459 // DEPRECATED: Use LLSD versions of addSimpleItem() and getSimpleSelectedValue(). 478 // DEPRECATED: Use LLSD versions of addCommentText() and getSelectedValue().
460 // "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which 479 // "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which
461 // has an associated, unique UUID, and only one of which can be selected at a time. 480 // has an associated, unique UUID, and only one of which can be selected at a time.
462 LLScrollListItem* addStringUUIDItem(const LLString& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0); 481 LLScrollListItem* addStringUUIDItem(const LLString& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0);
@@ -472,6 +491,8 @@ public:
472 LLScrollListItem* getFirstData() const; 491 LLScrollListItem* getFirstData() const;
473 LLScrollListItem* getLastData() const; 492 LLScrollListItem* getLastData() const;
474 std::vector<LLScrollListItem*> getAllData() const; 493 std::vector<LLScrollListItem*> getAllData() const;
494
495 LLScrollListItem* getItem(const LLSD& sd) const;
475 496
476 void setAllowMultipleSelection(BOOL mult ) { mAllowMultipleSelection = mult; } 497 void setAllowMultipleSelection(BOOL mult ) { mAllowMultipleSelection = mult; }
477 498
@@ -501,28 +522,34 @@ public:
501 522
502 S32 getSearchColumn() { return mSearchColumn; } 523 S32 getSearchColumn() { return mSearchColumn; }
503 void setSearchColumn(S32 column) { mSearchColumn = column; } 524 void setSearchColumn(S32 column) { mSearchColumn = column; }
525 S32 getColumnIndexFromOffset(S32 x);
526 S32 getColumnOffsetFromIndex(S32 index);
527 S32 getRowOffsetFromIndex(S32 index);
504 528
505 void clearSearchString() { mSearchString.clear(); } 529 void clearSearchString() { mSearchString.clear(); }
506 530
507 // Overridden from LLView 531 // Overridden from LLView
508 virtual void draw(); 532 /*virtual*/ void draw();
509 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); 533 /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
510 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); 534 /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
511 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); 535 /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
512 virtual BOOL handleHover(S32 x, S32 y, MASK mask); 536 /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
513 virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); 537 /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
514 virtual BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent); 538 /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent);
515 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 539 /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
516 virtual void setEnabled(BOOL enabled); 540 /*virtual*/ BOOL handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect);
517 virtual void setFocus( BOOL b ); 541 /*virtual*/ void setEnabled(BOOL enabled);
518 virtual void onFocusReceived(); 542 /*virtual*/ void setFocus( BOOL b );
519 virtual void onFocusLost(); 543 /*virtual*/ void onFocusReceived();
544 /*virtual*/ void onFocusLost();
545 /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
520 546
521 virtual BOOL isDirty() const; 547 virtual BOOL isDirty() const;
522 virtual void resetDirty(); // Clear dirty state 548 virtual void resetDirty(); // Clear dirty state
523 549
524 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); 550 virtual void updateLayout();
525 virtual void arrange(S32 max_width, S32 max_height); 551 virtual void fitContents(S32 max_width, S32 max_height);
552
526 virtual LLRect getRequiredRect(); 553 virtual LLRect getRequiredRect();
527 static BOOL rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row); 554 static BOOL rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row);
528 555
@@ -534,12 +561,12 @@ public:
534 static void onClickColumn(void *userdata); 561 static void onClickColumn(void *userdata);
535 562
536 void updateColumns(); 563 void updateColumns();
537 void updateMaxContentWidth(LLScrollListItem* changed_item); 564 void calcMaxContentWidth(LLScrollListItem* changed_item);
565 S32 getMaxContentWidth() { return mMaxContentWidth; }
538 566
539 void setDisplayHeading(BOOL display); 567 void setDisplayHeading(BOOL display);
540 void setHeadingHeight(S32 heading_height); 568 void setHeadingHeight(S32 heading_height);
541 void setCollapseEmptyColumns(BOOL collapse); 569 void setCollapseEmptyColumns(BOOL collapse);
542 void setIsPopup(BOOL is_popup) { mIsPopup = is_popup; }
543 570
544 LLScrollListItem* hitItem(S32 x,S32 y); 571 LLScrollListItem* hitItem(S32 x,S32 y);
545 virtual void scrollToShowSelected(); 572 virtual void scrollToShowSelected();
@@ -564,9 +591,11 @@ public:
564 void setTotalStaticColumnWidth(int width) { mTotalStaticColumnWidth = width; } 591 void setTotalStaticColumnWidth(int width) { mTotalStaticColumnWidth = width; }
565 592
566 std::string getSortColumnName(); 593 std::string getSortColumnName();
567 BOOL getSortAscending() { return mSortAscending; } 594 BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
595 BOOL needsSorting();
568 596
569 S32 selectMultiple( LLDynamicArray<LLUUID> ids ); 597 S32 selectMultiple( LLDynamicArray<LLUUID> ids );
598 void sortItems();
570 599
571protected: 600protected:
572 // "Full" interface: use this when you're creating a list that has one or more of the following: 601 // "Full" interface: use this when you're creating a list that has one or more of the following:
@@ -584,7 +613,7 @@ protected:
584 // to the caller to delete the item) 613 // to the caller to delete the item)
585 614
586 // returns FALSE if item faile to be added to list, does NOT delete 'item' 615 // returns FALSE if item faile to be added to list, does NOT delete 'item'
587 BOOL addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM ); 616 BOOL addItem( LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM, BOOL requires_column = TRUE );
588 void selectPrevItem(BOOL extend_selection); 617 void selectPrevItem(BOOL extend_selection);
589 void selectNextItem(BOOL extend_selection); 618 void selectNextItem(BOOL extend_selection);
590 void drawItems(); 619 void drawItems();
@@ -596,6 +625,7 @@ protected:
596 void deselectItem(LLScrollListItem* itemp); 625 void deselectItem(LLScrollListItem* itemp);
597 void commitIfChanged(); 626 void commitIfChanged();
598 void setSorted(BOOL sorted); 627 void setSorted(BOOL sorted);
628 BOOL setSort(S32 column, BOOL ascending);
599 629
600protected: 630protected:
601 S32 mCurIndex; // For get[First/Next]Data 631 S32 mCurIndex; // For get[First/Next]Data
@@ -615,8 +645,6 @@ protected:
615 BOOL mNeedsScroll; 645 BOOL mNeedsScroll;
616 BOOL mCanSelect; 646 BOOL mCanSelect;
617 BOOL mDisplayColumnHeaders; 647 BOOL mDisplayColumnHeaders;
618 BOOL mCollapseEmptyColumns;
619 BOOL mIsPopup;
620 648
621 typedef std::deque<LLScrollListItem *> item_list; 649 typedef std::deque<LLScrollListItem *> item_list;
622 item_list mItemList; 650 item_list mItemList;
@@ -626,7 +654,7 @@ protected:
626 S32 mMaxItemCount; 654 S32 mMaxItemCount;
627 655
628 LLRect mItemListRect; 656 LLRect mItemListRect;
629 657 S32 mMaxContentWidth;
630 S32 mColumnPadding; 658 S32 mColumnPadding;
631 659
632 BOOL mBackgroundVisible; 660 BOOL mBackgroundVisible;
@@ -652,22 +680,23 @@ protected:
652 LLWString mSearchString; 680 LLWString mSearchString;
653 LLFrameTimer mSearchTimer; 681 LLFrameTimer mSearchTimer;
654 682
655 LLString mDefaultColumn;
656
657 S32 mSearchColumn; 683 S32 mSearchColumn;
658 S32 mNumDynamicWidthColumns; 684 S32 mNumDynamicWidthColumns;
659 S32 mTotalStaticColumnWidth; 685 S32 mTotalStaticColumnWidth;
660 686
661 S32 mSortColumn;
662 BOOL mSortAscending;
663 BOOL mSorted; 687 BOOL mSorted;
664 688
665 std::map<LLString, LLScrollListColumn> mColumns; 689 std::map<LLString, LLScrollListColumn> mColumns;
666 std::vector<LLScrollListColumn*> mColumnsIndexed;
667 690
668 BOOL mDirty; 691 BOOL mDirty;
669 S32 mOriginalSelection; 692 S32 mOriginalSelection;
670 693
694 typedef std::vector<LLScrollListColumn*> ordered_columns_t;
695 ordered_columns_t mColumnsIndexed;
696
697 typedef std::pair<S32, BOOL> sort_column_t;
698 std::vector<sort_column_t> mSortColumns;
699
671public: 700public:
672 // HACK: Did we draw one selected item this frame? 701 // HACK: Did we draw one selected item this frame?
673 BOOL mDrewSelected; 702 BOOL mDrewSelected;
diff --git a/linden/indra/llui/llslider.cpp b/linden/indra/llui/llslider.cpp
index 606a8a1..e03603d 100644
--- a/linden/indra/llui/llslider.cpp
+++ b/linden/indra/llui/llslider.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -41,9 +41,6 @@
41#include "llcontrol.h" 41#include "llcontrol.h"
42#include "llimagegl.h" 42#include "llimagegl.h"
43 43
44const S32 THUMB_WIDTH = 8;
45const S32 TRACK_HEIGHT = 6;
46
47LLSlider::LLSlider( 44LLSlider::LLSlider(
48 const LLString& name, 45 const LLString& name,
49 const LLRect& rect, 46 const LLRect& rect,
@@ -65,20 +62,24 @@ LLSlider::LLSlider(
65 mIncrement( increment ), 62 mIncrement( increment ),
66 mVolumeSlider( volume ), 63 mVolumeSlider( volume ),
67 mMouseOffset( 0 ), 64 mMouseOffset( 0 ),
68 mDragStartThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
69 mThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
70 mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ), 65 mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ),
71 mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ), 66 mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ),
72 mThumbCenterColor( LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ), 67 mThumbCenterColor( LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ),
73 mDisabledThumbColor(LLUI::sColorsGroup->getColor( "SliderDisabledThumbColor" ) ),
74 mMouseDownCallback( NULL ), 68 mMouseDownCallback( NULL ),
75 mMouseUpCallback( NULL ) 69 mMouseUpCallback( NULL )
76{ 70{
71 mThumbImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("icn_slide-thumb_dark.tga")));
72 mTrackImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("icn_slide-groove_dark.tga")));
73 mTrackHighlightImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("icn_slide-highlight.tga")));
74
77 // properly handle setting the starting thumb rect 75 // properly handle setting the starting thumb rect
78 // do it this way to handle both the operating-on-settings 76 // do it this way to handle both the operating-on-settings
79 // and standalone ways of using this 77 // and standalone ways of using this
80 setControlName(control_name, NULL); 78 setControlName(control_name, NULL);
81 setValue(getValueF32()); 79 setValue(getValueF32());
80
81 updateThumbRect();
82 mDragStartThumbRect = mThumbRect;
82} 83}
83 84
84EWidgetType LLSlider::getWidgetType() const 85EWidgetType LLSlider::getWidgetType() const
@@ -107,17 +108,26 @@ void LLSlider::setValue(F32 value, BOOL from_event)
107 } 108 }
108 109
109 mValue = value; 110 mValue = value;
111 updateThumbRect();
112}
110 113
114void LLSlider::updateThumbRect()
115{
111 F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue); 116 F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
112 117
113 S32 left_edge = THUMB_WIDTH/2; 118 S32 thumb_width = mThumbImage->getWidth();
114 S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2); 119 S32 thumb_height = mThumbImage->getHeight();
120 S32 left_edge = (thumb_width / 2);
121 S32 right_edge = mRect.getWidth() - (thumb_width / 2);
115 122
116 S32 x = left_edge + S32( t * (right_edge - left_edge) ); 123 S32 x = left_edge + S32( t * (right_edge - left_edge) );
117 mThumbRect.mLeft = x - (THUMB_WIDTH/2); 124 mThumbRect.mLeft = x - (thumb_width / 2);
118 mThumbRect.mRight = x + (THUMB_WIDTH/2); 125 mThumbRect.mRight = mThumbRect.mLeft + thumb_width;
126 mThumbRect.mBottom = getLocalRect().getCenterY() - (thumb_height / 2);
127 mThumbRect.mTop = mThumbRect.mBottom + thumb_height;
119} 128}
120 129
130
121void LLSlider::setValueAndCommit(F32 value) 131void LLSlider::setValueAndCommit(F32 value)
122{ 132{
123 F32 old_value = mValue; 133 F32 old_value = mValue;
@@ -139,8 +149,9 @@ BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
139{ 149{
140 if( hasMouseCapture() ) 150 if( hasMouseCapture() )
141 { 151 {
142 S32 left_edge = THUMB_WIDTH/2; 152 S32 thumb_half_width = mThumbImage->getWidth()/2;
143 S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2); 153 S32 left_edge = thumb_half_width;
154 S32 right_edge = mRect.getWidth() - (thumb_half_width);
144 155
145 x += mMouseOffset; 156 x += mMouseOffset;
146 x = llclamp( x, left_edge, right_edge ); 157 x = llclamp( x, left_edge, right_edge );
@@ -203,7 +214,7 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
203 // Find the offset of the actual mouse location from the center of the thumb. 214 // Find the offset of the actual mouse location from the center of the thumb.
204 if (mThumbRect.pointInRect(x,y)) 215 if (mThumbRect.pointInRect(x,y))
205 { 216 {
206 mMouseOffset = (mThumbRect.mLeft + THUMB_WIDTH/2) - x; 217 mMouseOffset = (mThumbRect.mLeft + mThumbImage->getWidth()/2) - x;
207 } 218 }
208 else 219 else
209 { 220 {
@@ -251,6 +262,9 @@ void LLSlider::draw()
251{ 262{
252 if( getVisible() ) 263 if( getVisible() )
253 { 264 {
265 // since thumb image might still be decoding, need thumb to accomodate image size
266 updateThumbRect();
267
254 // Draw background and thumb. 268 // Draw background and thumb.
255 269
256 // drawing solids requires texturing be disabled 270 // drawing solids requires texturing be disabled
@@ -260,104 +274,37 @@ void LLSlider::draw()
260 274
261 F32 opacity = mEnabled ? 1.f : 0.3f; 275 F32 opacity = mEnabled ? 1.f : 0.3f;
262 LLColor4 center_color = (mThumbCenterColor % opacity); 276 LLColor4 center_color = (mThumbCenterColor % opacity);
263 LLColor4 outline_color = (mThumbOutlineColor % opacity);
264 LLColor4 track_color = (mTrackColor % opacity); 277 LLColor4 track_color = (mTrackColor % opacity);
265 278
266 LLImageGL* thumb_imagep = NULL;
267
268 // Track 279 // Track
269 if (mVolumeSlider) 280 LLRect track_rect(mThumbImage->getWidth() / 2,
270 { 281 getLocalRect().getCenterY() + (mTrackImage->getHeight() / 2),
271 LLRect track(0, mRect.getHeight(), mRect.getWidth(), 0); 282 mRect.getWidth() - mThumbImage->getWidth() / 2,
272 283 getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
273 track.mBottom += 3;
274 track.mTop -= 1;
275 track.mRight -= 1;
276
277 gl_triangle_2d(track.mLeft, track.mBottom,
278 track.mRight, track.mBottom,
279 track.mRight, track.mTop,
280 center_color,
281 TRUE);
282 gl_triangle_2d(track.mLeft, track.mBottom,
283 track.mRight, track.mBottom,
284 track.mRight, track.mTop,
285 outline_color,
286 FALSE);
287 }
288 else
289 {
290 LLUUID thumb_image_id;
291 thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
292 thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
293 284
294 S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2; 285 gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 3, 3, track_rect.getWidth(), track_rect.getHeight(),
295 LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset ); 286 mTrackImage, track_color);
287 gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 3, 3, mThumbRect.mLeft, track_rect.getHeight(),
288 mTrackHighlightImage, track_color);
296 289
297 track_rect.stretch(-1);
298 gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
299 thumb_imagep, track_color);
300 }
301 290
302 // Thumb 291 // Thumb
303 if (!thumb_imagep) 292 if( hasMouseCapture() )
304 {
305 if (mVolumeSlider)
306 {
307 if (hasMouseCapture())
308 {
309 LLRect rect(mDragStartThumbRect);
310 gl_rect_2d( rect, outline_color );
311 rect.stretch(-1);
312 gl_rect_2d( rect, mThumbCenterColor % 0.3f );
313
314 if (hasFocus())
315 {
316 LLRect thumb_rect = mThumbRect;
317 thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
318 gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
319 }
320 gl_rect_2d( mThumbRect, mThumbOutlineColor );
321 }
322 else
323 {
324 if (hasFocus())
325 {
326 LLRect thumb_rect = mThumbRect;
327 thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
328 gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
329 }
330 LLRect rect(mThumbRect);
331 gl_rect_2d(rect, outline_color);
332 rect.stretch(-1);
333 gl_rect_2d( rect, center_color);
334 }
335 }
336 else
337 {
338 gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
339 if (hasMouseCapture())
340 {
341 gl_rect_2d(mDragStartThumbRect, center_color, FALSE);
342 }
343 }
344 }
345 else if( hasMouseCapture() )
346 { 293 {
347 gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(), 294 gl_draw_scaled_image(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(),
348 thumb_imagep, mThumbCenterColor % 0.3f, TRUE); 295 mThumbImage, mThumbCenterColor % 0.3f);
349 296
350 if (hasFocus()) 297 if (hasFocus())
351 { 298 {
352 F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); 299 F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
353 LLRect highlight_rect = mThumbRect; 300 LLRect highlight_rect = mThumbRect;
354 highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt))); 301 highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
355 gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(), 302 gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 0, 0, highlight_rect.getWidth(), highlight_rect.getHeight(),
356 thumb_imagep, gFocusMgr.getFocusColor()); 303 mThumbImage, gFocusMgr.getFocusColor(), TRUE);
357 } 304 }
358 305
359 gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(), 306 gl_draw_scaled_image(mThumbRect.mLeft, mThumbRect.mBottom, mThumbRect.getWidth(), mThumbRect.getHeight(),
360 thumb_imagep, mThumbOutlineColor, TRUE); 307 mThumbImage, mThumbOutlineColor);
361 308
362 } 309 }
363 else 310 else
@@ -367,12 +314,12 @@ void LLSlider::draw()
367 F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); 314 F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
368 LLRect highlight_rect = mThumbRect; 315 LLRect highlight_rect = mThumbRect;
369 highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt))); 316 highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
370 gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(), 317 gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 0, 0, highlight_rect.getWidth(), highlight_rect.getHeight(),
371 thumb_imagep, gFocusMgr.getFocusColor()); 318 mThumbImage, gFocusMgr.getFocusColor(), TRUE);
372 } 319 }
373 320
374 gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(), 321 gl_draw_scaled_image(mThumbRect.mLeft, mThumbRect.mBottom, mThumbRect.getWidth(), mThumbRect.getHeight(),
375 thumb_imagep, center_color, TRUE); 322 mThumbImage, center_color);
376 } 323 }
377 LLUICtrl::draw(); 324 LLUICtrl::draw();
378 } 325 }
diff --git a/linden/indra/llui/llslider.h b/linden/indra/llui/llslider.h
index 28a8d07..08ab600 100644
--- a/linden/indra/llui/llslider.h
+++ b/linden/indra/llui/llslider.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -36,6 +36,7 @@
36#include "v4color.h" 36#include "v4color.h"
37 37
38class LLUICtrlFactory; 38class LLUICtrlFactory;
39class LLImageGL;
39 40
40class LLSlider : public LLUICtrl 41class LLSlider : public LLUICtrl
41{ 42{
@@ -85,6 +86,7 @@ public:
85 86
86protected: 87protected:
87 void setValueAndCommit(F32 value); 88 void setValueAndCommit(F32 value);
89 void updateThumbRect();
88 90
89protected: 91protected:
90 F32 mValue; 92 F32 mValue;
@@ -97,11 +99,14 @@ protected:
97 S32 mMouseOffset; 99 S32 mMouseOffset;
98 LLRect mDragStartThumbRect; 100 LLRect mDragStartThumbRect;
99 101
102 LLImageGL* mThumbImage;
103 LLImageGL* mTrackImage;
104 LLImageGL* mTrackHighlightImage;
105
100 LLRect mThumbRect; 106 LLRect mThumbRect;
101 LLColor4 mTrackColor; 107 LLColor4 mTrackColor;
102 LLColor4 mThumbOutlineColor; 108 LLColor4 mThumbOutlineColor;
103 LLColor4 mThumbCenterColor; 109 LLColor4 mThumbCenterColor;
104 LLColor4 mDisabledThumbColor;
105 110
106 void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata); 111 void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata);
107 void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata); 112 void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata);
diff --git a/linden/indra/llui/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp
index 8bb8e24..17854d0 100644
--- a/linden/indra/llui/llsliderctrl.cpp
+++ b/linden/indra/llui/llsliderctrl.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -125,7 +125,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
125 &LLLineEditor::prevalidateFloat ); 125 &LLLineEditor::prevalidateFloat );
126 mEditor->setFollowsLeft(); 126 mEditor->setFollowsLeft();
127 mEditor->setFollowsBottom(); 127 mEditor->setFollowsBottom();
128 mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus ); 128 mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus, this );
129 mEditor->setIgnoreTab(TRUE); 129 mEditor->setIgnoreTab(TRUE);
130 // don't do this, as selecting the entire text is single clicking in some cases 130 // don't do this, as selecting the entire text is single clicking in some cases
131 // and double clicking in others 131 // and double clicking in others
@@ -150,7 +150,7 @@ LLSliderCtrl::~LLSliderCtrl()
150} 150}
151 151
152// static 152// static
153void LLSliderCtrl::onEditorGainFocus( LLUICtrl* caller, void *userdata ) 153void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
154{ 154{
155 LLSliderCtrl* self = (LLSliderCtrl*) userdata; 155 LLSliderCtrl* self = (LLSliderCtrl*) userdata;
156 llassert( caller == self->mEditor ); 156 llassert( caller == self->mEditor );
diff --git a/linden/indra/llui/llsliderctrl.h b/linden/indra/llui/llsliderctrl.h
index 87d2d89..7af0abf 100644
--- a/linden/indra/llui/llsliderctrl.h
+++ b/linden/indra/llui/llsliderctrl.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -117,7 +117,7 @@ public:
117 static void onSliderMouseUp(LLUICtrl* caller,void* userdata); 117 static void onSliderMouseUp(LLUICtrl* caller,void* userdata);
118 118
119 static void onEditorCommit(LLUICtrl* caller, void* userdata); 119 static void onEditorCommit(LLUICtrl* caller, void* userdata);
120 static void onEditorGainFocus(LLUICtrl* caller, void *userdata); 120 static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
121 static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); 121 static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
122 122
123private: 123private:
diff --git a/linden/indra/llui/llspinctrl.cpp b/linden/indra/llui/llspinctrl.cpp
index 0cd9390..4bd79e6 100644
--- a/linden/indra/llui/llspinctrl.cpp
+++ b/linden/indra/llui/llspinctrl.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -128,7 +128,7 @@ LLSpinCtrl::LLSpinCtrl( const LLString& name, const LLRect& rect, const LLString
128 &LLLineEditor::prevalidateFloat ); 128 &LLLineEditor::prevalidateFloat );
129 mEditor->setFollowsLeft(); 129 mEditor->setFollowsLeft();
130 mEditor->setFollowsBottom(); 130 mEditor->setFollowsBottom();
131 mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus ); 131 mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus, this );
132 //RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus 132 //RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus
133 // than when it doesn't. Instead, if you always have to double click to select all the text, 133 // than when it doesn't. Instead, if you always have to double click to select all the text,
134 // it's easier to understand 134 // it's easier to understand
@@ -137,7 +137,7 @@ LLSpinCtrl::LLSpinCtrl( const LLString& name, const LLRect& rect, const LLString
137 addChild(mEditor); 137 addChild(mEditor);
138 138
139 updateEditor(); 139 updateEditor();
140 setSpanChildren( TRUE ); 140 setUseBoundingRect( TRUE );
141} 141}
142 142
143LLSpinCtrl::~LLSpinCtrl() 143LLSpinCtrl::~LLSpinCtrl()
@@ -230,7 +230,7 @@ void LLSpinCtrl::onDownBtn( void *userdata )
230} 230}
231 231
232// static 232// static
233void LLSpinCtrl::onEditorGainFocus( LLUICtrl* caller, void *userdata ) 233void LLSpinCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
234{ 234{
235 LLSpinCtrl* self = (LLSpinCtrl*) userdata; 235 LLSpinCtrl* self = (LLSpinCtrl*) userdata;
236 llassert( caller == self->mEditor ); 236 llassert( caller == self->mEditor );
diff --git a/linden/indra/llui/llspinctrl.h b/linden/indra/llui/llspinctrl.h
index de8513e..c5a36f5 100644
--- a/linden/indra/llui/llspinctrl.h
+++ b/linden/indra/llui/llspinctrl.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -113,7 +113,7 @@ public:
113 virtual void draw(); 113 virtual void draw();
114 114
115 static void onEditorCommit(LLUICtrl* caller, void* userdata); 115 static void onEditorCommit(LLUICtrl* caller, void* userdata);
116 static void onEditorGainFocus(LLUICtrl* caller, void *userdata); 116 static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
117 static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); 117 static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
118 118
119 static void onUpBtn(void *userdata); 119 static void onUpBtn(void *userdata);
diff --git a/linden/indra/llui/llstyle.cpp b/linden/indra/llui/llstyle.cpp
index 2281d44..693e0be 100644
--- a/linden/indra/llui/llstyle.cpp
+++ b/linden/indra/llui/llstyle.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -230,7 +230,7 @@ void LLStyle::setImage(const LLString& src)
230 } 230 }
231 else 231 else
232 { 232 {
233 mImagep = LLUI::sImageProvider->getUIImageByID(LLUUID(src)); 233 mImagep = LLUI::sImageProvider->getImageByID(LLUUID(src));
234 } 234 }
235} 235}
236 236
diff --git a/linden/indra/llui/llstyle.h b/linden/indra/llui/llstyle.h
index fcff789..1712dc0 100644
--- a/linden/indra/llui/llstyle.h
+++ b/linden/indra/llui/llstyle.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lltabcontainer.cpp b/linden/indra/llui/lltabcontainer.cpp
index 19dc6ec..0400b50 100644
--- a/linden/indra/llui/lltabcontainer.cpp
+++ b/linden/indra/llui/lltabcontainer.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -156,7 +156,12 @@ void LLTabContainerCommon::lockTabs(S32 num_tabs)
156{ 156{
157 // count current tabs or use supplied value and ensure no new tabs get 157 // count current tabs or use supplied value and ensure no new tabs get
158 // inserted between them 158 // inserted between them
159 mLockedTabCount = num_tabs > 0 ? num_tabs : getTabCount(); 159 mLockedTabCount = num_tabs > 0 ? llmin(getTabCount(), num_tabs) : getTabCount();
160}
161
162void LLTabContainerCommon::unlockTabs()
163{
164 mLockedTabCount = 0;
160} 165}
161 166
162void LLTabContainerCommon::removeTabPanel(LLPanel* child) 167void LLTabContainerCommon::removeTabPanel(LLPanel* child)
@@ -557,7 +562,7 @@ void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name, con
557} 562}
558 563
559void LLTabContainerCommon::setTitle(const LLString& title) 564void LLTabContainerCommon::setTitle(const LLString& title)
560{ 565{
561 if (mTitleBox) 566 if (mTitleBox)
562 { 567 {
563 mTitleBox->setText( title ); 568 mTitleBox->setText( title );
@@ -721,6 +726,14 @@ void LLTabContainerCommon::insertTuple(LLTabTuple * tuple, eInsertionPoint inser
721 // insert the new tab in the front of the list 726 // insert the new tab in the front of the list
722 mTabList.insert(mTabList.begin() + mLockedTabCount, tuple); 727 mTabList.insert(mTabList.begin() + mLockedTabCount, tuple);
723 break; 728 break;
729 case LEFT_OF_CURRENT:
730 // insert the new tab before the current tab (but not before mLockedTabCount)
731 {
732 tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx);
733 mTabList.insert(current_iter, tuple);
734 }
735 break;
736
724 case RIGHT_OF_CURRENT: 737 case RIGHT_OF_CURRENT:
725 // insert the new tab after the current tab (but not before mLockedTabCount) 738 // insert the new tab after the current tab (but not before mLockedTabCount)
726 { 739 {
@@ -946,14 +959,14 @@ void LLTabContainer::addTabPanel(LLPanel* child,
946 if( LLTabContainer::TOP == mTabPosition ) 959 if( LLTabContainer::TOP == mTabPosition )
947 { 960 {
948 btn_rect.setLeftTopAndSize( 0, mRect.getHeight() - mTopBorderHeight + tab_fudge, button_width, TABCNTR_TAB_HEIGHT ); 961 btn_rect.setLeftTopAndSize( 0, mRect.getHeight() - mTopBorderHeight + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
949 tab_img = "UIImgBtnTabTopOutUUID"; 962 tab_img = "tab_top_blue.tga";
950 tab_selected_img = "UIImgBtnTabTopInUUID"; 963 tab_selected_img = "tab_top_selected_blue.tga";
951 } 964 }
952 else 965 else
953 { 966 {
954 btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT ); 967 btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
955 tab_img = "UIImgBtnTabBottomOutUUID"; 968 tab_img = "tab_bottom_blue.tga";
956 tab_selected_img = "UIImgBtnTabBottomInUUID"; 969 tab_selected_img = "tab_bottom_selected_blue.tga";
957 } 970 }
958 971
959 if (placeholder) 972 if (placeholder)
@@ -979,7 +992,7 @@ void LLTabContainer::addTabPanel(LLPanel* child,
979 LLButton* btn = new LLButton( 992 LLButton* btn = new LLButton(
980 LLString(child->getName()) + " tab", 993 LLString(child->getName()) + " tab",
981 btn_rect, 994 btn_rect,
982 tab_img, tab_selected_img, "", 995 "", "", "",
983 &LLTabContainer::onTabBtn, NULL, // set userdata below 996 &LLTabContainer::onTabBtn, NULL, // set userdata below
984 font, 997 font,
985 trimmed_label, trimmed_label ); 998 trimmed_label, trimmed_label );
@@ -987,7 +1000,7 @@ void LLTabContainer::addTabPanel(LLPanel* child,
987 btn->setVisible( FALSE ); 1000 btn->setVisible( FALSE );
988 btn->setToolTip( tooltip ); 1001 btn->setToolTip( tooltip );
989 btn->setScaleImage(TRUE); 1002 btn->setScaleImage(TRUE);
990 btn->setFixedBorder(14, 14); 1003 btn->setImages(tab_img, tab_selected_img);
991 1004
992 // Try to squeeze in a bit more text 1005 // Try to squeeze in a bit more text
993 btn->setLeftHPad( 4 ); 1006 btn->setLeftHPad( 4 );
@@ -1139,7 +1152,7 @@ BOOL LLTabContainer::selectTab(S32 which)
1139 1152
1140 //if( gFocusMgr.childHasKeyboardFocus( this ) ) 1153 //if( gFocusMgr.childHasKeyboardFocus( this ) )
1141 //{ 1154 //{
1142 // gFocusMgr.setKeyboardFocus( NULL, NULL ); 1155 // gFocusMgr.setKeyboardFocus( NULL );
1143 //} 1156 //}
1144 1157
1145 LLTabTuple* selected_tuple = mTabList[which]; 1158 LLTabTuple* selected_tuple = mTabList[which];
@@ -1370,7 +1383,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
1370 { 1383 {
1371 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; 1384 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
1372 gFocusMgr.setMouseCapture(this); 1385 gFocusMgr.setMouseCapture(this);
1373 gFocusMgr.setKeyboardFocus(tab_button, NULL); 1386 gFocusMgr.setKeyboardFocus(tab_button);
1374 } 1387 }
1375 } 1388 }
1376 return handled; 1389 return handled;
@@ -1475,7 +1488,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
1475BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect ) 1488BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect )
1476{ 1489{
1477 BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect ); 1490 BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
1478 if (!handled && mTabList.size() > 0 && getVisible() && pointInView( x, y ) ) 1491 if (!handled && mTabList.size() > 0)
1479 { 1492 {
1480 LLTabTuple* firsttuple = mTabList[0]; 1493 LLTabTuple* firsttuple = mTabList[0];
1481 1494
@@ -1645,12 +1658,12 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
1645 mTotalTabWidth -= tuple->mButton->getRect().getWidth(); 1658 mTotalTabWidth -= tuple->mButton->getRect().getWidth();
1646 1659
1647 S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? 1660 S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
1648 tuple->mButton->getImageOverlay()->getWidth(0) : 1661 tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
1649 0; 1662 0;
1650 1663
1651 tuple->mPadding = image_overlay_width; 1664 tuple->mPadding = image_overlay_width;
1652 1665
1653 tuple->mButton->setRightHPad(tuple->mPadding + LLBUTTON_H_PAD); 1666 tuple->mButton->setRightHPad(6);
1654 tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), 1667 tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
1655 tuple->mButton->getRect().getHeight()); 1668 tuple->mButton->getRect().getHeight());
1656 // add back in button width to total tab strip width 1669 // add back in button width to total tab strip width
diff --git a/linden/indra/llui/lltabcontainer.h b/linden/indra/llui/lltabcontainer.h
index 3f2b1b4..e2770ee 100644
--- a/linden/indra/llui/lltabcontainer.h
+++ b/linden/indra/llui/lltabcontainer.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -54,6 +54,7 @@ public:
54 { 54 {
55 START, 55 START,
56 END, 56 END,
57 LEFT_OF_CURRENT,
57 RIGHT_OF_CURRENT 58 RIGHT_OF_CURRENT
58 } eInsertionPoint; 59 } eInsertionPoint;
59 60
@@ -91,6 +92,8 @@ public:
91 eInsertionPoint insertion_point = END) = 0; 92 eInsertionPoint insertion_point = END) = 0;
92 virtual void addPlaceholder(LLPanel* child, const LLString& label); 93 virtual void addPlaceholder(LLPanel* child, const LLString& label);
93 virtual void lockTabs(S32 num_tabs = 0); 94 virtual void lockTabs(S32 num_tabs = 0);
95 virtual void unlockTabs();
96 S32 getNumLockedTabs() { return mLockedTabCount; }
94 97
95 virtual void enableTabButton(S32 which, BOOL enable); 98 virtual void enableTabButton(S32 which, BOOL enable);
96 99
diff --git a/linden/indra/llui/lltabcontainervertical.cpp b/linden/indra/llui/lltabcontainervertical.cpp
index 5a04417..334cb43 100644
--- a/linden/indra/llui/lltabcontainervertical.cpp
+++ b/linden/indra/llui/lltabcontainervertical.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -185,14 +185,14 @@ void LLTabContainerVertical::addTabPanel(LLPanel* child, const LLString& label,
185 { 185 {
186 LLButton *btn = new LLButton("vert tab button", 186 LLButton *btn = new LLButton("vert tab button",
187 btn_rect, 187 btn_rect,
188 "tab_left.tga", 188 "",
189 "tab_left_selected.tga", 189 "",
190 "", 190 "",
191 &LLTabContainerVertical::onTabBtn, NULL, 191 &LLTabContainerVertical::onTabBtn, NULL,
192 font, 192 font,
193 trimmed_label, trimmed_label); 193 trimmed_label, trimmed_label);
194 btn->setSaveToXML(false); 194 btn->setSaveToXML(false);
195 btn->setFixedBorder(16, 16); 195 btn->setImages("tab_left.tga", "tab_left_selected.tga");
196 btn->setScaleImage(TRUE); 196 btn->setScaleImage(TRUE);
197 btn->setHAlign(LLFontGL::LEFT); 197 btn->setHAlign(LLFontGL::LEFT);
198 btn->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); 198 btn->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
@@ -306,7 +306,7 @@ BOOL LLTabContainerVertical::selectTab(S32 which)
306 306
307 //if( gFocusMgr.childHasKeyboardFocus( this ) ) 307 //if( gFocusMgr.childHasKeyboardFocus( this ) )
308 //{ 308 //{
309 // gFocusMgr.setKeyboardFocus( NULL, NULL ); 309 // gFocusMgr.setKeyboardFocus( NULL );
310 //} 310 //}
311 311
312 LLTabTuple* selected_tuple = mTabList[which]; 312 LLTabTuple* selected_tuple = mTabList[which];
@@ -476,7 +476,7 @@ BOOL LLTabContainerVertical::handleMouseDown( S32 x, S32 y, MASK mask )
476 { 476 {
477 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; 477 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
478 gFocusMgr.setMouseCapture(this); 478 gFocusMgr.setMouseCapture(this);
479 gFocusMgr.setKeyboardFocus(tab_button, NULL); 479 gFocusMgr.setKeyboardFocus(tab_button);
480 } 480 }
481 } 481 }
482 return handled; 482 return handled;
diff --git a/linden/indra/llui/lltabcontainervertical.h b/linden/indra/llui/lltabcontainervertical.h
index bfaf461..e887e53 100644
--- a/linden/indra/llui/lltabcontainervertical.h
+++ b/linden/indra/llui/lltabcontainervertical.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lltextbox.cpp b/linden/indra/llui/lltextbox.cpp
index d2dae30..1422e0a 100644
--- a/linden/indra/llui/lltextbox.cpp
+++ b/linden/indra/llui/lltextbox.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -56,6 +56,7 @@ LLTextBox::LLTextBox(const LLString& name, const LLRect& rect, const LLString& t
56 mBorderVisible( FALSE ), 56 mBorderVisible( FALSE ),
57 mFontStyle(LLFontGL::DROP_SHADOW_SOFT), 57 mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
58 mBorderDropShadowVisible( FALSE ), 58 mBorderDropShadowVisible( FALSE ),
59 mUseEllipses( FALSE ),
59 mHPad(0), 60 mHPad(0),
60 mVPad(0), 61 mVPad(0),
61 mHAlign( LLFontGL::LEFT ), 62 mHAlign( LLFontGL::LEFT ),
@@ -84,6 +85,7 @@ LLTextBox::LLTextBox(const LLString& name, const LLString& text, F32 max_width,
84 mBorderVisible(FALSE), 85 mBorderVisible(FALSE),
85 mFontStyle(LLFontGL::DROP_SHADOW_SOFT), 86 mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
86 mBorderDropShadowVisible(FALSE), 87 mBorderDropShadowVisible(FALSE),
88 mUseEllipses( FALSE ),
87 mHPad(0), 89 mHPad(0),
88 mVPad(0), 90 mVPad(0),
89 mHAlign(LLFontGL::LEFT), 91 mHAlign(LLFontGL::LEFT),
@@ -174,7 +176,7 @@ BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
174 mHasHover = TRUE; // This should be set every frame during a hover. 176 mHasHover = TRUE; // This should be set every frame during a hover.
175 return TRUE; 177 return TRUE;
176 } 178 }
177 return FALSE; 179 return LLView::handleHover(x,y,mask);
178} 180}
179 181
180void LLTextBox::setText(const LLStringExplicit& text) 182void LLTextBox::setText(const LLStringExplicit& text)
@@ -393,7 +395,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
393 mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color, 395 mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
394 mHAlign, mVAlign, 396 mHAlign, mVAlign,
395 mFontStyle, 397 mFontStyle,
396 line_length, mRect.getWidth(), NULL, TRUE ); 398 line_length, mRect.getWidth(), NULL, TRUE, mUseEllipses );
397 cur_pos += line_length + 1; 399 cur_pos += line_length + 1;
398 y -= llfloor(mFontGL->getLineHeight()); 400 y -= llfloor(mFontGL->getLineHeight());
399 } 401 }
@@ -403,7 +405,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
403 mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color, 405 mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
404 mHAlign, mVAlign, 406 mHAlign, mVAlign,
405 mFontStyle, 407 mFontStyle,
406 S32_MAX, mRect.getWidth(), NULL, TRUE); 408 S32_MAX, mRect.getWidth(), NULL, TRUE, mUseEllipses);
407 } 409 }
408} 410}
409 411
@@ -481,7 +483,7 @@ LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
481 text_box->mFontStyle = LLFontGL::getStyleFromString(font_style); 483 text_box->mFontStyle = LLFontGL::getStyleFromString(font_style);
482 } 484 }
483 485
484 BOOL mouse_opaque; 486 BOOL mouse_opaque = text_box->getMouseOpaque();
485 if (node->getAttributeBOOL("mouse_opaque", mouse_opaque)) 487 if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
486 { 488 {
487 text_box->setMouseOpaque(mouse_opaque); 489 text_box->setMouseOpaque(mouse_opaque);
diff --git a/linden/indra/llui/lltextbox.h b/linden/indra/llui/lltextbox.h
index bdcccf7..c8bdfc5 100644
--- a/linden/indra/llui/lltextbox.h
+++ b/linden/indra/llui/lltextbox.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -79,6 +79,7 @@ public:
79 void setText( const LLStringExplicit& text ); 79 void setText( const LLStringExplicit& text );
80 void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.0); 80 void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.0);
81 // default width means use existing control width 81 // default width means use existing control width
82 void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
82 83
83 void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; } 84 void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; }
84 void setBorderVisible(BOOL visible) { mBorderVisible = visible; } 85 void setBorderVisible(BOOL visible) { mBorderVisible = visible; }
@@ -124,6 +125,7 @@ protected:
124 125
125 U8 mFontStyle; // style bit flags for font 126 U8 mFontStyle; // style bit flags for font
126 BOOL mBorderDropShadowVisible; 127 BOOL mBorderDropShadowVisible;
128 BOOL mUseEllipses;
127 129
128 S32 mHPad; 130 S32 mHPad;
129 S32 mVPad; 131 S32 mVPad;
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index b4d693b..ca9ea0a 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -79,6 +79,15 @@ const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
79const S32 CURSOR_THICKNESS = 2; 79const S32 CURSOR_THICKNESS = 2;
80const S32 SPACES_PER_TAB = 4; 80const S32 SPACES_PER_TAB = 4;
81 81
82const F32 PREEDIT_MARKER_BRIGHTNESS = 0.4f;
83const S32 PREEDIT_MARKER_GAP = 1;
84const S32 PREEDIT_MARKER_POSITION = 2;
85const S32 PREEDIT_MARKER_THICKNESS = 1;
86const F32 PREEDIT_STANDOUT_BRIGHTNESS = 0.6f;
87const S32 PREEDIT_STANDOUT_GAP = 1;
88const S32 PREEDIT_STANDOUT_POSITION = 2;
89const S32 PREEDIT_STANDOUT_THICKNESS = 2;
90
82LLColor4 LLTextEditor::mLinkColor = LLColor4::blue; 91LLColor4 LLTextEditor::mLinkColor = LLColor4::blue;
83void (* LLTextEditor::mURLcallback)(const char*) = NULL; 92void (* LLTextEditor::mURLcallback)(const char*) = NULL;
84bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; 93bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
@@ -274,14 +283,14 @@ private:
274LLTextEditor::LLTextEditor( 283LLTextEditor::LLTextEditor(
275 const LLString& name, 284 const LLString& name,
276 const LLRect& rect, 285 const LLRect& rect,
277 S32 max_length, 286 S32 max_length, // In bytes
278 const LLString &default_text, 287 const LLString &default_text,
279 const LLFontGL* font, 288 const LLFontGL* font,
280 BOOL allow_embedded_items) 289 BOOL allow_embedded_items)
281 : 290 :
282 LLUICtrl( name, rect, TRUE, NULL, NULL, FOLLOWS_TOP | FOLLOWS_LEFT ), 291 LLUICtrl( name, rect, TRUE, NULL, NULL, FOLLOWS_TOP | FOLLOWS_LEFT ),
283 mTextIsUpToDate(TRUE), 292 mTextIsUpToDate(TRUE),
284 mMaxTextLength( max_length ), 293 mMaxTextByteLength( max_length ),
285 mBaseDocIsPristine(TRUE), 294 mBaseDocIsPristine(TRUE),
286 mPristineCmd( NULL ), 295 mPristineCmd( NULL ),
287 mLastCmd( NULL ), 296 mLastCmd( NULL ),
@@ -293,6 +302,7 @@ LLTextEditor::LLTextEditor(
293 mOnScrollEndData( NULL ), 302 mOnScrollEndData( NULL ),
294 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), 303 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ),
295 mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ), 304 mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ),
305 mDefaultColor( LLUI::sColorsGroup->getColor( "TextDefaultColor" ) ),
296 mReadOnlyFgColor( LLUI::sColorsGroup->getColor( "TextFgReadOnlyColor" ) ), 306 mReadOnlyFgColor( LLUI::sColorsGroup->getColor( "TextFgReadOnlyColor" ) ),
297 mWriteableBgColor( LLUI::sColorsGroup->getColor( "TextBgWriteableColor" ) ), 307 mWriteableBgColor( LLUI::sColorsGroup->getColor( "TextBgWriteableColor" ) ),
298 mReadOnlyBgColor( LLUI::sColorsGroup->getColor( "TextBgReadOnlyColor" ) ), 308 mReadOnlyBgColor( LLUI::sColorsGroup->getColor( "TextBgReadOnlyColor" ) ),
@@ -301,9 +311,9 @@ LLTextEditor::LLTextEditor(
301 mWordWrap( FALSE ), 311 mWordWrap( FALSE ),
302 mTabToNextField( TRUE ), 312 mTabToNextField( TRUE ),
303 mCommitOnFocusLost( FALSE ), 313 mCommitOnFocusLost( FALSE ),
304 mTakesFocus( TRUE ),
305 mHideScrollbarForShortDocs( FALSE ), 314 mHideScrollbarForShortDocs( FALSE ),
306 mTakesNonScrollClicks( TRUE ), 315 mTakesNonScrollClicks( TRUE ),
316 mTrackBottom( TRUE ),
307 mAllowEmbeddedItems( allow_embedded_items ), 317 mAllowEmbeddedItems( allow_embedded_items ),
308 mAcceptCallingCardNames(FALSE), 318 mAcceptCallingCardNames(FALSE),
309 mHandleEditKeysDirectly( FALSE ), 319 mHandleEditKeysDirectly( FALSE ),
@@ -510,13 +520,27 @@ BOOL LLTextEditor::isPartOfWord(llwchar c) { return (c == '_') || isalnum(c); }
510 520
511 521
512 522
513void LLTextEditor::truncate() 523BOOL LLTextEditor::truncate()
514{ 524{
515 if (mWText.size() > (size_t)mMaxTextLength) 525 BOOL did_truncate = FALSE;
516 { 526
517 LLWString::truncate(mWText, mMaxTextLength); 527 // First rough check - if we're less than 1/4th the size, we're OK
518 mTextIsUpToDate = FALSE; 528 if (mWText.size() >= (size_t) (mMaxTextByteLength / 4))
529 {
530 // Have to check actual byte size
531 S32 utf8_byte_size = wstring_utf8_length( mWText );
532 if ( utf8_byte_size > mMaxTextByteLength )
533 {
534 // Truncate safely in UTF-8
535 std::string temp_utf8_text = wstring_to_utf8str( mWText );
536 temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
537 mWText = utf8str_to_wstring( temp_utf8_text );
538 mTextIsUpToDate = FALSE;
539 did_truncate = TRUE;
540 }
519 } 541 }
542
543 return did_truncate;
520} 544}
521 545
522void LLTextEditor::setText(const LLStringExplicit &utf8str) 546void LLTextEditor::setText(const LLStringExplicit &utf8str)
@@ -750,12 +774,12 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
750 return cursorPos; 774 return cursorPos;
751} 775}
752 776
753S32 LLTextEditor::getLineCount() 777S32 LLTextEditor::getLineCount() const
754{ 778{
755 return mLineStartList.size(); 779 return mLineStartList.size();
756} 780}
757 781
758S32 LLTextEditor::getLineStart( S32 line ) 782S32 LLTextEditor::getLineStart( S32 line ) const
759{ 783{
760 S32 num_lines = getLineCount(); 784 S32 num_lines = getLineCount();
761 if (num_lines == 0) 785 if (num_lines == 0)
@@ -1118,46 +1142,42 @@ void LLTextEditor::selectAll()
1118 1142
1119BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) 1143BOOL LLTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
1120{ 1144{
1121 if (pointInView(x, y) && getVisible()) 1145 for ( child_list_const_iter_t child_it = getChildList()->begin();
1146 child_it != getChildList()->end(); ++child_it)
1122 { 1147 {
1123 for ( child_list_const_iter_t child_it = getChildList()->begin(); 1148 LLView* viewp = *child_it;
1124 child_it != getChildList()->end(); ++child_it) 1149 S32 local_x = x - viewp->getRect().mLeft;
1125 { 1150 S32 local_y = y - viewp->getRect().mBottom;
1126 LLView* viewp = *child_it; 1151 if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
1127 S32 local_x = x - viewp->getRect().mLeft;
1128 S32 local_y = y - viewp->getRect().mBottom;
1129 if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
1130 {
1131 return TRUE;
1132 }
1133 }
1134
1135 if( mSegments.empty() )
1136 { 1152 {
1137 return TRUE; 1153 return TRUE;
1138 } 1154 }
1155 }
1139 1156
1140 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); 1157 if( mSegments.empty() )
1141 if( cur_segment ) 1158 {
1142 { 1159 return TRUE;
1143 BOOL has_tool_tip = FALSE; 1160 }
1144 has_tool_tip = cur_segment->getToolTip( msg );
1145 1161
1146 if( has_tool_tip ) 1162 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
1147 { 1163 if( cur_segment )
1148 // Just use a slop area around the cursor 1164 {
1149 // Convert rect local to screen coordinates 1165 BOOL has_tool_tip = FALSE;
1150 S32 SLOP = 8; 1166 has_tool_tip = cur_segment->getToolTip( msg );
1151 localPointToScreen( 1167
1152 x - SLOP, y - SLOP, 1168 if( has_tool_tip )
1153 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); 1169 {
1154 sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP; 1170 // Just use a slop area around the cursor
1155 sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP; 1171 // Convert rect local to screen coordinates
1156 } 1172 S32 SLOP = 8;
1173 localPointToScreen(
1174 x - SLOP, y - SLOP,
1175 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
1176 sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
1177 sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
1157 } 1178 }
1158 return TRUE;
1159 } 1179 }
1160 return FALSE; 1180 return TRUE;
1161} 1181}
1162 1182
1163BOOL LLTextEditor::handleScrollWheel(S32 x, S32 y, S32 clicks) 1183BOOL LLTextEditor::handleScrollWheel(S32 x, S32 y, S32 clicks)
@@ -1240,7 +1260,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
1240 handled = TRUE; 1260 handled = TRUE;
1241 } 1261 }
1242 1262
1243 if (mTakesFocus) 1263 if (hasTabStop())
1244 { 1264 {
1245 setFocus( TRUE ); 1265 setFocus( TRUE );
1246 handled = TRUE; 1266 handled = TRUE;
@@ -1413,11 +1433,6 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
1413 1433
1414 if( !handled && mTakesNonScrollClicks) 1434 if( !handled && mTakesNonScrollClicks)
1415 { 1435 {
1416 if (mTakesFocus)
1417 {
1418 setFocus( TRUE );
1419 }
1420
1421 setCursorAtLocalPos( x, y, FALSE ); 1436 setCursorAtLocalPos( x, y, FALSE );
1422 deselect(); 1437 deselect();
1423 1438
@@ -1604,7 +1619,7 @@ void LLTextEditor::removeChar()
1604// Add a single character to the text 1619// Add a single character to the text
1605S32 LLTextEditor::addChar(S32 pos, llwchar wc) 1620S32 LLTextEditor::addChar(S32 pos, llwchar wc)
1606{ 1621{
1607 if ((S32)mWText.length() == mMaxTextLength) 1622 if ( (wstring_utf8_length( mWText ) + wchar_utf8_length( wc )) >= mMaxTextByteLength)
1608 { 1623 {
1609 make_ui_sound("UISndBadKeystroke"); 1624 make_ui_sound("UISndBadKeystroke");
1610 return 0; 1625 return 0;
@@ -2490,11 +2505,16 @@ void LLTextEditor::redo()
2490 } 2505 }
2491} 2506}
2492 2507
2508void LLTextEditor::onFocusReceived()
2509{
2510 LLUICtrl::onFocusReceived();
2511 updateAllowingLanguageInput();
2512}
2493 2513
2494// virtual, from LLView 2514// virtual, from LLView
2495void LLTextEditor::onFocusLost() 2515void LLTextEditor::onFocusLost()
2496{ 2516{
2497 getWindow()->allowLanguageTextInput(FALSE); 2517 updateAllowingLanguageInput();
2498 2518
2499 // Route menu back to the default 2519 // Route menu back to the default
2500 if( gEditMenuHandler == this ) 2520 if( gEditMenuHandler == this )
@@ -2521,6 +2541,7 @@ void LLTextEditor::setEnabled(BOOL enabled)
2521 { 2541 {
2522 mReadOnly = read_only; 2542 mReadOnly = read_only;
2523 updateSegments(); 2543 updateSegments();
2544 updateAllowingLanguageInput();
2524 } 2545 }
2525} 2546}
2526 2547
@@ -2825,6 +2846,100 @@ void LLTextEditor::drawCursor()
2825 } 2846 }
2826} 2847}
2827 2848
2849void LLTextEditor::drawPreeditMarker()
2850{
2851 if (!hasPreeditString())
2852 {
2853 return;
2854 }
2855
2856 const llwchar *text = mWText.c_str();
2857 const S32 text_len = getLength();
2858 const S32 num_lines = getLineCount();
2859
2860 S32 cur_line = mScrollbar->getDocPos();
2861 if (cur_line >= num_lines)
2862 {
2863 return;
2864 }
2865
2866 const S32 line_height = llround( mGLFont->getLineHeight() );
2867
2868 S32 line_start = getLineStart(cur_line);
2869 S32 line_y = mTextRect.mTop - line_height;
2870 while((mTextRect.mBottom <= line_y) && (num_lines > cur_line))
2871 {
2872 S32 next_start = -1;
2873 S32 line_end = text_len;
2874
2875 if ((cur_line + 1) < num_lines)
2876 {
2877 next_start = getLineStart(cur_line + 1);
2878 line_end = next_start;
2879 }
2880 if ( text[line_end-1] == '\n' )
2881 {
2882 --line_end;
2883 }
2884
2885 // Does this line contain preedits?
2886 if (line_start >= mPreeditPositions.back())
2887 {
2888 // We have passed the preedits.
2889 break;
2890 }
2891 if (line_end > mPreeditPositions.front())
2892 {
2893 for (U32 i = 0; i < mPreeditStandouts.size(); i++)
2894 {
2895 S32 left = mPreeditPositions[i];
2896 S32 right = mPreeditPositions[i + 1];
2897 if (right <= line_start || left >= line_end)
2898 {
2899 continue;
2900 }
2901
2902 S32 preedit_left = mTextRect.mLeft;
2903 if (left > line_start)
2904 {
2905 preedit_left += mGLFont->getWidth(text, line_start, left - line_start, mAllowEmbeddedItems);
2906 }
2907 S32 preedit_right = mTextRect.mLeft;
2908 if (right < line_end)
2909 {
2910 preedit_right += mGLFont->getWidth(text, line_start, right - line_start, mAllowEmbeddedItems);
2911 }
2912 else
2913 {
2914 preedit_right += mGLFont->getWidth(text, line_start, line_end - line_start, mAllowEmbeddedItems);
2915 }
2916
2917 if (mPreeditStandouts[i])
2918 {
2919 gl_rect_2d(preedit_left + PREEDIT_STANDOUT_GAP,
2920 line_y + PREEDIT_STANDOUT_POSITION,
2921 preedit_right - PREEDIT_STANDOUT_GAP - 1,
2922 line_y + PREEDIT_STANDOUT_POSITION - PREEDIT_STANDOUT_THICKNESS,
2923 (mCursorColor * PREEDIT_STANDOUT_BRIGHTNESS + mWriteableBgColor * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
2924 }
2925 else
2926 {
2927 gl_rect_2d(preedit_left + PREEDIT_MARKER_GAP,
2928 line_y + PREEDIT_MARKER_POSITION,
2929 preedit_right - PREEDIT_MARKER_GAP - 1,
2930 line_y + PREEDIT_MARKER_POSITION - PREEDIT_MARKER_THICKNESS,
2931 (mCursorColor * PREEDIT_MARKER_BRIGHTNESS + mWriteableBgColor * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
2932 }
2933 }
2934 }
2935
2936 // move down one line
2937 line_y -= line_height;
2938 line_start = next_start;
2939 cur_line++;
2940 }
2941}
2942
2828 2943
2829void LLTextEditor::drawText() 2944void LLTextEditor::drawText()
2830{ 2945{
@@ -3025,6 +3140,7 @@ void LLTextEditor::draw()
3025 3140
3026 drawBackground(); 3141 drawBackground();
3027 drawSelectionBackground(); 3142 drawSelectionBackground();
3143 drawPreeditMarker();
3028 drawText(); 3144 drawText();
3029 drawCursor(); 3145 drawCursor();
3030 3146
@@ -3036,6 +3152,9 @@ void LLTextEditor::draw()
3036 } 3152 }
3037 LLView::draw(); // Draw children (scrollbar and border) 3153 LLView::draw(); // Draw children (scrollbar and border)
3038 } 3154 }
3155
3156 // remember if we are supposed to be at the bottom of the buffer
3157 mScrolledToBottom = isScrolledToBottom();
3039} 3158}
3040 3159
3041void LLTextEditor::reportBadKeystroke() 3160void LLTextEditor::reportBadKeystroke()
@@ -3067,10 +3186,10 @@ void LLTextEditor::setFocus( BOOL new_state )
3067 // Don't change anything if the focus state didn't change 3186 // Don't change anything if the focus state didn't change
3068 if (new_state == old_state) return; 3187 if (new_state == old_state) return;
3069 3188
3070 // Notify early if we are loosing focus. 3189 // Notify early if we are losing focus.
3071 if (!new_state) 3190 if (!new_state)
3072 { 3191 {
3073 getWindow()->allowLanguageTextInput(FALSE); 3192 getWindow()->allowLanguageTextInput(this, FALSE);
3074 } 3193 }
3075 3194
3076 LLUICtrl::setFocus( new_state ); 3195 LLUICtrl::setFocus( new_state );
@@ -3093,12 +3212,6 @@ void LLTextEditor::setFocus( BOOL new_state )
3093 3212
3094 endSelection(); 3213 endSelection();
3095 } 3214 }
3096
3097 // Notify late if we are gaining focus.
3098 if (new_state && !mReadOnly)
3099 {
3100 getWindow()->allowLanguageTextInput(TRUE);
3101 }
3102} 3215}
3103 3216
3104BOOL LLTextEditor::acceptsTextInput() const 3217BOOL LLTextEditor::acceptsTextInput() const
@@ -3210,6 +3323,17 @@ void LLTextEditor::changeLine( S32 delta )
3210 unbindEmbeddedChars( mGLFont ); 3323 unbindEmbeddedChars( mGLFont );
3211} 3324}
3212 3325
3326BOOL LLTextEditor::isScrolledToTop()
3327{
3328 return mScrollbar->isAtBeginning();
3329}
3330
3331BOOL LLTextEditor::isScrolledToBottom()
3332{
3333 return mScrollbar->isAtEnd();
3334}
3335
3336
3213void LLTextEditor::startOfLine() 3337void LLTextEditor::startOfLine()
3214{ 3338{
3215 S32 line, offset; 3339 S32 line, offset;
@@ -3330,6 +3454,13 @@ void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
3330{ 3454{
3331 LLView::reshape( width, height, called_from_parent ); 3455 LLView::reshape( width, height, called_from_parent );
3332 3456
3457 // if scrolled to bottom, stay at bottom
3458 // unless user is editing text
3459 if (mScrolledToBottom && mTrackBottom && !hasFocus())
3460 {
3461 endOfDoc();
3462 }
3463
3333 updateTextRect(); 3464 updateTextRect();
3334 3465
3335 S32 line_height = llround( mGLFont->getLineHeight() ); 3466 S32 line_height = llround( mGLFont->getLineHeight() );
@@ -3540,22 +3671,20 @@ void LLTextEditor::removeTextFromEnd(S32 num_chars)
3540 3671
3541S32 LLTextEditor::insertStringNoUndo(const S32 pos, const LLWString &wstr) 3672S32 LLTextEditor::insertStringNoUndo(const S32 pos, const LLWString &wstr)
3542{ 3673{
3543 S32 len = mWText.length(); 3674 S32 old_len = mWText.length(); // length() returns character length
3544 S32 s_len = wstr.length(); 3675 S32 insert_len = wstr.length();
3545 S32 new_len = len + s_len; 3676
3546 if( new_len > mMaxTextLength ) 3677 mWText.insert(pos, wstr);
3547 { 3678 mTextIsUpToDate = FALSE;
3548 new_len = mMaxTextLength;
3549 3679
3680 if ( truncate() )
3681 {
3550 // The user's not getting everything he's hoping for 3682 // The user's not getting everything he's hoping for
3551 make_ui_sound("UISndBadKeystroke"); 3683 make_ui_sound("UISndBadKeystroke");
3684 insert_len = mWText.length() - old_len;
3552 } 3685 }
3553 3686
3554 mWText.insert(pos, wstr); 3687 return insert_len;
3555 mTextIsUpToDate = FALSE;
3556 truncate();
3557
3558 return new_len - len;
3559} 3688}
3560 3689
3561S32 LLTextEditor::removeStringNoUndo(S32 pos, S32 length) 3690S32 LLTextEditor::removeStringNoUndo(S32 pos, S32 length)
@@ -3671,7 +3800,7 @@ void LLTextEditor::loadKeywords(const LLString& filename,
3671 mKeywords.addToken(LLKeywordToken::WORD, name.c_str(), color, tooltips.get(i) ); 3800 mKeywords.addToken(LLKeywordToken::WORD, name.c_str(), color, tooltips.get(i) );
3672 } 3801 }
3673 3802
3674 mKeywords.findSegments( &mSegments, mWText ); 3803 mKeywords.findSegments( &mSegments, mWText, mDefaultColor );
3675 3804
3676 llassert( mSegments.front()->getStart() == 0 ); 3805 llassert( mSegments.front()->getStart() == 0 );
3677 llassert( mSegments.back()->getEnd() == getLength() ); 3806 llassert( mSegments.back()->getEnd() == getLength() );
@@ -3683,7 +3812,7 @@ void LLTextEditor::updateSegments()
3683 if (mKeywords.isLoaded()) 3812 if (mKeywords.isLoaded())
3684 { 3813 {
3685 // HACK: No non-ascii keywords for now 3814 // HACK: No non-ascii keywords for now
3686 mKeywords.findSegments(&mSegments, mWText); 3815 mKeywords.findSegments(&mSegments, mWText, mDefaultColor);
3687 } 3816 }
3688 else if (mAllowEmbeddedItems) 3817 else if (mAllowEmbeddedItems)
3689 { 3818 {
@@ -3920,7 +4049,7 @@ BOOL LLTextEditor::importBuffer(const LLString& buffer )
3920 return FALSE; 4049 return FALSE;
3921 } 4050 }
3922 4051
3923 if( text_len > mMaxTextLength ) 4052 if( text_len > mMaxTextByteLength )
3924 { 4053 {
3925 llwarns << "Invalid Linden text length: " << text_len << llendl; 4054 llwarns << "Invalid Linden text length: " << text_len << llendl;
3926 return FALSE; 4055 return FALSE;
@@ -4064,6 +4193,7 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const
4064 4193
4065 addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor"); 4194 addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor");
4066 addColorXML(node, mFgColor, "text_color", "TextFgColor"); 4195 addColorXML(node, mFgColor, "text_color", "TextFgColor");
4196 addColorXML(node, mDefaultColor, "text_default_color", "TextDefaultColor");
4067 addColorXML(node, mReadOnlyFgColor, "text_readonly_color", "TextFgReadOnlyColor"); 4197 addColorXML(node, mReadOnlyFgColor, "text_readonly_color", "TextFgReadOnlyColor");
4068 addColorXML(node, mReadOnlyBgColor, "bg_readonly_color", "TextBgReadOnlyColor"); 4198 addColorXML(node, mReadOnlyBgColor, "bg_readonly_color", "TextBgReadOnlyColor");
4069 addColorXML(node, mWriteableBgColor, "bg_writeable_color", "TextBgWriteableColor"); 4199 addColorXML(node, mWriteableBgColor, "bg_writeable_color", "TextBgWriteableColor");
@@ -4118,6 +4248,8 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node)
4118 node->getAttributeBOOL("word_wrap", word_wrap); 4248 node->getAttributeBOOL("word_wrap", word_wrap);
4119 setWordWrap(word_wrap); 4249 setWordWrap(word_wrap);
4120 4250
4251 node->getAttributeBOOL("track_bottom", mTrackBottom);
4252
4121 LLColor4 color; 4253 LLColor4 color;
4122 if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color)) 4254 if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color))
4123 { 4255 {
@@ -4281,3 +4413,262 @@ BOOL LLTextEditor::findHTML(const LLString &line, S32 *begin, S32 *end)
4281 } 4413 }
4282 return matched; 4414 return matched;
4283} 4415}
4416
4417
4418
4419void LLTextEditor::updateAllowingLanguageInput()
4420{
4421 if (hasFocus() && !mReadOnly)
4422 {
4423 getWindow()->allowLanguageTextInput(this, TRUE);
4424 }
4425 else
4426 {
4427 getWindow()->allowLanguageTextInput(this, FALSE);
4428 }
4429}
4430
4431// Preedit is managed off the undo/redo command stack.
4432
4433BOOL LLTextEditor::hasPreeditString() const
4434{
4435 return (mPreeditPositions.size() > 1);
4436}
4437
4438void LLTextEditor::resetPreedit()
4439{
4440 if (hasPreeditString())
4441 {
4442 mCursorPos = mPreeditPositions.front();
4443 removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
4444 insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
4445
4446 mPreeditWString.clear();
4447 mPreeditOverwrittenWString.clear();
4448 mPreeditPositions.clear();
4449
4450 updateLineStartList();
4451 setCursorPos(mCursorPos);
4452 // updateScrollFromCursor();
4453 }
4454}
4455
4456void LLTextEditor::updatePreedit(const LLWString &preedit_string,
4457 const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position)
4458{
4459 // Just in case.
4460 if (mReadOnly)
4461 {
4462 return;
4463 }
4464
4465 if (hasSelection())
4466 {
4467 if (hasPreeditString())
4468 {
4469 llwarns << "Preedit and selection!" << llendl;
4470 deselect();
4471 }
4472 else
4473 {
4474 deleteSelection(TRUE);
4475 }
4476 }
4477
4478 getWindow()->hideCursorUntilMouseMove();
4479
4480 S32 insert_preedit_at = mCursorPos;
4481 if (hasPreeditString())
4482 {
4483 insert_preedit_at = mPreeditPositions.front();
4484 removeStringNoUndo(insert_preedit_at, mPreeditPositions.back() - insert_preedit_at);
4485 insertStringNoUndo(insert_preedit_at, mPreeditOverwrittenWString);
4486 }
4487
4488 mPreeditWString = preedit_string;
4489 mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
4490 S32 position = insert_preedit_at;
4491 for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++)
4492 {
4493 mPreeditPositions[i] = position;
4494 position += preedit_segment_lengths[i];
4495 }
4496 mPreeditPositions.back() = position;
4497
4498 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
4499 {
4500 mPreeditOverwrittenWString = getWSubString(insert_preedit_at, mPreeditWString.length());
4501 removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
4502 }
4503 else
4504 {
4505 mPreeditOverwrittenWString.clear();
4506 }
4507 insertStringNoUndo(insert_preedit_at, mPreeditWString);
4508
4509 mPreeditStandouts = preedit_standouts;
4510
4511 updateLineStartList();
4512 setCursorPos(insert_preedit_at + caret_position);
4513 // updateScrollFromCursor();
4514
4515 // Update of the preedit should be caused by some key strokes.
4516 mKeystrokeTimer.reset();
4517}
4518
4519BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const
4520{
4521 if (control)
4522 {
4523 LLRect control_rect_screen;
4524 localRectToScreen(mTextRect, &control_rect_screen);
4525 LLUI::screenRectToGL(control_rect_screen, control);
4526 }
4527
4528 S32 preedit_left_position, preedit_right_position;
4529 if (hasPreeditString())
4530 {
4531 preedit_left_position = mPreeditPositions.front();
4532 preedit_right_position = mPreeditPositions.back();
4533 }
4534 else
4535 {
4536 preedit_left_position = preedit_right_position = mCursorPos;
4537 }
4538
4539 const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos);
4540 if (query < preedit_left_position || query > preedit_right_position)
4541 {
4542 return FALSE;
4543 }
4544
4545 const S32 first_visible_line = mScrollbar->getDocPos();
4546 if (query < getLineStart(first_visible_line))
4547 {
4548 return FALSE;
4549 }
4550
4551 S32 current_line = first_visible_line;
4552 S32 current_line_start, current_line_end;
4553 for (;;)
4554 {
4555 current_line_start = getLineStart(current_line);
4556 current_line_end = getLineStart(current_line + 1);
4557 if (query >= current_line_start && query < current_line_end)
4558 {
4559 break;
4560 }
4561 if (current_line_start == current_line_end)
4562 {
4563 // We have reached on the last line. The query position must be here.
4564 break;
4565 }
4566 current_line++;
4567 }
4568
4569 const llwchar * const text = mWText.c_str();
4570 const S32 line_height = llround(mGLFont->getLineHeight());
4571
4572 if (coord)
4573 {
4574 const S32 query_x = mTextRect.mLeft + mGLFont->getWidth(text, current_line_start, query - current_line_start, mAllowEmbeddedItems);
4575 const S32 query_y = mTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
4576 S32 query_screen_x, query_screen_y;
4577 localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
4578 LLUI::screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
4579 }
4580
4581 if (bounds)
4582 {
4583 S32 preedit_left = mTextRect.mLeft;
4584 if (preedit_left_position > current_line_start)
4585 {
4586 preedit_left += mGLFont->getWidth(text, current_line_start, preedit_left_position - current_line_start, mAllowEmbeddedItems);
4587 }
4588
4589 S32 preedit_right = mTextRect.mLeft;
4590 if (preedit_right_position < current_line_end)
4591 {
4592 preedit_right += mGLFont->getWidth(text, current_line_start, preedit_right_position - current_line_start, mAllowEmbeddedItems);
4593 }
4594 else
4595 {
4596 preedit_right += mGLFont->getWidth(text, current_line_start, current_line_end - current_line_start, mAllowEmbeddedItems);
4597 }
4598
4599 const S32 preedit_top = mTextRect.mTop - (current_line - first_visible_line) * line_height;
4600 const S32 preedit_bottom = preedit_top - line_height;
4601
4602 const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
4603 LLRect preedit_rect_screen;
4604 localRectToScreen(preedit_rect_local, &preedit_rect_screen);
4605 LLUI::screenRectToGL(preedit_rect_screen, bounds);
4606 }
4607
4608 return TRUE;
4609}
4610
4611void LLTextEditor::getSelectionRange(S32 *position, S32 *length) const
4612{
4613 if (hasSelection())
4614 {
4615 *position = llmin(mSelectionStart, mSelectionEnd);
4616 *length = llabs(mSelectionStart - mSelectionEnd);
4617 }
4618 else
4619 {
4620 *position = mCursorPos;
4621 *length = 0;
4622 }
4623}
4624
4625void LLTextEditor::getPreeditRange(S32 *position, S32 *length) const
4626{
4627 if (hasPreeditString())
4628 {
4629 *position = mPreeditPositions.front();
4630 *length = mPreeditPositions.back() - mPreeditPositions.front();
4631 }
4632 else
4633 {
4634 *position = mCursorPos;
4635 *length = 0;
4636 }
4637}
4638
4639void LLTextEditor::markAsPreedit(S32 position, S32 length)
4640{
4641 deselect();
4642 setCursorPos(position);
4643 if (hasPreeditString())
4644 {
4645 llwarns << "markAsPreedit invoked when hasPreeditString is true." << llendl;
4646 }
4647 mPreeditWString = LLWString( mWText, position, length );
4648 if (length > 0)
4649 {
4650 mPreeditPositions.resize(2);
4651 mPreeditPositions[0] = position;
4652 mPreeditPositions[1] = position + length;
4653 mPreeditStandouts.resize(1);
4654 mPreeditStandouts[0] = FALSE;
4655 }
4656 else
4657 {
4658 mPreeditPositions.clear();
4659 mPreeditStandouts.clear();
4660 }
4661 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
4662 {
4663 mPreeditOverwrittenWString = mPreeditWString;
4664 }
4665 else
4666 {
4667 mPreeditOverwrittenWString.clear();
4668 }
4669}
4670
4671S32 LLTextEditor::getPreeditFontSize() const
4672{
4673 return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
4674}
diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h
index 33ec1c6..4c92297 100644
--- a/linden/indra/llui/lltexteditor.h
+++ b/linden/indra/llui/lltexteditor.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -43,6 +43,8 @@
43#include "lleditmenuhandler.h" 43#include "lleditmenuhandler.h"
44#include "lldarray.h" 44#include "lldarray.h"
45 45
46#include "llpreeditor.h"
47
46class LLFontGL; 48class LLFontGL;
47class LLScrollbar; 49class LLScrollbar;
48class LLViewBorder; 50class LLViewBorder;
@@ -64,7 +66,7 @@ const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1;
64class LLTextSegment; 66class LLTextSegment;
65class LLTextCmd; 67class LLTextCmd;
66 68
67class LLTextEditor : public LLUICtrl, LLEditMenuHandler 69class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor
68{ 70{
69 friend class LLTextCmd; 71 friend class LLTextCmd;
70public: 72public:
@@ -104,6 +106,7 @@ public:
104 // view overrides 106 // view overrides
105 virtual void reshape(S32 width, S32 height, BOOL called_from_parent); 107 virtual void reshape(S32 width, S32 height, BOOL called_from_parent);
106 virtual void draw(); 108 virtual void draw();
109 virtual void onFocusReceived();
107 virtual void onFocusLost(); 110 virtual void onFocusLost();
108 virtual void setEnabled(BOOL enabled); 111 virtual void setEnabled(BOOL enabled);
109 112
@@ -184,6 +187,7 @@ public:
184 187
185 void setCursorColor(const LLColor4& c) { mCursorColor = c; } 188 void setCursorColor(const LLColor4& c) { mCursorColor = c; }
186 void setFgColor( const LLColor4& c ) { mFgColor = c; } 189 void setFgColor( const LLColor4& c ) { mFgColor = c; }
190 void setTextDefaultColor( const LLColor4& c ) { mDefaultColor = c; }
187 void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; } 191 void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; }
188 void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; } 192 void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; }
189 void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; } 193 void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; }
@@ -203,13 +207,13 @@ public:
203 void setTabToNextField(BOOL b) { mTabToNextField = b; } 207 void setTabToNextField(BOOL b) { mTabToNextField = b; }
204 void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; } 208 void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; }
205 209
206 // If takes focus, will take keyboard focus on click.
207 void setTakesFocus(BOOL b) { mTakesFocus = b; }
208
209 // Hack to handle Notecards 210 // Hack to handle Notecards
210 virtual BOOL importBuffer(const LLString& buffer ); 211 virtual BOOL importBuffer(const LLString& buffer );
211 virtual BOOL exportBuffer(LLString& buffer ); 212 virtual BOOL exportBuffer(LLString& buffer );
212 213
214 // If takes focus, will take keyboard focus on click.
215 void setTakesFocus(BOOL b) { mTakesFocus = b; }
216
213 void setSourceID(const LLUUID& id) { mSourceID = id; } 217 void setSourceID(const LLUUID& id) { mSourceID = id; }
214 void setAcceptCallingCardNames(BOOL enable) { mAcceptCallingCardNames = enable; } 218 void setAcceptCallingCardNames(BOOL enable) { mAcceptCallingCardNames = enable; }
215 219
@@ -234,13 +238,17 @@ public:
234 void setText(const LLStringExplicit &utf8str); 238 void setText(const LLStringExplicit &utf8str);
235 void setWText(const LLWString &wtext); 239 void setWText(const LLWString &wtext);
236 240
237 S32 getMaxLength() const { return mMaxTextLength; } 241 // Returns byte length limit
242 S32 getMaxLength() const { return mMaxTextByteLength; }
238 243
239 // Change cursor 244 // Change cursor
240 void startOfLine(); 245 void startOfLine();
241 void endOfLine(); 246 void endOfLine();
242 void endOfDoc(); 247 void endOfDoc();
243 248
249 BOOL isScrolledToTop();
250 BOOL isScrolledToBottom();
251
244 // Getters 252 // Getters
245 const LLWString& getWText() const; 253 const LLWString& getWText() const;
246 llwchar getWChar(S32 pos); 254 llwchar getWChar(S32 pos);
@@ -259,6 +267,7 @@ protected:
259 void drawCursor(); 267 void drawCursor();
260 void drawText(); 268 void drawText();
261 void drawClippedSegment(const LLWString &wtext, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyle& color, F32* right_x); 269 void drawClippedSegment(const LLWString &wtext, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyle& color, F32* right_x);
270 void drawPreeditMarker();
262 271
263 void updateLineStartList(S32 startpos = 0); 272 void updateLineStartList(S32 startpos = 0);
264 void updateScrollFromCursor(); 273 void updateScrollFromCursor();
@@ -267,7 +276,7 @@ protected:
267 void pruneSegments(); 276 void pruneSegments();
268 277
269 void assignEmbedded(const LLString &s); 278 void assignEmbedded(const LLString &s);
270 void truncate(); 279 BOOL truncate(); // Returns true if truncation occurs
271 280
272 static BOOL isPartOfWord(llwchar c); 281 static BOOL isPartOfWord(llwchar c);
273 282
@@ -291,7 +300,7 @@ protected:
291 BOOL handleControlKey(const KEY key, const MASK mask); 300 BOOL handleControlKey(const KEY key, const MASK mask);
292 BOOL handleEditKey(const KEY key, const MASK mask); 301 BOOL handleEditKey(const KEY key, const MASK mask);
293 302
294 BOOL hasSelection() { return (mSelectionStart !=mSelectionEnd); } 303 BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
295 BOOL selectionContainsLineBreaks(); 304 BOOL selectionContainsLineBreaks();
296 void startSelection(); 305 void startSelection();
297 void endSelection(); 306 void endSelection();
@@ -300,8 +309,8 @@ protected:
300 S32 prevWordPos(S32 cursorPos) const; 309 S32 prevWordPos(S32 cursorPos) const;
301 S32 nextWordPos(S32 cursorPos) const; 310 S32 nextWordPos(S32 cursorPos) const;
302 311
303 S32 getLineCount(); 312 S32 getLineCount() const;
304 S32 getLineStart( S32 line ); 313 S32 getLineStart( S32 line ) const;
305 void getLineAndOffset(S32 pos, S32* linep, S32* offsetp); 314 void getLineAndOffset(S32 pos, S32* linep, S32* offsetp);
306 S32 getPos(S32 line, S32 offset); 315 S32 getPos(S32 line, S32 offset);
307 316
@@ -338,6 +347,20 @@ protected:
338 S32 removeStringNoUndo(S32 pos, S32 length); 347 S32 removeStringNoUndo(S32 pos, S32 length);
339 S32 overwriteCharNoUndo(S32 pos, llwchar wc); 348 S32 overwriteCharNoUndo(S32 pos, llwchar wc);
340 349
350protected:
351 void updateAllowingLanguageInput();
352 BOOL hasPreeditString() const;
353
354 // Overrides LLPreeditor
355 virtual void resetPreedit();
356 virtual void updatePreedit(const LLWString &preedit_string,
357 const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position);
358 virtual void markAsPreedit(S32 position, S32 length);
359 virtual void getPreeditRange(S32 *position, S32 *length) const;
360 virtual void getSelectionRange(S32 *position, S32 *length) const;
361 virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
362 virtual S32 getPreeditFontSize() const;
363
341public: 364public:
342 LLKeywords mKeywords; 365 LLKeywords mKeywords;
343 static LLColor4 mLinkColor; 366 static LLColor4 mLinkColor;
@@ -349,7 +372,7 @@ protected:
349 mutable LLString mUTF8Text; 372 mutable LLString mUTF8Text;
350 mutable BOOL mTextIsUpToDate; 373 mutable BOOL mTextIsUpToDate;
351 374
352 S32 mMaxTextLength; // Maximum length mText is allowed to be 375 S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
353 376
354 const LLFontGL* mGLFont; 377 const LLFontGL* mGLFont;
355 378
@@ -407,6 +430,7 @@ protected:
407 LLColor4 mCursorColor; 430 LLColor4 mCursorColor;
408 431
409 LLColor4 mFgColor; 432 LLColor4 mFgColor;
433 LLColor4 mDefaultColor;
410 LLColor4 mReadOnlyFgColor; 434 LLColor4 mReadOnlyFgColor;
411 LLColor4 mWriteableBgColor; 435 LLColor4 mWriteableBgColor;
412 LLColor4 mReadOnlyBgColor; 436 LLColor4 mReadOnlyBgColor;
@@ -420,6 +444,8 @@ protected:
420 BOOL mTakesFocus; 444 BOOL mTakesFocus;
421 BOOL mHideScrollbarForShortDocs; 445 BOOL mHideScrollbarForShortDocs;
422 BOOL mTakesNonScrollClicks; 446 BOOL mTakesNonScrollClicks;
447 BOOL mTrackBottom; // if true, keeps scroll position at bottom during resize
448 BOOL mScrolledToBottom;
423 449
424 BOOL mAllowEmbeddedItems; 450 BOOL mAllowEmbeddedItems;
425 451
@@ -439,6 +465,11 @@ protected:
439 465
440 BOOL mParseHTML; 466 BOOL mParseHTML;
441 LLString mHTML; 467 LLString mHTML;
468
469 LLWString mPreeditWString;
470 LLWString mPreeditOverwrittenWString;
471 std::vector<S32> mPreeditPositions;
472 std::vector<BOOL> mPreeditStandouts;
442}; 473};
443 474
444class LLTextSegment 475class LLTextSegment
diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp
index 96f293e..f6ce985 100644
--- a/linden/indra/llui/llui.cpp
+++ b/linden/indra/llui/llui.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -79,7 +79,7 @@ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
79LLWindow* LLUI::sWindow = NULL; 79LLWindow* LLUI::sWindow = NULL;
80LLHtmlHelp* LLUI::sHtmlHelp = NULL; 80LLHtmlHelp* LLUI::sHtmlHelp = NULL;
81BOOL LLUI::sShowXUINames = FALSE; 81BOOL LLUI::sShowXUINames = FALSE;
82std::stack<LLRect> LLUI::sClipRectStack; 82std::stack<LLRect> LLScreenClipRect::sClipRectStack;
83 83
84// 84//
85// Functions 85// Functions
@@ -410,39 +410,76 @@ void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max
410} 410}
411 411
412 412
413void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color ) 413void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect )
414{ 414{
415 gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color ); 415 if (NULL == image)
416 {
417 llwarns << "image == NULL; aborting function" << llendl;
418 return;
419 }
420 gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
416} 421}
417 422
418void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color) 423void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
419{ 424{
420 gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color ); 425 if (NULL == image)
426 {
427 llwarns << "image == NULL; aborting function" << llendl;
428 return;
429 }
430 gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
421} 431}
422 432
423void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color) 433void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
424{ 434{
425 stop_glerror();
426 F32 border_scale = 1.f;
427
428 if (NULL == image) 435 if (NULL == image)
429 { 436 {
430 llwarns << "image == NULL; aborting function" << llendl; 437 llwarns << "image == NULL; aborting function" << llendl;
431 return; 438 return;
432 } 439 }
433 440
434 if (border_height * 2 > height) 441 // scale screen size of borders down
435 { 442 F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
436 border_scale = (F32)height / ((F32)border_height * 2.f); 443 F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
437 } 444
438 if (border_width * 2 > width) 445 LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
446 gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
447}
448
449void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect)
450{
451 stop_glerror();
452
453 if (NULL == image)
439 { 454 {
440 border_scale = llmin(border_scale, (F32)width / ((F32)border_width * 2.f)); 455 llwarns << "image == NULL; aborting function" << llendl;
456 return;
441 } 457 }
442 458
443 // scale screen size of borders down 459 // scale screen size of borders down
444 S32 scaled_border_width = llfloor(border_scale * (F32)border_width); 460 LLRectf clipped_scale_rect = uv_rect;
445 S32 scaled_border_height = llfloor(border_scale * (F32)border_height); 461 clipped_scale_rect.intersectWith(scale_rect);
462
463 LLRect draw_rect(0, height, width, 0);
464 LLRect draw_scale_rect(llround((F32)image->getWidth() * scale_rect.mLeft),
465 llround((F32)image->getHeight() * scale_rect.mTop),
466 llround((F32)image->getWidth() * scale_rect.mRight),
467 llround((F32)image->getHeight() * scale_rect.mBottom));
468 // scale fixed region of image up with drawn region
469 draw_scale_rect.mRight += width - image->getWidth();
470 draw_scale_rect.mTop += height - image->getHeight();
471
472 S32 border_shrink_width = llmax(0, draw_scale_rect.mLeft - draw_scale_rect.mRight);
473 S32 border_shrink_height = llmax(0, draw_scale_rect.mBottom - draw_scale_rect.mTop);
474
475 F32 shrink_width_ratio = scale_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image->getWidth() * (1.f - scale_rect.getWidth()));
476 F32 shrink_height_ratio = scale_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image->getHeight() * (1.f - scale_rect.getHeight()));
477
478 F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
479 draw_scale_rect.mLeft = llround((F32)draw_scale_rect.mLeft * shrink_scale);
480 draw_scale_rect.mTop = llround(lerp((F32)height, (F32)draw_scale_rect.mTop, shrink_scale));
481 draw_scale_rect.mRight = llround(lerp((F32)width, (F32)draw_scale_rect.mRight, shrink_scale));
482 draw_scale_rect.mBottom = llround((F32)draw_scale_rect.mBottom * shrink_scale);
446 483
447 LLGLSUIDefault gls_ui; 484 LLGLSUIDefault gls_ui;
448 485
@@ -470,127 +507,124 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
470 507
471 glColor4fv(color.mV); 508 glColor4fv(color.mV);
472 509
473 F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
474 F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
475
476 glBegin(GL_QUADS); 510 glBegin(GL_QUADS);
477 { 511 {
478 // draw bottom left 512 // draw bottom left
479 glTexCoord2f(0.f, 0.f); 513 glTexCoord2d(uv_rect.mLeft, uv_rect.mBottom);
480 glVertex2i(0, 0); 514 glVertex2i(0, 0);
481 515
482 glTexCoord2f(border_width_fraction, 0.f); 516 glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mBottom);
483 glVertex2i(scaled_border_width, 0); 517 glVertex2i(draw_scale_rect.mLeft, 0);
484 518
485 glTexCoord2f(border_width_fraction, border_height_fraction); 519 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
486 glVertex2i(scaled_border_width, scaled_border_height); 520 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
487 521
488 glTexCoord2f(0.f, border_height_fraction); 522 glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mBottom);
489 glVertex2i(0, scaled_border_height); 523 glVertex2i(0, draw_scale_rect.mBottom);
490 524
491 // draw bottom middle 525 // draw bottom middle
492 glTexCoord2f(border_width_fraction, 0.f); 526 glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mBottom);
493 glVertex2i(scaled_border_width, 0); 527 glVertex2i(draw_scale_rect.mLeft, 0);
494 528
495 glTexCoord2f(1.f - border_width_fraction, 0.f); 529 glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mBottom);
496 glVertex2i(width - scaled_border_width, 0); 530 glVertex2i(draw_scale_rect.mRight, 0);
497 531
498 glTexCoord2f(1.f - border_width_fraction, border_height_fraction); 532 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
499 glVertex2i(width - scaled_border_width, scaled_border_height); 533 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
500 534
501 glTexCoord2f(border_width_fraction, border_height_fraction); 535 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
502 glVertex2i(scaled_border_width, scaled_border_height); 536 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
503 537
504 // draw bottom right 538 // draw bottom right
505 glTexCoord2f(1.f - border_width_fraction, 0.f); 539 glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mBottom);
506 glVertex2i(width - scaled_border_width, 0); 540 glVertex2i(draw_scale_rect.mRight, 0);
507 541
508 glTexCoord2f(1.f, 0.f); 542 glTexCoord2d(uv_rect.mRight, uv_rect.mBottom);
509 glVertex2i(width, 0); 543 glVertex2i(width, 0);
510 544
511 glTexCoord2f(1.f, border_height_fraction); 545 glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mBottom);
512 glVertex2i(width, scaled_border_height); 546 glVertex2i(width, draw_scale_rect.mBottom);
513 547
514 glTexCoord2f(1.f - border_width_fraction, border_height_fraction); 548 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
515 glVertex2i(width - scaled_border_width, scaled_border_height); 549 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
516 550
517 // draw left 551 // draw left
518 glTexCoord2f(0.f, border_height_fraction); 552 glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mBottom);
519 glVertex2i(0, scaled_border_height); 553 glVertex2i(0, draw_scale_rect.mBottom);
520 554
521 glTexCoord2f(border_width_fraction, border_height_fraction); 555 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
522 glVertex2i(scaled_border_width, scaled_border_height); 556 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
523 557
524 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction); 558 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
525 glVertex2i(scaled_border_width, height - scaled_border_height); 559 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
526 560
527 glTexCoord2f(0.f, 1.f - border_height_fraction); 561 glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mTop);
528 glVertex2i(0, height - scaled_border_height); 562 glVertex2i(0, draw_scale_rect.mTop);
529 563
530 // draw middle 564 // draw middle
531 glTexCoord2f(border_width_fraction, border_height_fraction); 565 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mBottom);
532 glVertex2i(scaled_border_width, scaled_border_height); 566 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
533 567
534 glTexCoord2f(1.f - border_width_fraction, border_height_fraction); 568 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
535 glVertex2i(width - scaled_border_width, scaled_border_height); 569 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
536 570
537 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction); 571 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
538 glVertex2i(width - scaled_border_width, height - scaled_border_height); 572 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
539 573
540 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction); 574 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
541 glVertex2i(scaled_border_width, height - scaled_border_height); 575 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
542 576
543 // draw right 577 // draw right
544 glTexCoord2f(1.f - border_width_fraction, border_height_fraction); 578 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mBottom);
545 glVertex2i(width - scaled_border_width, scaled_border_height); 579 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
546 580
547 glTexCoord2f(1.f, border_height_fraction); 581 glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mBottom);
548 glVertex2i(width, scaled_border_height); 582 glVertex2i(width, draw_scale_rect.mBottom);
549 583
550 glTexCoord2f(1.f, 1.f - border_height_fraction); 584 glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mTop);
551 glVertex2i(width, height - scaled_border_height); 585 glVertex2i(width, draw_scale_rect.mTop);
552 586
553 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction); 587 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
554 glVertex2i(width - scaled_border_width, height - scaled_border_height); 588 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
555 589
556 // draw top left 590 // draw top left
557 glTexCoord2f(0.f, 1.f - border_height_fraction); 591 glTexCoord2d(uv_rect.mLeft, clipped_scale_rect.mTop);
558 glVertex2i(0, height - scaled_border_height); 592 glVertex2i(0, draw_scale_rect.mTop);
559 593
560 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction); 594 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
561 glVertex2i(scaled_border_width, height - scaled_border_height); 595 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
562 596
563 glTexCoord2f(border_width_fraction, 1.f); 597 glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mTop);
564 glVertex2i(scaled_border_width, height); 598 glVertex2i(draw_scale_rect.mLeft, height);
565 599
566 glTexCoord2f(0.f, 1.f); 600 glTexCoord2d(uv_rect.mLeft, uv_rect.mTop);
567 glVertex2i(0, height); 601 glVertex2i(0, height);
568 602
569 // draw top middle 603 // draw top middle
570 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction); 604 glTexCoord2f(clipped_scale_rect.mLeft, clipped_scale_rect.mTop);
571 glVertex2i(scaled_border_width, height - scaled_border_height); 605 glVertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
572 606
573 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction); 607 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
574 glVertex2i(width - scaled_border_width, height - scaled_border_height); 608 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
575 609
576 glTexCoord2f(1.f - border_width_fraction, 1.f); 610 glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mTop);
577 glVertex2i(width - scaled_border_width, height); 611 glVertex2i(draw_scale_rect.mRight, height);
578 612
579 glTexCoord2f(border_width_fraction, 1.f); 613 glTexCoord2f(clipped_scale_rect.mLeft, uv_rect.mTop);
580 glVertex2i(scaled_border_width, height); 614 glVertex2i(draw_scale_rect.mLeft, height);
581 615
582 // draw top right 616 // draw top right
583 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction); 617 glTexCoord2d(clipped_scale_rect.mRight, clipped_scale_rect.mTop);
584 glVertex2i(width - scaled_border_width, height - scaled_border_height); 618 glVertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
585 619
586 glTexCoord2f(1.f, 1.f - border_height_fraction); 620 glTexCoord2d(uv_rect.mRight, clipped_scale_rect.mTop);
587 glVertex2i(width, height - scaled_border_height); 621 glVertex2i(width, draw_scale_rect.mTop);
588 622
589 glTexCoord2f(1.f, 1.f); 623 glTexCoord2d(uv_rect.mRight, uv_rect.mTop);
590 glVertex2i(width, height); 624 glVertex2i(width, height);
591 625
592 glTexCoord2f(1.f - border_width_fraction, 1.f); 626 glTexCoord2d(clipped_scale_rect.mRight, uv_rect.mTop);
593 glVertex2i(width - scaled_border_width, height); 627 glVertex2i(draw_scale_rect.mRight, height);
594 } 628 }
595 glEnd(); 629 glEnd();
596 } 630 }
@@ -602,12 +636,12 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
602 } 636 }
603} 637}
604 638
605void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color) 639void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
606{ 640{
607 gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color ); 641 gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
608} 642}
609 643
610void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color) 644void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
611{ 645{
612 if (NULL == image) 646 if (NULL == image)
613 { 647 {
@@ -635,16 +669,16 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
635 669
636 glBegin(GL_QUADS); 670 glBegin(GL_QUADS);
637 { 671 {
638 glTexCoord2f(1.f, 1.f); 672 glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
639 glVertex2i(width, height ); 673 glVertex2i(width, height );
640 674
641 glTexCoord2f(0.f, 1.f); 675 glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
642 glVertex2i(0, height ); 676 glVertex2i(0, height );
643 677
644 glTexCoord2f(0.f, 0.f); 678 glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
645 glVertex2i(0, 0); 679 glVertex2i(0, 0);
646 680
647 glTexCoord2f(1.f, 0.f); 681 glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
648 glVertex2i(width, 0); 682 glVertex2i(width, 0);
649 } 683 }
650 glEnd(); 684 glEnd();
@@ -653,7 +687,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
653} 687}
654 688
655 689
656void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color) 690void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
657{ 691{
658 if (NULL == image) 692 if (NULL == image)
659 { 693 {
@@ -673,16 +707,16 @@ void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageG
673 707
674 glBegin(GL_QUADS); 708 glBegin(GL_QUADS);
675 { 709 {
676 glTexCoord2f(1.f, 0.f); 710 glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
677 glVertex2i(width, height ); 711 glVertex2i(width, height );
678 712
679 glTexCoord2f(0.f, 0.f); 713 glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
680 glVertex2i(0, height ); 714 glVertex2i(0, height );
681 715
682 glTexCoord2f(0.f, 1.f); 716 glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
683 glVertex2i(0, 0); 717 glVertex2i(0, 0);
684 718
685 glTexCoord2f(1.f, 1.f); 719 glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
686 glVertex2i(width, 0); 720 glVertex2i(width, 0);
687 } 721 }
688 glEnd(); 722 glEnd();
@@ -1584,40 +1618,6 @@ void LLUI::loadIdentity()
1584 LLFontGL::sCurOrigin.mZ = 0; 1618 LLFontGL::sCurOrigin.mZ = 0;
1585} 1619}
1586 1620
1587//static
1588void LLUI::setScissorRegionScreen(const LLRect& rect)
1589{
1590 stop_glerror();
1591 S32 x,y,w,h;
1592 x = llround(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
1593 y = llround(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
1594 w = llround(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX]);
1595 h = llround(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY]);
1596 glScissor( x,y,w,h );
1597 stop_glerror();
1598}
1599
1600//static
1601void LLUI::setScissorRegionLocal(const LLRect& rect)
1602{
1603 stop_glerror();
1604 S32 screen_left = LLFontGL::sCurOrigin.mX + rect.mLeft;
1605 S32 screen_bottom = LLFontGL::sCurOrigin.mY + rect.mBottom;
1606
1607 S32 x,y,w,h;
1608
1609 x = llround((F32)screen_left * LLUI::sGLScaleFactor.mV[VX]);
1610 y = llround((F32)screen_bottom * LLUI::sGLScaleFactor.mV[VY]);
1611 w = llround((F32)rect.getWidth() * LLUI::sGLScaleFactor.mV[VX]);
1612 h = llround((F32)rect.getHeight() * LLUI::sGLScaleFactor.mV[VY]);
1613
1614 w = llmax(0,w);
1615 h = llmax(0,h);
1616
1617 glScissor(x,y,w,h);
1618 stop_glerror();
1619}
1620
1621//static 1621//static
1622void LLUI::setScaleFactor(const LLVector2 &scale_factor) 1622void LLUI::setScaleFactor(const LLVector2 &scale_factor)
1623{ 1623{
@@ -1696,6 +1696,34 @@ LLVector2 LLUI::getWindowSize()
1696} 1696}
1697 1697
1698//static 1698//static
1699void LLUI::screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y)
1700{
1701 *gl_x = llround((F32)screen_x * sGLScaleFactor.mV[VX]);
1702 *gl_y = llround((F32)screen_y * sGLScaleFactor.mV[VY]);
1703}
1704
1705//static
1706void LLUI::glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y)
1707{
1708 *screen_x = llround((F32)gl_x / sGLScaleFactor.mV[VX]);
1709 *screen_y = llround((F32)gl_y / sGLScaleFactor.mV[VY]);
1710}
1711
1712//static
1713void LLUI::screenRectToGL(const LLRect& screen, LLRect *gl)
1714{
1715 screenPointToGL(screen.mLeft, screen.mTop, &gl->mLeft, &gl->mTop);
1716 screenPointToGL(screen.mRight, screen.mBottom, &gl->mRight, &gl->mBottom);
1717}
1718
1719//static
1720void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen)
1721{
1722 glPointToScreen(gl.mLeft, gl.mTop, &screen->mLeft, &screen->mTop);
1723 glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom);
1724}
1725
1726//static
1699LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name) 1727LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name)
1700{ 1728{
1701 if(asset_name == LLString::null) return LLUUID::null; 1729 if(asset_name == LLString::null) return LLUUID::null;
@@ -1710,64 +1738,169 @@ LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name)
1710 return LLUUID( foundValue ); 1738 return LLUUID( foundValue );
1711} 1739}
1712 1740
1741//static
1742LLUIImage* LLUI::getUIImageByName(const LLString& name)
1743{
1744 return sImageProvider->getUIImageByID(findAssetUUIDByName(name));
1745}
1746
1747
1713// static 1748// static
1714void LLUI::setHtmlHelp(LLHtmlHelp* html_help) 1749void LLUI::setHtmlHelp(LLHtmlHelp* html_help)
1715{ 1750{
1716 LLUI::sHtmlHelp = html_help; 1751 LLUI::sHtmlHelp = html_help;
1717} 1752}
1718 1753
1754LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled)
1755{
1756 if (mEnabled)
1757 {
1758 pushClipRect(rect);
1759 }
1760 mScissorState.setEnabled(!sClipRectStack.empty());
1761 updateScissorRegion();
1762}
1763
1764LLScreenClipRect::~LLScreenClipRect()
1765{
1766 if (mEnabled)
1767 {
1768 popClipRect();
1769 }
1770 updateScissorRegion();
1771}
1772
1719//static 1773//static
1720void LLUI::pushClipRect(const LLRect& rect) 1774void LLScreenClipRect::pushClipRect(const LLRect& rect)
1721{ 1775{
1722 LLRect combined_clip_rect = rect; 1776 LLRect combined_clip_rect = rect;
1723 if (!sClipRectStack.empty()) 1777 if (!sClipRectStack.empty())
1724 { 1778 {
1725 combined_clip_rect.intersectWith(sClipRectStack.top()); 1779 LLRect top = sClipRectStack.top();
1780 combined_clip_rect.intersectWith(top);
1726 } 1781 }
1727 sClipRectStack.push(combined_clip_rect); 1782 sClipRectStack.push(combined_clip_rect);
1728 setScissorRegionScreen(combined_clip_rect);
1729} 1783}
1730 1784
1731//static 1785//static
1732void LLUI::popClipRect() 1786void LLScreenClipRect::popClipRect()
1733{ 1787{
1734 sClipRectStack.pop(); 1788 sClipRectStack.pop();
1735 if (!sClipRectStack.empty())
1736 {
1737 setScissorRegionScreen(sClipRectStack.top());
1738 }
1739} 1789}
1740 1790
1741LLClipRect::LLClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled) 1791//static
1792void LLScreenClipRect::updateScissorRegion()
1742{ 1793{
1743 if (mEnabled) 1794 if (sClipRectStack.empty()) return;
1744 { 1795
1745 LLUI::pushClipRect(rect); 1796 LLRect rect = sClipRectStack.top();
1746 } 1797 stop_glerror();
1798 S32 x,y,w,h;
1799 x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
1800 y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
1801 w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
1802 h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
1803 glScissor( x,y,w,h );
1804 stop_glerror();
1747} 1805}
1748 1806
1749LLClipRect::~LLClipRect() 1807
1808LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled)
1809: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
1810 rect.mTop + LLFontGL::sCurOrigin.mY,
1811 rect.mRight + LLFontGL::sCurOrigin.mX,
1812 rect.mBottom + LLFontGL::sCurOrigin.mY),
1813 enabled)
1750{ 1814{
1751 if (mEnabled)
1752 {
1753 LLUI::popClipRect();
1754 }
1755} 1815}
1756 1816
1757LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled) 1817
1818//
1819// LLUIImage
1820//
1821
1822LLUIImage::LLUIImage(LLPointer<LLImageGL> image) :
1823 mImage(image),
1824 mScaleRegion(0.f, 1.f, 1.f, 0.f),
1825 mClipRegion(0.f, 1.f, 1.f, 0.f),
1826 mUniformScaling(TRUE),
1827 mNoClip(TRUE)
1758{ 1828{
1759 if (mEnabled)
1760 {
1761 LLRect scissor_rect = rect;
1762 scissor_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY);
1763 LLUI::pushClipRect(scissor_rect);
1764 }
1765} 1829}
1766 1830
1767LLLocalClipRect::~LLLocalClipRect() 1831void LLUIImage::setClipRegion(const LLRectf& region)
1832{
1833 mClipRegion = region;
1834 mNoClip = mClipRegion.mLeft == 0.f
1835 && mClipRegion.mRight == 1.f
1836 && mClipRegion.mBottom == 0.f
1837 && mClipRegion.mTop == 1.f;
1838}
1839
1840void LLUIImage::setScaleRegion(const LLRectf& region)
1841{
1842 mScaleRegion = region;
1843 mUniformScaling = mScaleRegion.mLeft == 0.f
1844 && mScaleRegion.mRight == 1.f
1845 && mScaleRegion.mBottom == 0.f
1846 && mScaleRegion.mTop == 1.f;
1847}
1848
1849//TODO: move drawing implementation inside class
1850void LLUIImage::draw(S32 x, S32 y, const LLColor4& color)
1768{ 1851{
1769 if (mEnabled) 1852 gl_draw_image(x, y, mImage, color, mClipRegion);
1853}
1854
1855void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color)
1856{
1857 if (mUniformScaling)
1858 {
1859 gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion);
1860 }
1861 else
1770 { 1862 {
1771 LLUI::popClipRect(); 1863 gl_draw_scaled_image_with_border(
1864 x, y,
1865 width, height,
1866 mImage,
1867 color,
1868 FALSE,
1869 mClipRegion,
1870 mScaleRegion);
1772 } 1871 }
1773} 1872}
1873
1874void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color)
1875{
1876 gl_draw_scaled_image_with_border(
1877 x, y,
1878 width, height,
1879 mImage,
1880 color,
1881 TRUE,
1882 mClipRegion,
1883 mScaleRegion);
1884}
1885
1886void LLUIImage::drawSolid(S32 x, S32 y, const LLColor4& color)
1887{
1888 gl_draw_scaled_image_with_border(
1889 x, y,
1890 getWidth(), getHeight(),
1891 mImage,
1892 color,
1893 TRUE,
1894 mClipRegion,
1895 mScaleRegion);
1896}
1897
1898S32 LLUIImage::getWidth()
1899{
1900 return mImage->getWidth(0);
1901}
1902
1903S32 LLUIImage::getHeight()
1904{
1905 return mImage->getHeight(0);
1906}
diff --git a/linden/indra/llui/llui.h b/linden/indra/llui/llui.h
index 2832b39..9d98620 100644
--- a/linden/indra/llui/llui.h
+++ b/linden/indra/llui/llui.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -41,14 +41,15 @@
41#include "llhtmlhelp.h" 41#include "llhtmlhelp.h"
42#include "llgl.h" 42#include "llgl.h"
43#include <stack> 43#include <stack>
44#include "llimagegl.h"
44 45
45class LLColor4; 46class LLColor4;
46class LLVector3; 47class LLVector3;
47class LLVector2; 48class LLVector2;
48class LLImageGL;
49class LLUUID; 49class LLUUID;
50class LLWindow; 50class LLWindow;
51class LLView; 51class LLView;
52class LLUIImage;
52 53
53// UI colors 54// UI colors
54extern const LLColor4 UI_VERTEX_COLOR; 55extern const LLColor4 UI_VERTEX_COLOR;
@@ -83,13 +84,14 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4&
83void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); 84void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
84void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color); 85void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color);
85 86
86void gl_draw_image(S32 x, S32 y, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR); 87void gl_draw_image(S32 x, S32 y, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
87void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR); 88void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
88void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR); 89void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
89void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR); 90void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
90void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4 &color, BOOL solid_color = FALSE); 91void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
92void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
91// Flip vertical, used for LLFloaterHTML 93// Flip vertical, used for LLFloaterHTML
92void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR); 94void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
93 95
94void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom); 96void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom);
95void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); 97void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
@@ -166,20 +168,19 @@ public:
166 168
167 //helper functions (should probably move free standing rendering helper functions here) 169 //helper functions (should probably move free standing rendering helper functions here)
168 static LLString locateSkin(const LLString& filename); 170 static LLString locateSkin(const LLString& filename);
169 static void pushClipRect(const LLRect& rect);
170 static void popClipRect();
171 static void setCursorPositionScreen(S32 x, S32 y); 171 static void setCursorPositionScreen(S32 x, S32 y);
172 static void setCursorPositionLocal(LLView* viewp, S32 x, S32 y); 172 static void setCursorPositionLocal(LLView* viewp, S32 x, S32 y);
173 static void setScaleFactor(const LLVector2& scale_factor); 173 static void setScaleFactor(const LLVector2& scale_factor);
174 static void setLineWidth(F32 width); 174 static void setLineWidth(F32 width);
175 static LLUUID findAssetUUIDByName(const LLString& name); 175 static LLUUID findAssetUUIDByName(const LLString& name);
176 static LLUIImage* getUIImageByName(const LLString& name);
176 static LLVector2 getWindowSize(); 177 static LLVector2 getWindowSize();
178 static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y);
179 static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y);
180 static void screenRectToGL(const LLRect& screen, LLRect *gl);
181 static void glRectToScreen(const LLRect& gl, LLRect *screen);
177 static void setHtmlHelp(LLHtmlHelp* html_help); 182 static void setHtmlHelp(LLHtmlHelp* html_help);
178 183
179private:
180 static void setScissorRegionScreen(const LLRect& rect);
181 static void setScissorRegionLocal(const LLRect& rect); // works assuming LLUI::translate has been called
182
183public: 184public:
184 static LLControlGroup* sConfigGroup; 185 static LLControlGroup* sConfigGroup;
185 static LLControlGroup* sColorsGroup; 186 static LLControlGroup* sColorsGroup;
@@ -190,7 +191,6 @@ public:
190 static LLWindow* sWindow; 191 static LLWindow* sWindow;
191 static BOOL sShowXUINames; 192 static BOOL sShowXUINames;
192 static LLHtmlHelp* sHtmlHelp; 193 static LLHtmlHelp* sHtmlHelp;
193 static std::stack<LLRect> sClipRectStack;
194 194
195}; 195};
196 196
@@ -282,6 +282,7 @@ typedef enum e_widget_type
282 WIDGET_TYPE_MEMORY_VIEW, 282 WIDGET_TYPE_MEMORY_VIEW,
283 WIDGET_TYPE_FRAME_STAT_VIEW, 283 WIDGET_TYPE_FRAME_STAT_VIEW,
284 WIDGET_TYPE_LAYOUT_STACK, 284 WIDGET_TYPE_LAYOUT_STACK,
285 WIDGET_TYPE_FLYOUT_BUTTON,
285 WIDGET_TYPE_DONTCARE, 286 WIDGET_TYPE_DONTCARE,
286 WIDGET_TYPE_COUNT 287 WIDGET_TYPE_COUNT
287} EWidgetType; 288} EWidgetType;
@@ -378,24 +379,65 @@ protected:
378 379
379template <class T, class U> T* LLUISingleton<T,U>::sInstance = NULL; 380template <class T, class U> T* LLUISingleton<T,U>::sInstance = NULL;
380 381
381class LLClipRect 382class LLScreenClipRect
382{ 383{
383public: 384public:
384 LLClipRect(const LLRect& rect, BOOL enabled = TRUE); 385 LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
385 virtual ~LLClipRect(); 386 virtual ~LLScreenClipRect();
386protected: 387
388private:
389 static void pushClipRect(const LLRect& rect);
390 static void popClipRect();
391 static void updateScissorRegion();
392
393private:
387 LLGLState mScissorState; 394 LLGLState mScissorState;
388 BOOL mEnabled; 395 BOOL mEnabled;
396
397 static std::stack<LLRect> sClipRectStack;
389}; 398};
390 399
391class LLLocalClipRect 400class LLLocalClipRect : public LLScreenClipRect
392{ 401{
393public: 402public:
394 LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); 403 LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
395 virtual ~LLLocalClipRect(); 404};
405
406class LLUIImage : public LLRefCount
407{
408public:
409 LLUIImage(LLPointer<LLImageGL> image);
410
411 void setClipRegion(const LLRectf& region);
412 void setScaleRegion(const LLRectf& region);
413
414 LLPointer<LLImageGL> getImage() { return mImage; }
415
416 void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR);
417 void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR);
418 void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color);
419 void drawSolid(S32 x, S32 y, const LLColor4& color);
420
421 S32 getWidth();
422 S32 getHeight();
423
396protected: 424protected:
397 LLGLState mScissorState; 425 LLRectf mScaleRegion;
398 BOOL mEnabled; 426 LLRectf mClipRegion;
427 LLPointer<LLImageGL> mImage;
428 BOOL mUniformScaling;
429 BOOL mNoClip;
430};
431
432//RN: maybe this needs to moved elsewhere?
433class LLImageProviderInterface
434{
435public:
436 LLImageProviderInterface() {};
437 virtual ~LLImageProviderInterface() {};
438
439 virtual LLUIImage* getUIImageByID(const LLUUID& id, BOOL clamped = TRUE) = 0;
440 virtual LLImageGL* getImageByID(const LLUUID& id, BOOL clamped = TRUE) = 0;
399}; 441};
400 442
401#endif 443#endif
diff --git a/linden/indra/llui/llui_vc9.vcproj b/linden/indra/llui/llui_vc9.vcproj
new file mode 100644
index 0000000..cfaaf66
--- /dev/null
+++ b/linden/indra/llui/llui_vc9.vcproj
@@ -0,0 +1,596 @@
1<?xml version="1.0" encoding="Windows-1252"?>
2<VisualStudioProject
3 ProjectType="Visual C++"
4 Version="9.00"
5 Name="llui"
6 ProjectGUID="{DE55D666-6A3D-476C-937F-109269B83681}"
7 RootNamespace="llui"
8 Keyword="Win32Proj"
9 TargetFrameworkVersion="131072"
10 >
11 <Platforms>
12 <Platform
13 Name="Win32"
14 />
15 </Platforms>
16 <ToolFiles>
17 </ToolFiles>
18 <Configurations>
19 <Configuration
20 Name="Debug|Win32"
21 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
22 IntermediateDirectory="Debug"
23 ConfigurationType="4"
24 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
25 CharacterSet="1"
26 >
27 <Tool
28 Name="VCPreBuildEventTool"
29 />
30 <Tool
31 Name="VCCustomBuildTool"
32 />
33 <Tool
34 Name="VCXMLDataGeneratorTool"
35 />
36 <Tool
37 Name="VCWebServiceProxyGeneratorTool"
38 />
39 <Tool
40 Name="VCMIDLTool"
41 />
42 <Tool
43 Name="VCCLCompilerTool"
44 Optimization="0"
45 AdditionalIncludeDirectories="..\llmath;..\llvfs;..\llcommon;..\llprimitive;..\llwindow;..\llrender;..\llimage;..\llaudio;..\llxml;..\llmessage;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include\"
46 PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_DEBUG"
47 MinimalRebuild="true"
48 BasicRuntimeChecks="3"
49 RuntimeLibrary="1"
50 StructMemberAlignment="4"
51 TreatWChar_tAsBuiltInType="false"
52 ForceConformanceInForLoopScope="true"
53 UsePrecompiledHeader="0"
54 WarningLevel="3"
55 WarnAsError="true"
56 Detect64BitPortabilityProblems="false"
57 DebugInformationFormat="4"
58 />
59 <Tool
60 Name="VCManagedResourceCompilerTool"
61 />
62 <Tool
63 Name="VCResourceCompilerTool"
64 />
65 <Tool
66 Name="VCPreLinkEventTool"
67 />
68 <Tool
69 Name="VCLibrarianTool"
70 OutputFile="$(OutDir)/llui.lib"
71 />
72 <Tool
73 Name="VCALinkTool"
74 />
75 <Tool
76 Name="VCXDCMakeTool"
77 />
78 <Tool
79 Name="VCBscMakeTool"
80 />
81 <Tool
82 Name="VCFxCopTool"
83 />
84 <Tool
85 Name="VCPostBuildEventTool"
86 />
87 </Configuration>
88 <Configuration
89 Name="Release|Win32"
90 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
91 IntermediateDirectory="Release"
92 ConfigurationType="4"
93 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
94 CharacterSet="1"
95 >
96 <Tool
97 Name="VCPreBuildEventTool"
98 />
99 <Tool
100 Name="VCCustomBuildTool"
101 />
102 <Tool
103 Name="VCXMLDataGeneratorTool"
104 />
105 <Tool
106 Name="VCWebServiceProxyGeneratorTool"
107 />
108 <Tool
109 Name="VCMIDLTool"
110 />
111 <Tool
112 Name="VCCLCompilerTool"
113 AdditionalOptions="/Oy-"
114 AdditionalIncludeDirectories="..\llmath;..\llvfs;..\llcommon;..\llprimitive;..\llwindow;..\llrender;..\llimage;..\llaudio;..\llxml;..\llmessage;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include\"
115 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE"
116 RuntimeLibrary="0"
117 StructMemberAlignment="0"
118 TreatWChar_tAsBuiltInType="false"
119 ForceConformanceInForLoopScope="true"
120 UsePrecompiledHeader="0"
121 WarningLevel="3"
122 WarnAsError="true"
123 Detect64BitPortabilityProblems="false"
124 DebugInformationFormat="3"
125 />
126 <Tool
127 Name="VCManagedResourceCompilerTool"
128 />
129 <Tool
130 Name="VCResourceCompilerTool"
131 />
132 <Tool
133 Name="VCPreLinkEventTool"
134 />
135 <Tool
136 Name="VCLibrarianTool"
137 OutputFile="$(OutDir)/llui.lib"
138 />
139 <Tool
140 Name="VCALinkTool"
141 />
142 <Tool
143 Name="VCXDCMakeTool"
144 />
145 <Tool
146 Name="VCBscMakeTool"
147 />
148 <Tool
149 Name="VCFxCopTool"
150 />
151 <Tool
152 Name="VCPostBuildEventTool"
153 />
154 </Configuration>
155 <Configuration
156 Name="ReleaseNoOpt|Win32"
157 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
158 IntermediateDirectory="$(ConfigurationName)"
159 ConfigurationType="4"
160 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
161 CharacterSet="1"
162 >
163 <Tool
164 Name="VCPreBuildEventTool"
165 />
166 <Tool
167 Name="VCCustomBuildTool"
168 />
169 <Tool
170 Name="VCXMLDataGeneratorTool"
171 />
172 <Tool
173 Name="VCWebServiceProxyGeneratorTool"
174 />
175 <Tool
176 Name="VCMIDLTool"
177 />
178 <Tool
179 Name="VCCLCompilerTool"
180 AdditionalOptions="/Oy-"
181 Optimization="0"
182 AdditionalIncludeDirectories="..\llmath;..\llvfs;..\llcommon;..\llprimitive;..\llwindow;..\llrender;..\llimage;..\llaudio;..\llxml;..\llmessage;&quot;..\..\libraries\i686-win32\include&quot;;..\..\libraries\include\"
183 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE"
184 RuntimeLibrary="0"
185 StructMemberAlignment="0"
186 TreatWChar_tAsBuiltInType="false"
187 ForceConformanceInForLoopScope="true"
188 UsePrecompiledHeader="0"
189 WarningLevel="3"
190 WarnAsError="true"
191 Detect64BitPortabilityProblems="false"
192 DebugInformationFormat="3"
193 />
194 <Tool
195 Name="VCManagedResourceCompilerTool"
196 />
197 <Tool
198 Name="VCResourceCompilerTool"
199 />
200 <Tool
201 Name="VCPreLinkEventTool"
202 />
203 <Tool
204 Name="VCLibrarianTool"
205 OutputFile="$(OutDir)/llui.lib"
206 />
207 <Tool
208 Name="VCALinkTool"
209 />
210 <Tool
211 Name="VCXDCMakeTool"
212 />
213 <Tool
214 Name="VCBscMakeTool"
215 />
216 <Tool
217 Name="VCFxCopTool"
218 />
219 <Tool
220 Name="VCPostBuildEventTool"
221 />
222 </Configuration>
223 </Configurations>
224 <References>
225 </References>
226 <Files>
227 <Filter
228 Name="Source Files"
229 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
230 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
231 >
232 <File
233 RelativePath=".\llalertdialog.cpp"
234 >
235 </File>
236 <File
237 RelativePath=".\llbutton.cpp"
238 >
239 </File>
240 <File
241 RelativePath=".\llcheckboxctrl.cpp"
242 >
243 </File>
244 <File
245 RelativePath=".\llclipboard.cpp"
246 >
247 </File>
248 <File
249 RelativePath=".\llcombobox.cpp"
250 >
251 </File>
252 <File
253 RelativePath=".\llctrlselectioninterface.cpp"
254 >
255 </File>
256 <File
257 RelativePath=".\lldraghandle.cpp"
258 >
259 </File>
260 <File
261 RelativePath=".\lleditmenuhandler.cpp"
262 >
263 </File>
264 <File
265 RelativePath=".\llfloater.cpp"
266 >
267 </File>
268 <File
269 RelativePath=".\llfocusmgr.cpp"
270 >
271 </File>
272 <File
273 RelativePath=".\lliconctrl.cpp"
274 >
275 </File>
276 <File
277 RelativePath=".\llkeywords.cpp"
278 >
279 </File>
280 <File
281 RelativePath=".\lllineeditor.cpp"
282 >
283 </File>
284 <File
285 RelativePath=".\llmenugl.cpp"
286 >
287 </File>
288 <File
289 RelativePath=".\llmodaldialog.cpp"
290 >
291 </File>
292 <File
293 RelativePath=".\llpanel.cpp"
294 >
295 </File>
296 <File
297 RelativePath=".\llradiogroup.cpp"
298 >
299 </File>
300 <File
301 RelativePath=".\llresizebar.cpp"
302 >
303 </File>
304 <File
305 RelativePath=".\llresizehandle.cpp"
306 >
307 </File>
308 <File
309 RelativePath=".\llresmgr.cpp"
310 >
311 </File>
312 <File
313 RelativePath=".\llrootview.cpp"
314 >
315 </File>
316 <File
317 RelativePath=".\llscrollbar.cpp"
318 >
319 </File>
320 <File
321 RelativePath=".\llscrollcontainer.cpp"
322 >
323 </File>
324 <File
325 RelativePath=".\llscrollingpanellist.cpp"
326 >
327 </File>
328 <File
329 RelativePath=".\llscrolllistctrl.cpp"
330 >
331 </File>
332 <File
333 RelativePath=".\llslider.cpp"
334 >
335 </File>
336 <File
337 RelativePath=".\llsliderctrl.cpp"
338 >
339 </File>
340 <File
341 RelativePath=".\llspinctrl.cpp"
342 >
343 </File>
344 <File
345 RelativePath=".\llstyle.cpp"
346 >
347 </File>
348 <File
349 RelativePath=".\lltabcontainer.cpp"
350 >
351 </File>
352 <File
353 RelativePath=".\lltabcontainervertical.cpp"
354 >
355 </File>
356 <File
357 RelativePath=".\lltextbox.cpp"
358 >
359 </File>
360 <File
361 RelativePath=".\lltexteditor.cpp"
362 >
363 </File>
364 <File
365 RelativePath=".\llui.cpp"
366 >
367 </File>
368 <File
369 RelativePath=".\lluictrl.cpp"
370 >
371 </File>
372 <File
373 RelativePath=".\lluictrlfactory.cpp"
374 >
375 </File>
376 <File
377 RelativePath=".\lluistring.cpp"
378 >
379 </File>
380 <File
381 RelativePath=".\llundo.cpp"
382 >
383 </File>
384 <File
385 RelativePath=".\llview.cpp"
386 >
387 </File>
388 <File
389 RelativePath=".\llviewborder.cpp"
390 >
391 </File>
392 <File
393 RelativePath=".\llviewquery.cpp"
394 >
395 </File>
396 </Filter>
397 <Filter
398 Name="Header Files"
399 Filter="h;hpp;hxx;hm;inl;inc;xsd"
400 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
401 >
402 <File
403 RelativePath=".\llalertdialog.h"
404 >
405 </File>
406 <File
407 RelativePath=".\llbutton.h"
408 >
409 </File>
410 <File
411 RelativePath=".\llcallbackmap.h"
412 >
413 </File>
414 <File
415 RelativePath=".\llcheckboxctrl.h"
416 >
417 </File>
418 <File
419 RelativePath=".\llclipboard.h"
420 >
421 </File>
422 <File
423 RelativePath=".\llcombobox.h"
424 >
425 </File>
426 <File
427 RelativePath=".\llctrlselectioninterface.h"
428 >
429 </File>
430 <File
431 RelativePath=".\lldraghandle.h"
432 >
433 </File>
434 <File
435 RelativePath=".\lleditmenuhandler.h"
436 >
437 </File>
438 <File
439 RelativePath=".\llfloater.h"
440 >
441 </File>
442 <File
443 RelativePath=".\llfocusmgr.h"
444 >
445 </File>
446 <File
447 RelativePath=".\llhtmlhelp.h"
448 >
449 </File>
450 <File
451 RelativePath=".\lliconctrl.h"
452 >
453 </File>
454 <File
455 RelativePath=".\llkeywords.h"
456 >
457 </File>
458 <File
459 RelativePath=".\lllineeditor.h"
460 >
461 </File>
462 <File
463 RelativePath=".\llmemberlistener.h"
464 >
465 </File>
466 <File
467 RelativePath=".\llmenugl.h"
468 >
469 </File>
470 <File
471 RelativePath=".\llmodaldialog.h"
472 >
473 </File>
474 <File
475 RelativePath=".\llpanel.h"
476 >
477 </File>
478 <File
479 RelativePath=".\llradiogroup.h"
480 >
481 </File>
482 <File
483 RelativePath=".\llresizebar.h"
484 >
485 </File>
486 <File
487 RelativePath=".\llresizehandle.h"
488 >
489 </File>
490 <File
491 RelativePath=".\llresmgr.h"
492 >
493 </File>
494 <File
495 RelativePath=".\llrootview.h"
496 >
497 </File>
498 <File
499 RelativePath=".\llscrollbar.h"
500 >
501 </File>
502 <File
503 RelativePath=".\llscrollcontainer.h"
504 >
505 </File>
506 <File
507 RelativePath=".\llscrollingpanellist.h"
508 >
509 </File>
510 <File
511 RelativePath=".\llscrolllistctrl.h"
512 >
513 </File>
514 <File
515 RelativePath=".\llslider.h"
516 >
517 </File>
518 <File
519 RelativePath=".\llsliderctrl.h"
520 >
521 </File>
522 <File
523 RelativePath=".\llspinctrl.h"
524 >
525 </File>
526 <File
527 RelativePath=".\llstyle.h"
528 >
529 </File>
530 <File
531 RelativePath=".\lltabcontainer.h"
532 >
533 </File>
534 <File
535 RelativePath=".\lltabcontainervertical.h"
536 >
537 </File>
538 <File
539 RelativePath=".\lltextbox.h"
540 >
541 </File>
542 <File
543 RelativePath=".\lltexteditor.h"
544 >
545 </File>
546 <File
547 RelativePath=".\llui.h"
548 >
549 </File>
550 <File
551 RelativePath=".\lluiconstants.h"
552 >
553 </File>
554 <File
555 RelativePath=".\lluictrl.h"
556 >
557 </File>
558 <File
559 RelativePath=".\lluictrlfactory.h"
560 >
561 </File>
562 <File
563 RelativePath=".\lluistring.h"
564 >
565 </File>
566 <File
567 RelativePath=".\lluixmltags.h"
568 >
569 </File>
570 <File
571 RelativePath=".\llundo.h"
572 >
573 </File>
574 <File
575 RelativePath=".\llview.h"
576 >
577 </File>
578 <File
579 RelativePath=".\llviewborder.h"
580 >
581 </File>
582 <File
583 RelativePath=".\llviewquery.h"
584 >
585 </File>
586 </Filter>
587 <Filter
588 Name="Resource Files"
589 Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
590 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
591 >
592 </Filter>
593 </Files>
594 <Globals>
595 </Globals>
596</VisualStudioProject>
diff --git a/linden/indra/llui/lluiconstants.h b/linden/indra/llui/lluiconstants.h
index bd75d27..b3b9297 100644
--- a/linden/indra/llui/lluiconstants.h
+++ b/linden/indra/llui/lluiconstants.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp
index 61d6c8c..63db1cc 100644
--- a/linden/indra/llui/lluictrl.cpp
+++ b/linden/indra/llui/lluictrl.cpp
@@ -13,12 +13,12 @@
13 * ("GPL"), unless you have obtained a separate licensing agreement 13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of 14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or 15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2 16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 * 17 *
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at http://secondlife.com/developers/opensource/flossexception 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * 22 *
23 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -47,11 +47,53 @@
47 47
48const U32 MAX_STRING_LENGTH = 10; 48const U32 MAX_STRING_LENGTH = 10;
49 49
50LLUICtrl::LLUICtrl() : 50LLFocusableElement::LLFocusableElement()
51 mCommitCallback(NULL), 51: mFocusLostCallback(NULL),
52 mFocusLostCallback(NULL),
53 mFocusReceivedCallback(NULL), 52 mFocusReceivedCallback(NULL),
54 mFocusChangedCallback(NULL), 53 mFocusChangedCallback(NULL),
54 mFocusCallbackUserData(NULL)
55{
56}
57
58void LLFocusableElement::onFocusReceived()
59{
60 if( mFocusReceivedCallback )
61 {
62 mFocusReceivedCallback( this, mFocusCallbackUserData );
63 }
64 if( mFocusChangedCallback )
65 {
66 mFocusChangedCallback( this, mFocusCallbackUserData );
67 }
68}
69
70void LLFocusableElement::onFocusLost()
71{
72 if( mFocusLostCallback )
73 {
74 mFocusLostCallback( this, mFocusCallbackUserData );
75 }
76
77 if( mFocusChangedCallback )
78 {
79 mFocusChangedCallback( this, mFocusCallbackUserData );
80 }
81}
82
83BOOL LLFocusableElement::hasFocus() const
84{
85 return FALSE;
86}
87
88void LLFocusableElement::setFocus(BOOL b)
89{
90}
91
92
93
94LLUICtrl::LLUICtrl() :
95 mCommitCallback(NULL),
96 mLostTopCallback(NULL),
55 mValidateCallback(NULL), 97 mValidateCallback(NULL),
56 mCallbackUserData(NULL), 98 mCallbackUserData(NULL),
57 mTentative(FALSE), 99 mTentative(FALSE),
@@ -68,9 +110,7 @@ LLUICtrl::LLUICtrl(const LLString& name, const LLRect& rect, BOOL mouse_opaque,
68 // of buttons in the UI. JC 7/20/2002 110 // of buttons in the UI. JC 7/20/2002
69 LLView( name, rect, mouse_opaque, reshape ), 111 LLView( name, rect, mouse_opaque, reshape ),
70 mCommitCallback( on_commit_callback) , 112 mCommitCallback( on_commit_callback) ,
71 mFocusLostCallback( NULL ), 113 mLostTopCallback( NULL ),
72 mFocusReceivedCallback( NULL ),
73 mFocusChangedCallback( NULL ),
74 mValidateCallback( NULL ), 114 mValidateCallback( NULL ),
75 mCallbackUserData( callback_userdata ), 115 mCallbackUserData( callback_userdata ),
76 mTentative( FALSE ), 116 mTentative( FALSE ),
@@ -128,6 +168,86 @@ LLCtrlScrollInterface* LLUICtrl::getScrollInterface()
128 return NULL; 168 return NULL;
129} 169}
130 170
171BOOL LLUICtrl::hasFocus() const
172{
173 return (gFocusMgr.childHasKeyboardFocus(this));
174}
175
176void LLUICtrl::setFocus(BOOL b)
177{
178 // focus NEVER goes to ui ctrls that are disabled!
179 if (!mEnabled)
180 {
181 return;
182 }
183 if( b )
184 {
185 if (!hasFocus())
186 {
187 gFocusMgr.setKeyboardFocus( this );
188 }
189 }
190 else
191 {
192 if( gFocusMgr.childHasKeyboardFocus(this))
193 {
194 gFocusMgr.setKeyboardFocus( NULL );
195 }
196 }
197}
198
199void LLUICtrl::onFocusReceived()
200{
201 // trigger callbacks
202 LLFocusableElement::onFocusReceived();
203
204 // find first view in hierarchy above new focus that is a LLUICtrl
205 LLView* viewp = getParent();
206 LLUICtrl* last_focus = gFocusMgr.getLastKeyboardFocus();
207
208 while (viewp && !viewp->isCtrl())
209 {
210 viewp = viewp->getParent();
211 }
212
213 // and if it has newly gained focus, call onFocusReceived()
214 LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
215 if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp)))
216 {
217 ctrlp->onFocusReceived();
218 }
219}
220
221void LLUICtrl::onFocusLost()
222{
223 // trigger callbacks
224 LLFocusableElement::onFocusLost();
225
226 // find first view in hierarchy above old focus that is a LLUICtrl
227 LLView* viewp = getParent();
228 while (viewp && !viewp->isCtrl())
229 {
230 viewp = viewp->getParent();
231 }
232
233 // and if it has just lost focus, call onFocusReceived()
234 LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
235 // hasFocus() includes any descendants
236 if (ctrlp && !ctrlp->hasFocus())
237 {
238 ctrlp->onFocusLost();
239 }
240}
241
242void LLUICtrl::onLostTop()
243{
244 if (mLostTopCallback)
245 {
246 mLostTopCallback(this, mCallbackUserData);
247 }
248}
249
250
131// virtual 251// virtual
132void LLUICtrl::setTabStop( BOOL b ) 252void LLUICtrl::setTabStop( BOOL b )
133{ 253{
@@ -165,68 +285,26 @@ void LLUICtrl::setIsChrome(BOOL is_chrome)
165// virtual 285// virtual
166BOOL LLUICtrl::getIsChrome() const 286BOOL LLUICtrl::getIsChrome() const
167{ 287{
168 return mIsChrome; 288 // am I or any of my ancestors flagged as "chrome"?
169} 289 if (mIsChrome) return TRUE;
170 290
171void LLUICtrl::onFocusReceived() 291 LLView* parent_ctrl = getParent();
172{ 292 while(parent_ctrl)
173 if( mFocusReceivedCallback )
174 {
175 mFocusReceivedCallback( this, mCallbackUserData );
176 }
177 if( mFocusChangedCallback )
178 { 293 {
179 mFocusChangedCallback( this, mCallbackUserData ); 294 if(parent_ctrl->isCtrl())
180 }
181}
182
183void LLUICtrl::onFocusLost()
184{
185 if( mFocusLostCallback )
186 {
187 mFocusLostCallback( this, mCallbackUserData );
188 }
189
190 if( mFocusChangedCallback )
191 {
192 mFocusChangedCallback( this, mCallbackUserData );
193 }
194}
195
196BOOL LLUICtrl::hasFocus() const
197{
198 return (gFocusMgr.childHasKeyboardFocus(this));
199}
200
201void LLUICtrl::setFocus(BOOL b)
202{
203 // focus NEVER goes to ui ctrls that are disabled!
204 if (!mEnabled)
205 {
206 return;
207 }
208 if( b )
209 {
210 if (!hasFocus())
211 { 295 {
212 gFocusMgr.setKeyboardFocus( this, &LLUICtrl::onFocusLostCallback ); 296 break;
213 onFocusReceived();
214 } 297 }
298 parent_ctrl = parent_ctrl->getParent();
215 } 299 }
216 else 300
301 if(parent_ctrl)
217 { 302 {
218 if( gFocusMgr.childHasKeyboardFocus(this)) 303 // recurse into parent_ctrl and ask if it is in a chrome subtree
219 { 304 return ((LLUICtrl*)parent_ctrl)->getIsChrome();
220 gFocusMgr.setKeyboardFocus( NULL, NULL );
221 onFocusLost();
222 }
223 } 305 }
224}
225 306
226// static 307 return FALSE;
227void LLUICtrl::onFocusLostCallback( LLUICtrl* old_focus )
228{
229 old_focus->onFocusLost();
230} 308}
231 309
232// this comparator uses the crazy disambiguating logic of LLCompareByTabOrder, 310// this comparator uses the crazy disambiguating logic of LLCompareByTabOrder,
@@ -262,6 +340,7 @@ public:
262 } 340 }
263}; 341};
264 342
343
265BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields) 344BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields)
266{ 345{
267 // try to select default tab group child 346 // try to select default tab group child
diff --git a/linden/indra/llui/lluictrl.h b/linden/indra/llui/lluictrl.h
index bf61f8b..55e804c 100644
--- a/linden/indra/llui/lluictrl.h
+++ b/linden/indra/llui/lluictrl.h
@@ -13,12 +13,12 @@
13 * ("GPL"), unless you have obtained a separate licensing agreement 13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of 14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or 15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2 16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 * 17 *
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at http://secondlife.com/developers/opensource/flossexception 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * 22 *
23 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -53,8 +53,31 @@ class LLCtrlScrollInterface;
53typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata); 53typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
54typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata); 54typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata);
55 55
56class LLFocusableElement
57{
58 friend class LLFocusMgr; // allow access to focus change handlers
59public:
60 LLFocusableElement();
61 virtual ~LLFocusableElement() {};
62
63 virtual void setFocus( BOOL b );
64 virtual BOOL hasFocus() const;
65
66 void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; }
67 void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; }
68 void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; }
69
70protected:
71 virtual void onFocusReceived();
72 virtual void onFocusLost();
73 void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata );
74 void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata );
75 void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata );
76 void* mFocusCallbackUserData;
77};
78
56class LLUICtrl 79class LLUICtrl
57: public LLView 80: public LLView, public LLFocusableElement
58{ 81{
59public: 82public:
60 LLUICtrl(); 83 LLUICtrl();
@@ -85,6 +108,11 @@ public:
85 virtual void setFocus( BOOL b ); 108 virtual void setFocus( BOOL b );
86 virtual BOOL hasFocus() const; 109 virtual BOOL hasFocus() const;
87 110
111 virtual void onFocusReceived();
112 virtual void onFocusLost();
113
114 virtual void onLostTop(); // called when registered as top ctrl and user clicks elsewhere
115
88 virtual void setTabStop( BOOL b ); 116 virtual void setTabStop( BOOL b );
89 virtual BOOL hasTabStop() const; 117 virtual BOOL hasTabStop() const;
90 118
@@ -115,6 +143,7 @@ public:
115 143
116 void setCommitCallback( void (*cb)(LLUICtrl*, void*) ) { mCommitCallback = cb; } 144 void setCommitCallback( void (*cb)(LLUICtrl*, void*) ) { mCommitCallback = cb; }
117 void setValidateBeforeCommit( BOOL(*cb)(LLUICtrl*, void*) ) { mValidateCallback = cb; } 145 void setValidateBeforeCommit( BOOL(*cb)(LLUICtrl*, void*) ) { mValidateCallback = cb; }
146 void setLostTopCallback( void (*cb)(LLUICtrl*, void*) ) { mLostTopCallback = cb; }
118 147
119 // Defaults to no-op! 148 // Defaults to no-op!
120 virtual void setDoubleClickCallback( void (*cb)(void*) ); 149 virtual void setDoubleClickCallback( void (*cb)(void*) );
@@ -126,23 +155,8 @@ public:
126 virtual void setMinValue(LLSD min_value); 155 virtual void setMinValue(LLSD min_value);
127 virtual void setMaxValue(LLSD max_value); 156 virtual void setMaxValue(LLSD max_value);
128 157
129 // In general, only LLPanel uses these.
130 void setFocusLostCallback(void (*cb)(LLUICtrl* caller, void* user_data)) { mFocusLostCallback = cb; }
131 void setFocusReceivedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusReceivedCallback = cb; }
132 void setFocusChangedCallback( void (*cb)(LLUICtrl*, void*) ) { mFocusChangedCallback = cb; }
133
134 static void onFocusLostCallback(LLUICtrl* old_focus);
135
136 /*virtual*/ BOOL focusFirstItem(BOOL prefer_text_fields = FALSE ); 158 /*virtual*/ BOOL focusFirstItem(BOOL prefer_text_fields = FALSE );
137 159
138 class LLTabStopPostFilter : public LLQueryFilter, public LLSingleton<LLTabStopPostFilter>
139 {
140 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
141 {
142 return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->hasTabStop() && children.size() == 0, TRUE);
143 }
144 };
145
146 class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter> 160 class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>
147 { 161 {
148 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const 162 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
@@ -157,16 +171,9 @@ public:
157 virtual void resetDirty() {}; 171 virtual void resetDirty() {};
158 172
159protected: 173protected:
160 virtual void onFocusReceived();
161 virtual void onFocusLost();
162 void onChangeFocus( S32 direction );
163
164protected:
165 174
166 void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata ); 175 void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata );
167 void (*mFocusLostCallback)( LLUICtrl* caller, void* userdata ); 176 void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata );
168 void (*mFocusReceivedCallback)( LLUICtrl* ctrl, void* userdata );
169 void (*mFocusChangedCallback)( LLUICtrl* ctrl, void* userdata );
170 BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata ); 177 BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata );
171 178
172 void* mCallbackUserData; 179 void* mCallbackUserData;
diff --git a/linden/indra/llui/lluictrlfactory.cpp b/linden/indra/llui/lluictrlfactory.cpp
index 98228d5..a51d8e4 100644
--- a/linden/indra/llui/lluictrlfactory.cpp
+++ b/linden/indra/llui/lluictrlfactory.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -173,7 +173,7 @@ std::vector<LLString> LLUICtrlFactory::mXUIPaths;
173class LLUICtrlLocate : public LLUICtrl 173class LLUICtrlLocate : public LLUICtrl
174{ 174{
175public: 175public:
176 LLUICtrlLocate() : LLUICtrl("locate", LLRect(0,0,0,0), FALSE, NULL, NULL) {} 176 LLUICtrlLocate() : LLUICtrl("locate", LLRect(0,0,0,0), FALSE, NULL, NULL) { setTabStop(FALSE); }
177 virtual void draw() { } 177 virtual void draw() { }
178 178
179 virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LOCATE; } 179 virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LOCATE; }
@@ -181,7 +181,11 @@ public:
181 181
182 static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) 182 static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
183 { 183 {
184 LLString name("pad");
185 node->getAttributeString("name", name);
186
184 LLUICtrlLocate *new_ctrl = new LLUICtrlLocate(); 187 LLUICtrlLocate *new_ctrl = new LLUICtrlLocate();
188 new_ctrl->setName(name);
185 new_ctrl->initFromXML(node, parent); 189 new_ctrl->initFromXML(node, parent);
186 return new_ctrl; 190 return new_ctrl;
187 } 191 }
@@ -196,6 +200,7 @@ LLUICtrlFactory::LLUICtrlFactory()
196 LLUICtrlCreator<LLButton>::registerCreator(LL_BUTTON_TAG, this); 200 LLUICtrlCreator<LLButton>::registerCreator(LL_BUTTON_TAG, this);
197 LLUICtrlCreator<LLCheckBoxCtrl>::registerCreator(LL_CHECK_BOX_CTRL_TAG, this); 201 LLUICtrlCreator<LLCheckBoxCtrl>::registerCreator(LL_CHECK_BOX_CTRL_TAG, this);
198 LLUICtrlCreator<LLComboBox>::registerCreator(LL_COMBO_BOX_TAG, this); 202 LLUICtrlCreator<LLComboBox>::registerCreator(LL_COMBO_BOX_TAG, this);
203 LLUICtrlCreator<LLFlyoutButton>::registerCreator(LL_FLYOUT_BUTTON_TAG, this);
199 LLUICtrlCreator<LLLineEditor>::registerCreator(LL_LINE_EDITOR_TAG, this); 204 LLUICtrlCreator<LLLineEditor>::registerCreator(LL_LINE_EDITOR_TAG, this);
200 LLUICtrlCreator<LLSearchEditor>::registerCreator(LL_SEARCH_EDITOR_TAG, this); 205 LLUICtrlCreator<LLSearchEditor>::registerCreator(LL_SEARCH_EDITOR_TAG, this);
201 LLUICtrlCreator<LLScrollListCtrl>::registerCreator(LL_SCROLL_LIST_CTRL_TAG, this); 206 LLUICtrlCreator<LLScrollListCtrl>::registerCreator(LL_SCROLL_LIST_CTRL_TAG, this);
@@ -282,8 +287,11 @@ bool LLUICtrlFactory::getLayeredXMLNode(const LLString &filename, LLXMLNodePtr&
282 287
283 if (!LLXMLNode::parseFile(mXUIPaths.front() + filename, root, NULL)) 288 if (!LLXMLNode::parseFile(mXUIPaths.front() + filename, root, NULL))
284 { 289 {
285 llwarns << "Problem reading UI description file: " << mXUIPaths.front() + filename << llendl; 290 if (!LLXMLNode::parseFile(filename, root, NULL))
286 return FALSE; 291 {
292 llwarns << "Problem reading UI description file: " << mXUIPaths.front() + filename << llendl;
293 return FALSE;
294 }
287 } 295 }
288 296
289 LLXMLNodePtr updateRoot; 297 LLXMLNodePtr updateRoot;
diff --git a/linden/indra/llui/lluictrlfactory.h b/linden/indra/llui/lluictrlfactory.h
index 22fac59..fbb8d96 100644
--- a/linden/indra/llui/lluictrlfactory.h
+++ b/linden/indra/llui/lluictrlfactory.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lluistring.cpp b/linden/indra/llui/lluistring.cpp
index 36fba17..d3b5a52 100644
--- a/linden/indra/llui/lluistring.cpp
+++ b/linden/indra/llui/lluistring.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lluistring.h b/linden/indra/llui/lluistring.h
index e52f718..4e9bb55 100644
--- a/linden/indra/llui/lluistring.h
+++ b/linden/indra/llui/lluistring.h
@@ -13,12 +13,12 @@
13 * ("GPL"), unless you have obtained a separate licensing agreement 13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of 14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or 15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2 16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 * 17 *
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at http://secondlife.com/developers/opensource/flossexception 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * 22 *
23 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/lluixmltags.h b/linden/indra/llui/lluixmltags.h
index 84e571f..1afcb00 100644
--- a/linden/indra/llui/lluixmltags.h
+++ b/linden/indra/llui/lluixmltags.h
@@ -11,12 +11,12 @@
11 * ("GPL"), unless you have obtained a separate licensing agreement 11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of 12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or 13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2 14 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
15 * 15 *
16 * There are special exceptions to the terms and conditions of the GPL as 16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception 17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or 18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception 19 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20 * 20 *
21 * By copying, modifying or distributing this software, you acknowledge 21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above, 22 * that you have read and understood your obligations described above,
@@ -120,4 +120,5 @@
120#define LL_JOYSTICK_TURN LLString("joystick_turn") 120#define LL_JOYSTICK_TURN LLString("joystick_turn")
121#define LL_GROUP_DROP_TARGET_TAG LLString("group_drop_target") 121#define LL_GROUP_DROP_TARGET_TAG LLString("group_drop_target")
122#define LL_LAYOUT_STACK_TAG LLString("layout_stack") 122#define LL_LAYOUT_STACK_TAG LLString("layout_stack")
123#define LL_FLYOUT_BUTTON_TAG "flyout_button"
123#endif 124#endif
diff --git a/linden/indra/llui/llundo.cpp b/linden/indra/llui/llundo.cpp
index 3580d31..a267ae2 100644
--- a/linden/indra/llui/llundo.cpp
+++ b/linden/indra/llui/llundo.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llundo.h b/linden/indra/llui/llundo.h
index b3e2457..2bf04bc 100644
--- a/linden/indra/llui/llundo.h
+++ b/linden/indra/llui/llundo.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp
index e18dbb0..04d33a6 100644
--- a/linden/indra/llui/llview.cpp
+++ b/linden/indra/llui/llview.cpp
@@ -13,12 +13,12 @@
13 * ("GPL"), unless you have obtained a separate licensing agreement 13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of 14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or 15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2 16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
17 * 17 *
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at http://secondlife.com/developers/opensource/flossexception 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * 22 *
23 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -113,7 +113,7 @@ LLView::LLView() :
113 mSaveToXML(TRUE), 113 mSaveToXML(TRUE),
114 mIsFocusRoot(FALSE), 114 mIsFocusRoot(FALSE),
115 mLastVisible(TRUE), 115 mLastVisible(TRUE),
116 mSpanChildren(FALSE), 116 mUseBoundingRect(FALSE),
117 mVisible(TRUE), 117 mVisible(TRUE),
118 mHidden(FALSE), 118 mHidden(FALSE),
119 mNextInsertionOrdinal(0) 119 mNextInsertionOrdinal(0)
@@ -133,7 +133,7 @@ LLView::LLView(const LLString& name, BOOL mouse_opaque) :
133 mSaveToXML(TRUE), 133 mSaveToXML(TRUE),
134 mIsFocusRoot(FALSE), 134 mIsFocusRoot(FALSE),
135 mLastVisible(TRUE), 135 mLastVisible(TRUE),
136 mSpanChildren(FALSE), 136 mUseBoundingRect(FALSE),
137 mVisible(TRUE), 137 mVisible(TRUE),
138 mHidden(FALSE), 138 mHidden(FALSE),
139 mNextInsertionOrdinal(0) 139 mNextInsertionOrdinal(0)
@@ -148,6 +148,7 @@ LLView::LLView(
148 mParentView(NULL), 148 mParentView(NULL),
149 mName(name), 149 mName(name),
150 mRect(rect), 150 mRect(rect),
151 mBoundingRect(rect),
151 mReshapeFlags(reshape), 152 mReshapeFlags(reshape),
152 mDefaultTabGroup(0), 153 mDefaultTabGroup(0),
153 mEnabled(TRUE), 154 mEnabled(TRUE),
@@ -156,7 +157,7 @@ LLView::LLView(
156 mSaveToXML(TRUE), 157 mSaveToXML(TRUE),
157 mIsFocusRoot(FALSE), 158 mIsFocusRoot(FALSE),
158 mLastVisible(TRUE), 159 mLastVisible(TRUE),
159 mSpanChildren(FALSE), 160 mUseBoundingRect(FALSE),
160 mVisible(TRUE), 161 mVisible(TRUE),
161 mHidden(FALSE), 162 mHidden(FALSE),
162 mNextInsertionOrdinal(0) 163 mNextInsertionOrdinal(0)
@@ -235,10 +236,16 @@ BOOL LLView::setToolTipArg(const LLStringExplicit& key, const LLStringExplicit&
235 return TRUE; 236 return TRUE;
236} 237}
237 238
239void LLView::setToolTipArgs( const LLString::format_map_t& args )
240{
241 mToolTipMsg.setArgList(args);
242}
243
238// virtual 244// virtual
239void LLView::setRect(const LLRect& rect) 245void LLView::setRect(const LLRect& rect)
240{ 246{
241 mRect = rect; 247 mRect = rect;
248 updateBoundingRect();
242} 249}
243 250
244 251
@@ -287,9 +294,18 @@ void LLView::setName(LLString name)
287 mName = name; 294 mName = name;
288} 295}
289 296
290void LLView::setSpanChildren( BOOL span_children ) 297void LLView::setUseBoundingRect( BOOL use_bounding_rect )
298{
299 if (mUseBoundingRect != use_bounding_rect)
300 {
301 mUseBoundingRect = use_bounding_rect;
302 updateBoundingRect();
303 }
304}
305
306BOOL LLView::getUseBoundingRect()
291{ 307{
292 mSpanChildren = span_children; updateRect(); 308 return mUseBoundingRect;
293} 309}
294 310
295const LLString& LLView::getToolTip() 311const LLString& LLView::getToolTip()
@@ -306,7 +322,7 @@ const LLString& LLView::getName() const
306 322
307void LLView::sendChildToFront(LLView* child) 323void LLView::sendChildToFront(LLView* child)
308{ 324{
309 if (child->mParentView == this) 325 if (child && child->getParent() == this)
310 { 326 {
311 mChildList.remove( child ); 327 mChildList.remove( child );
312 mChildList.push_front(child); 328 mChildList.push_front(child);
@@ -315,7 +331,7 @@ void LLView::sendChildToFront(LLView* child)
315 331
316void LLView::sendChildToBack(LLView* child) 332void LLView::sendChildToBack(LLView* child)
317{ 333{
318 if (child->mParentView == this) 334 if (child && child->getParent() == this)
319 { 335 {
320 mChildList.remove( child ); 336 mChildList.remove( child );
321 mChildList.push_back(child); 337 mChildList.push_back(child);
@@ -330,6 +346,14 @@ void LLView::moveChildToFrontOfTabGroup(LLUICtrl* child)
330 } 346 }
331} 347}
332 348
349void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
350{
351 if(mCtrlOrder.find(child) != mCtrlOrder.end())
352 {
353 mCtrlOrder[child].second = mNextInsertionOrdinal++;
354 }
355}
356
333void LLView::addChild(LLView* child, S32 tab_group) 357void LLView::addChild(LLView* child, S32 tab_group)
334{ 358{
335 if (mParentView == child) 359 if (mParentView == child)
@@ -353,7 +377,7 @@ void LLView::addChild(LLView* child, S32 tab_group)
353 } 377 }
354 378
355 child->mParentView = this; 379 child->mParentView = this;
356 updateRect(); 380 updateBoundingRect();
357} 381}
358 382
359 383
@@ -380,7 +404,7 @@ void LLView::addChildAtEnd(LLView* child, S32 tab_group)
380 } 404 }
381 405
382 child->mParentView = this; 406 child->mParentView = this;
383 updateRect(); 407 updateBoundingRect();
384} 408}
385 409
386// remove the specified child from the view, and set it's parent to NULL. 410// remove the specified child from the view, and set it's parent to NULL.
@@ -403,6 +427,7 @@ void LLView::removeChild(LLView* child, BOOL deleteIt)
403 { 427 {
404 llerrs << "LLView::removeChild called with non-child" << llendl; 428 llerrs << "LLView::removeChild called with non-child" << llendl;
405 } 429 }
430 updateBoundingRect();
406} 431}
407 432
408void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group) 433void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group)
@@ -782,6 +807,7 @@ void LLView::setVisible(BOOL visible)
782 // tell all children of this view that the visibility may have changed 807 // tell all children of this view that the visibility may have changed
783 onVisibilityChange( visible ); 808 onVisibilityChange( visible );
784 } 809 }
810 updateBoundingRect();
785 } 811 }
786} 812}
787 813
@@ -815,6 +841,7 @@ void LLView::onVisibilityChange ( BOOL new_visibility )
815void LLView::translate(S32 x, S32 y) 841void LLView::translate(S32 x, S32 y)
816{ 842{
817 mRect.translate(x, y); 843 mRect.translate(x, y);
844 updateBoundingRect();
818} 845}
819 846
820// virtual 847// virtual
@@ -831,7 +858,8 @@ void LLView::snappedTo(LLView* snap_view)
831BOOL LLView::handleHover(S32 x, S32 y, MASK mask) 858BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
832{ 859{
833 BOOL handled = childrenHandleHover( x, y, mask ) != NULL; 860 BOOL handled = childrenHandleHover( x, y, mask ) != NULL;
834 if( !handled && mMouseOpaque && pointInView( x, y ) ) 861 if( !handled
862 && blockMouseEvent(x, y) )
835 { 863 {
836 LLUI::sWindow->setCursor(UI_CURSOR_ARROW); 864 LLUI::sWindow->setCursor(UI_CURSOR_ARROW);
837 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; 865 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
@@ -876,45 +904,46 @@ BOOL LLView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_scre
876 904
877 LLString tool_tip; 905 LLString tool_tip;
878 906
879 if ( getVisible() && getEnabled()) 907 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
880 { 908 {
881 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) 909 LLView* viewp = *child_it;
910 S32 local_x = x - viewp->mRect.mLeft;
911 S32 local_y = y - viewp->mRect.mBottom;
912 if( viewp->pointInView(local_x, local_y)
913 && viewp->getVisible()
914 && viewp->getEnabled()
915 && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ))
882 { 916 {
883 LLView* viewp = *child_it; 917 handled = TRUE;
884 S32 local_x = x - viewp->mRect.mLeft; 918 break;
885 S32 local_y = y - viewp->mRect.mBottom;
886 if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
887 {
888 handled = TRUE;
889 break;
890 }
891 } 919 }
920 }
892 921
893 tool_tip = mToolTipMsg.getString(); 922 tool_tip = mToolTipMsg.getString();
894 if (LLUI::sShowXUINames && (tool_tip.find(".xml", 0) == LLString::npos) && 923 if (
895 (mName.find("Drag", 0) == LLString::npos)) 924 LLUI::sShowXUINames &&
896 { 925 (tool_tip.find(".xml", 0) == LLString::npos) &&
897 tool_tip = getShowNamesToolTip(); 926 (mName.find("Drag", 0) == LLString::npos))
898 } 927 {
899 928 tool_tip = getShowNamesToolTip();
929 }
900 930
901 BOOL showNamesTextBox = LLUI::sShowXUINames && (getWidgetType() == WIDGET_TYPE_TEXT_BOX); 931 BOOL showNamesTextBox = LLUI::sShowXUINames && (getWidgetType() == WIDGET_TYPE_TEXT_BOX);
902 932
903 if( !handled && (mMouseOpaque || showNamesTextBox) && pointInView( x, y ) && !tool_tip.empty()) 933 if( !handled && (blockMouseEvent(x, y) || showNamesTextBox) && !tool_tip.empty())
904 { 934 {
905 935
906 msg = tool_tip; 936 msg = tool_tip;
907 937
908 // Convert rect local to screen coordinates 938 // Convert rect local to screen coordinates
909 localPointToScreen( 939 localPointToScreen(
910 0, 0, 940 0, 0,
911 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); 941 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
912 localPointToScreen( 942 localPointToScreen(
913 mRect.getWidth(), mRect.getHeight(), 943 mRect.getWidth(), mRect.getHeight(),
914 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); 944 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
915 945
916 handled = TRUE; 946 handled = TRUE;
917 }
918 } 947 }
919 948
920 return handled; 949 return handled;
@@ -1025,7 +1054,7 @@ BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
1025 cargo_data, 1054 cargo_data,
1026 accept, 1055 accept,
1027 tooltip_msg) != NULL; 1056 tooltip_msg) != NULL;
1028 if( !handled && mMouseOpaque ) 1057 if( !handled && blockMouseEvent(x, y) )
1029 { 1058 {
1030 *accept = ACCEPT_NO; 1059 *accept = ACCEPT_NO;
1031 handled = TRUE; 1060 handled = TRUE;
@@ -1081,7 +1110,7 @@ BOOL LLView::hasMouseCapture()
1081BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask) 1110BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
1082{ 1111{
1083 BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL; 1112 BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL;
1084 if( !handled && mMouseOpaque ) 1113 if( !handled && blockMouseEvent(x, y) )
1085 { 1114 {
1086 handled = TRUE; 1115 handled = TRUE;
1087 } 1116 }
@@ -1092,7 +1121,7 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
1092{ 1121{
1093 LLView* handled_view = childrenHandleMouseDown( x, y, mask ); 1122 LLView* handled_view = childrenHandleMouseDown( x, y, mask );
1094 BOOL handled = (handled_view != NULL); 1123 BOOL handled = (handled_view != NULL);
1095 if( !handled && mMouseOpaque ) 1124 if( !handled && blockMouseEvent(x, y) )
1096 { 1125 {
1097 handled = TRUE; 1126 handled = TRUE;
1098 handled_view = this; 1127 handled_view = this;
@@ -1118,7 +1147,7 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
1118BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask) 1147BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
1119{ 1148{
1120 BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL; 1149 BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
1121 if( !handled && mMouseOpaque ) 1150 if( !handled && blockMouseEvent(x, y) )
1122 { 1151 {
1123 handleMouseDown(x, y, mask); 1152 handleMouseDown(x, y, mask);
1124 handled = TRUE; 1153 handled = TRUE;
@@ -1132,7 +1161,7 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
1132 if( getVisible() && mEnabled ) 1161 if( getVisible() && mEnabled )
1133 { 1162 {
1134 handled = childrenHandleScrollWheel( x, y, clicks ) != NULL; 1163 handled = childrenHandleScrollWheel( x, y, clicks ) != NULL;
1135 if( !handled && mMouseOpaque ) 1164 if( !handled && blockMouseEvent(x, y) )
1136 { 1165 {
1137 handled = TRUE; 1166 handled = TRUE;
1138 } 1167 }
@@ -1143,7 +1172,7 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
1143BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask) 1172BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
1144{ 1173{
1145 BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; 1174 BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
1146 if( !handled && mMouseOpaque ) 1175 if( !handled && blockMouseEvent(x, y) )
1147 { 1176 {
1148 handled = TRUE; 1177 handled = TRUE;
1149 } 1178 }
@@ -1153,7 +1182,7 @@ BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
1153BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask) 1182BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask)
1154{ 1183{
1155 BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL; 1184 BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL;
1156 if( !handled && mMouseOpaque ) 1185 if( !handled && blockMouseEvent(x, y) )
1157 { 1186 {
1158 handled = TRUE; 1187 handled = TRUE;
1159 } 1188 }
@@ -1428,10 +1457,10 @@ void LLView::draw()
1428 focus_view = NULL; 1457 focus_view = NULL;
1429 } 1458 }
1430 1459
1460 ++sDepth;
1431 for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter) 1461 for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
1432 { 1462 {
1433 LLView *viewp = *child_iter; 1463 LLView *viewp = *child_iter;
1434 ++sDepth;
1435 1464
1436 if (viewp->getVisible() && viewp != focus_view) 1465 if (viewp->getVisible() && viewp != focus_view)
1437 { 1466 {
@@ -1449,8 +1478,8 @@ void LLView::draw()
1449 } 1478 }
1450 } 1479 }
1451 1480
1452 --sDepth;
1453 } 1481 }
1482 --sDepth;
1454 1483
1455 if (focus_view && focus_view->getVisible()) 1484 if (focus_view && focus_view->getVisible())
1456 { 1485 {
@@ -1467,50 +1496,61 @@ void LLView::draw()
1467//Draw a box for debugging. 1496//Draw a box for debugging.
1468void LLView::drawDebugRect() 1497void LLView::drawDebugRect()
1469{ 1498{
1470 // drawing solids requires texturing be disabled 1499 LLUI::pushMatrix();
1471 LLGLSNoTexture no_texture;
1472
1473 // draw red rectangle for the border
1474 LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
1475 if (sEditingUI)
1476 { 1500 {
1477 border_color.mV[0] = 1.f; 1501 // drawing solids requires texturing be disabled
1478 } 1502 LLGLSNoTexture no_texture;
1479 else
1480 {
1481 border_color.mV[sDepth%3] = 1.f;
1482 }
1483 1503
1484 glColor4fv( border_color.mV ); 1504 if (mUseBoundingRect)
1505 {
1506 LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f);
1507 }
1485 1508
1486 glBegin(GL_LINES); 1509 LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
1487 glVertex2i(0, mRect.getHeight() - 1);
1488 glVertex2i(0, 0);
1489 1510
1490 glVertex2i(0, 0); 1511 // draw red rectangle for the border
1491 glVertex2i(mRect.getWidth() - 1, 0); 1512 LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
1513 if (sEditingUI)
1514 {
1515 border_color.mV[0] = 1.f;
1516 }
1517 else
1518 {
1519 border_color.mV[sDepth%3] = 1.f;
1520 }
1492 1521
1493 glVertex2i(mRect.getWidth() - 1, 0); 1522 glColor4fv( border_color.mV );
1494 glVertex2i(mRect.getWidth() - 1, mRect.getHeight() - 1);
1495 1523
1496 glVertex2i(mRect.getWidth() - 1, mRect.getHeight() - 1); 1524 glBegin(GL_LINES);
1497 glVertex2i(0, mRect.getHeight() - 1); 1525 glVertex2i(0, debug_rect.getHeight() - 1);
1498 glEnd(); 1526 glVertex2i(0, 0);
1499 1527
1500 // Draw the name if it's not a leaf node 1528 glVertex2i(0, 0);
1501 if (mChildList.size() && !sEditingUI) 1529 glVertex2i(debug_rect.getWidth() - 1, 0);
1502 { 1530
1503 //char temp[256]; 1531 glVertex2i(debug_rect.getWidth() - 1, 0);
1504 S32 x, y; 1532 glVertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
1505 glColor4fv( border_color.mV ); 1533
1506 x = mRect.getWidth()/2; 1534 glVertex2i(debug_rect.getWidth() - 1, debug_rect.getHeight() - 1);
1507 y = mRect.getHeight()/2; 1535 glVertex2i(0, debug_rect.getHeight() - 1);
1508 LLString debug_text = llformat("%s (%d x %d)", getName().c_str(), 1536 glEnd();
1509 mRect.getWidth(), mRect.getHeight()); 1537
1510 LLFontGL::sSansSerifSmall->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, 1538 // Draw the name if it's not a leaf node
1511 LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, 1539 if (mChildList.size() && !sEditingUI)
1512 S32_MAX, S32_MAX, NULL, FALSE); 1540 {
1541 //char temp[256];
1542 S32 x, y;
1543 glColor4fv( border_color.mV );
1544 x = debug_rect.getWidth()/2;
1545 y = debug_rect.getHeight()/2;
1546 LLString debug_text = llformat("%s (%d x %d)", getName().c_str(),
1547 debug_rect.getWidth(), debug_rect.getHeight());
1548 LLFontGL::sSansSerifSmall->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
1549 LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL,
1550 S32_MAX, S32_MAX, NULL, FALSE);
1551 }
1513 } 1552 }
1553 LLUI::popMatrix();
1514} 1554}
1515 1555
1516void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_draw) 1556void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_draw)
@@ -1537,9 +1577,6 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr
1537 1577
1538void LLView::reshape(S32 width, S32 height, BOOL called_from_parent) 1578void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
1539{ 1579{
1540 // make sure this view contains all its children
1541 updateRect();
1542
1543 // compute how much things changed and apply reshape logic to children 1580 // compute how much things changed and apply reshape logic to children
1544 S32 delta_width = width - mRect.getWidth(); 1581 S32 delta_width = width - mRect.getWidth();
1545 S32 delta_height = height - mRect.getHeight(); 1582 S32 delta_height = height - mRect.getHeight();
@@ -1608,6 +1645,8 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
1608 mParentView->reshape(mParentView->getRect().getWidth(), mParentView->getRect().getHeight(), FALSE); 1645 mParentView->reshape(mParentView->getRect().getWidth(), mParentView->getRect().getHeight(), FALSE);
1609 } 1646 }
1610 } 1647 }
1648
1649 updateBoundingRect();
1611} 1650}
1612 1651
1613LLRect LLView::getRequiredRect() 1652LLRect LLView::getRequiredRect()
@@ -1615,6 +1654,53 @@ LLRect LLView::getRequiredRect()
1615 return mRect; 1654 return mRect;
1616} 1655}
1617 1656
1657void LLView::updateBoundingRect()
1658{
1659 if (isDead()) return;
1660
1661 if (mUseBoundingRect)
1662 {
1663 LLRect local_bounding_rect = LLRect::null;
1664
1665 child_list_const_iter_t child_it;
1666 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
1667 {
1668 LLView* childp = *child_it;
1669 if (!childp->getVisible()) continue;
1670
1671 LLRect child_bounding_rect = childp->getBoundingRect();
1672
1673 if (local_bounding_rect.isNull())
1674 {
1675 // start out with bounding rect equal to first visible child's bounding rect
1676 local_bounding_rect = child_bounding_rect;
1677 }
1678 else
1679 {
1680 // accumulate non-null children rectangles
1681 if (!child_bounding_rect.isNull())
1682 {
1683 local_bounding_rect.unionWith(child_bounding_rect);
1684 }
1685 }
1686 }
1687
1688 mBoundingRect = local_bounding_rect;
1689 // translate into parent-relative coordinates
1690 mBoundingRect.translate(mRect.mLeft, mRect.mBottom);
1691 }
1692 else
1693 {
1694 mBoundingRect = mRect;
1695 }
1696
1697 // give parent view a chance to resize, in case we just moved, for example
1698 if (getParent() && getParent()->mUseBoundingRect)
1699 {
1700 getParent()->updateBoundingRect();
1701 }
1702}
1703
1618const LLRect LLView::getScreenRect() const 1704const LLRect LLView::getScreenRect() const
1619{ 1705{
1620 // *FIX: check for one-off error 1706 // *FIX: check for one-off error
@@ -1624,6 +1710,15 @@ const LLRect LLView::getScreenRect() const
1624 return screen_rect; 1710 return screen_rect;
1625} 1711}
1626 1712
1713const LLRect LLView::getLocalBoundingRect() const
1714{
1715 LLRect local_bounding_rect = getBoundingRect();
1716 local_bounding_rect.translate(-mRect.mLeft, -mRect.mBottom);
1717
1718 return local_bounding_rect;
1719}
1720
1721
1627const LLRect LLView::getLocalRect() const 1722const LLRect LLView::getLocalRect() const
1628{ 1723{
1629 LLRect local_rect(0, mRect.getHeight(), mRect.getWidth(), 0); 1724 LLRect local_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
@@ -1637,38 +1732,7 @@ const LLRect LLView::getLocalSnapRect() const
1637 return local_snap_rect; 1732 return local_snap_rect;
1638} 1733}
1639 1734
1640void LLView::updateRect() 1735BOOL LLView::hasAncestor(const LLView* parentp)
1641{
1642 if (mSpanChildren && mChildList.size())
1643 {
1644 LLView* first_child = (*mChildList.begin());
1645 LLRect child_spanning_rect = first_child->mRect;
1646
1647 for ( child_list_iter_t child_it = ++mChildList.begin(); child_it != mChildList.end(); ++child_it)
1648 {
1649 LLView* viewp = *child_it;
1650 if (viewp->getVisible())
1651 {
1652 child_spanning_rect.unionWith(viewp->mRect);
1653 }
1654 }
1655
1656 S32 translate_x = llmin(0, child_spanning_rect.mLeft);
1657 S32 translate_y = llmin(0, child_spanning_rect.mBottom);
1658 S32 new_width = llmax(mRect.getWidth() + translate_x, child_spanning_rect.getWidth());
1659 S32 new_height = llmax(mRect.getHeight() + translate_y, child_spanning_rect.getHeight());
1660
1661 mRect.setOriginAndSize(mRect.mLeft + translate_x, mRect.mBottom + translate_y, new_width, new_height);
1662
1663 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
1664 {
1665 LLView* viewp = *child_it;
1666 viewp->mRect.translate(-translate_x, -translate_y);
1667 }
1668 }
1669}
1670
1671BOOL LLView::hasAncestor(LLView* parentp)
1672{ 1736{
1673 if (!parentp) 1737 if (!parentp)
1674 { 1738 {
@@ -1743,14 +1807,23 @@ LLView* LLView::getChildByName(const LLString& name, BOOL recurse) const
1743 return NULL; 1807 return NULL;
1744} 1808}
1745 1809
1746// virtual 1810BOOL LLView::parentPointInView(S32 x, S32 y, EHitTestType type) const
1747void LLView::onFocusLost() 1811{
1748{ 1812 return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
1813 ? mBoundingRect.pointInRect( x, y )
1814 : mRect.pointInRect( x, y );
1749} 1815}
1750 1816
1751// virtual 1817BOOL LLView::pointInView(S32 x, S32 y, EHitTestType type) const
1752void LLView::onFocusReceived() 1818{
1819 return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
1820 ? mBoundingRect.pointInRect( x + mRect.mLeft, y + mRect.mBottom )
1821 : mRect.localPointInRect( x, y );
1822}
1823
1824BOOL LLView::blockMouseEvent(S32 x, S32 y) const
1753{ 1825{
1826 return mMouseOpaque && pointInView(x, y, HIT_TEST_IGNORE_BOUNDING_RECT);
1754} 1827}
1755 1828
1756// virtual 1829// virtual
@@ -2024,9 +2097,9 @@ LLXMLNodePtr LLView::getXML(bool save_children) const
2024 // Export all widgets as enabled and visible - code must disable. 2097 // Export all widgets as enabled and visible - code must disable.
2025 node->createChild("hidden", TRUE)->setBoolValue(mHidden); 2098 node->createChild("hidden", TRUE)->setBoolValue(mHidden);
2026 node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque ); 2099 node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque );
2027 if (!mToolTipMsg.empty()) 2100 if (!mToolTipMsg.getString().empty())
2028 { 2101 {
2029 node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg); 2102 node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg.getString());
2030 } 2103 }
2031 if (mSoundFlags != MOUSE_UP) 2104 if (mSoundFlags != MOUSE_UP)
2032 { 2105 {
@@ -2116,7 +2189,7 @@ const LLCtrlQuery & LLView::getTabOrderQuery()
2116 query.addPreFilter(LLVisibleFilter::getInstance()); 2189 query.addPreFilter(LLVisibleFilter::getInstance());
2117 query.addPreFilter(LLEnabledFilter::getInstance()); 2190 query.addPreFilter(LLEnabledFilter::getInstance());
2118 query.addPreFilter(LLTabStopFilter::getInstance()); 2191 query.addPreFilter(LLTabStopFilter::getInstance());
2119 query.addPostFilter(LLUICtrl::LLTabStopPostFilter::getInstance()); 2192 query.addPostFilter(LLLeavesFilter::getInstance());
2120 } 2193 }
2121 return query; 2194 return query;
2122} 2195}
@@ -2129,6 +2202,7 @@ const LLCtrlQuery & LLView::getFocusRootsQuery()
2129 query.addPreFilter(LLVisibleFilter::getInstance()); 2202 query.addPreFilter(LLVisibleFilter::getInstance());
2130 query.addPreFilter(LLEnabledFilter::getInstance()); 2203 query.addPreFilter(LLEnabledFilter::getInstance());
2131 query.addPreFilter(LLView::LLFocusRootsFilter::getInstance()); 2204 query.addPreFilter(LLView::LLFocusRootsFilter::getInstance());
2205 query.addPostFilter(LLRootsFilter::getInstance());
2132 } 2206 }
2133 return query; 2207 return query;
2134} 2208}
@@ -2593,10 +2667,10 @@ const S32 VPAD = 4;
2593U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect) 2667U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect)
2594{ 2668{
2595 U32 follows = 0; 2669 U32 follows = 0;
2596 S32 x = FLOATER_H_MARGIN; 2670 S32 x = rect.mLeft;
2597 S32 y = 0; 2671 S32 y = rect.mBottom;
2598 S32 w = 0; 2672 S32 w = rect.getWidth();
2599 S32 h = 0; 2673 S32 h = rect.getHeight();
2600 2674
2601 U32 last_x = 0; 2675 U32 last_x = 0;
2602 U32 last_y = 0; 2676 U32 last_y = 0;
@@ -2639,8 +2713,15 @@ U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, con
2639 // view if you don't specify a width. 2713 // view if you don't specify a width.
2640 if (parent_view) 2714 if (parent_view)
2641 { 2715 {
2642 w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x); 2716 if(w == 0)
2643 h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight()); 2717 {
2718 w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x);
2719 }
2720
2721 if(h == 0)
2722 {
2723 h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight());
2724 }
2644 } 2725 }
2645 2726
2646 if (node->hasAttribute("width")) 2727 if (node->hasAttribute("width"))
@@ -2765,44 +2846,7 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent)
2765 setRect(view_rect); 2846 setRect(view_rect);
2766 setFollows(follows_flags); 2847 setFollows(follows_flags);
2767 2848
2768 if (node->hasAttribute("follows")) 2849 parseFollowsFlags(node);
2769 {
2770 setFollowsNone();
2771
2772 LLString follows;
2773 node->getAttributeString("follows", follows);
2774
2775 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
2776 boost::char_separator<char> sep("|");
2777 tokenizer tokens(follows, sep);
2778 tokenizer::iterator token_iter = tokens.begin();
2779
2780 while(token_iter != tokens.end())
2781 {
2782 const std::string& token_str = *token_iter;
2783 if (token_str == "left")
2784 {
2785 setFollowsLeft();
2786 }
2787 else if (token_str == "right")
2788 {
2789 setFollowsRight();
2790 }
2791 else if (token_str == "top")
2792 {
2793 setFollowsTop();
2794 }
2795 else if (token_str == "bottom")
2796 {
2797 setFollowsBottom();
2798 }
2799 else if (token_str == "all")
2800 {
2801 setFollowsAll();
2802 }
2803 ++token_iter;
2804 }
2805 }
2806 2850
2807 if (node->hasAttribute("control_name")) 2851 if (node->hasAttribute("control_name"))
2808 { 2852 {
@@ -2839,11 +2883,57 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent)
2839 setHidden(hidden); 2883 setHidden(hidden);
2840 } 2884 }
2841 2885
2886 node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect);
2887 node->getAttributeBOOL("mouse_opaque", mMouseOpaque);
2888
2842 node->getAttributeS32("default_tab_group", mDefaultTabGroup); 2889 node->getAttributeS32("default_tab_group", mDefaultTabGroup);
2843 2890
2844 reshape(view_rect.getWidth(), view_rect.getHeight()); 2891 reshape(view_rect.getWidth(), view_rect.getHeight());
2845} 2892}
2846 2893
2894void LLView::parseFollowsFlags(LLXMLNodePtr node)
2895{
2896 if (node->hasAttribute("follows"))
2897 {
2898 setFollowsNone();
2899
2900 LLString follows;
2901 node->getAttributeString("follows", follows);
2902
2903 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
2904 boost::char_separator<char> sep("|");
2905 tokenizer tokens(follows, sep);
2906 tokenizer::iterator token_iter = tokens.begin();
2907
2908 while(token_iter != tokens.end())
2909 {
2910 const std::string& token_str = *token_iter;
2911 if (token_str == "left")
2912 {
2913 setFollowsLeft();
2914 }
2915 else if (token_str == "right")
2916 {
2917 setFollowsRight();
2918 }
2919 else if (token_str == "top")
2920 {
2921 setFollowsTop();
2922 }
2923 else if (token_str == "bottom")
2924 {
2925 setFollowsBottom();
2926 }
2927 else if (token_str == "all")
2928 {
2929 setFollowsAll();
2930 }
2931 ++token_iter;
2932 }
2933 }
2934}
2935
2936
2847// static 2937// static
2848LLFontGL* LLView::selectFont(LLXMLNodePtr node) 2938LLFontGL* LLView::selectFont(LLXMLNodePtr node)
2849{ 2939{
diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h
index bd99a13..67a4d56 100644
--- a/linden/indra/llui/llview.h
+++ b/linden/indra/llui/llview.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -50,6 +50,7 @@
50#include "llviewquery.h" 50#include "llviewquery.h"
51#include "llxmlnode.h" 51#include "llxmlnode.h"
52#include "stdenums.h" 52#include "stdenums.h"
53#include "lluistring.h"
53 54
54class LLColor4; 55class LLColor4;
55class LLWindow; 56class LLWindow;
@@ -146,6 +147,7 @@ protected:
146 LLString mName; 147 LLString mName;
147 // location in pixels, relative to surrounding structure, bottom,left=0,0 148 // location in pixels, relative to surrounding structure, bottom,left=0,0
148 LLRect mRect; 149 LLRect mRect;
150 LLRect mBoundingRect;
149 151
150 U32 mReshapeFlags; 152 U32 mReshapeFlags;
151 153
@@ -161,11 +163,11 @@ protected:
161 BOOL mSaveToXML; 163 BOOL mSaveToXML;
162 164
163 BOOL mIsFocusRoot; 165 BOOL mIsFocusRoot;
166 BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements
164 167
165public: 168public:
166 LLViewHandle mViewHandle; 169 LLViewHandle mViewHandle;
167 BOOL mLastVisible; 170 BOOL mLastVisible;
168 BOOL mSpanChildren;
169 171
170private: 172private:
171 BOOL mVisible; 173 BOOL mVisible;
@@ -217,6 +219,7 @@ public:
217 void setMouseOpaque( BOOL b ); 219 void setMouseOpaque( BOOL b );
218 void setToolTip( const LLStringExplicit& msg ); 220 void setToolTip( const LLStringExplicit& msg );
219 BOOL setToolTipArg( const LLStringExplicit& key, const LLStringExplicit& text ); 221 BOOL setToolTipArg( const LLStringExplicit& key, const LLStringExplicit& text );
222 void setToolTipArgs( const LLString::format_map_t& args );
220 223
221 virtual void setRect(const LLRect &rect); 224 virtual void setRect(const LLRect &rect);
222 void setFollows(U32 flags); 225 void setFollows(U32 flags);
@@ -231,13 +234,15 @@ public:
231 234
232 void setSoundFlags(U8 flags); 235 void setSoundFlags(U8 flags);
233 void setName(LLString name); 236 void setName(LLString name);
234 void setSpanChildren( BOOL span_children ); 237 void setUseBoundingRect( BOOL use_bounding_rect );
238 BOOL getUseBoundingRect();
235 239
236 const LLString& getToolTip(); 240 const LLString& getToolTip();
237 241
238 void sendChildToFront(LLView* child); 242 void sendChildToFront(LLView* child);
239 void sendChildToBack(LLView* child); 243 void sendChildToBack(LLView* child);
240 void moveChildToFrontOfTabGroup(LLUICtrl* child); 244 void moveChildToFrontOfTabGroup(LLUICtrl* child);
245 void moveChildToBackOfTabGroup(LLUICtrl* child);
241 246
242 void addChild(LLView* view, S32 tab_group = 0); 247 void addChild(LLView* view, S32 tab_group = 0);
243 void addChildAtEnd(LLView* view, S32 tab_group = 0); 248 void addChildAtEnd(LLView* view, S32 tab_group = 0);
@@ -264,7 +269,7 @@ public:
264 { 269 {
265 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const 270 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
266 { 271 {
267 return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot()); 272 return filterResult_t(view->isCtrl() && view->isFocusRoot(), TRUE);
268 } 273 }
269 }; 274 };
270 275
@@ -312,20 +317,22 @@ public:
312 BOOL followsAll() const { return mReshapeFlags & FOLLOWS_ALL; } 317 BOOL followsAll() const { return mReshapeFlags & FOLLOWS_ALL; }
313 318
314 const LLRect& getRect() const { return mRect; } 319 const LLRect& getRect() const { return mRect; }
320 const LLRect& getBoundingRect() const { return mBoundingRect; }
321 const LLRect getLocalBoundingRect() const;
315 const LLRect getScreenRect() const; 322 const LLRect getScreenRect() const;
316 const LLRect getLocalRect() const; 323 const LLRect getLocalRect() const;
317 virtual const LLRect getSnapRect() const { return mRect; } 324 virtual const LLRect getSnapRect() const { return mRect; }
318 virtual const LLRect getLocalSnapRect() const; 325 virtual const LLRect getLocalSnapRect() const;
319 326
320 virtual LLRect getRequiredRect(); // Get required size for this object. 0 for width/height means don't care. 327 virtual LLRect getRequiredRect(); // Get required size for this object. 0 for width/height means don't care.
321 virtual void updateRect(); // apply procedural updates to own rectangle 328 void updateBoundingRect();
322 329
323 LLView* getRootView(); 330 LLView* getRootView();
324 LLView* getParent() const { return mParentView; } 331 LLView* getParent() const { return mParentView; }
325 LLView* getFirstChild() { return (mChildList.empty()) ? NULL : *(mChildList.begin()); } 332 LLView* getFirstChild() { return (mChildList.empty()) ? NULL : *(mChildList.begin()); }
326 S32 getChildCount() const { return (S32)mChildList.size(); } 333 S32 getChildCount() const { return (S32)mChildList.size(); }
327 template<class _Pr3> void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); } 334 template<class _Pr3> void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); }
328 BOOL hasAncestor(LLView* parentp); 335 BOOL hasAncestor(const LLView* parentp);
329 336
330 BOOL hasChild(const LLString& childname, BOOL recurse = FALSE) const; 337 BOOL hasChild(const LLString& childname, BOOL recurse = FALSE) const;
331 338
@@ -390,6 +397,7 @@ public:
390 397
391 static U32 createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect = LLRect()); 398 static U32 createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect = LLRect());
392 virtual void initFromXML(LLXMLNodePtr node, LLView* parent); 399 virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
400 void parseFollowsFlags(LLXMLNodePtr node);
393 401
394 static LLFontGL* selectFont(LLXMLNodePtr node); 402 static LLFontGL* selectFont(LLXMLNodePtr node);
395 static LLFontGL::HAlign selectFontHAlign(LLXMLNodePtr node); 403 static LLFontGL::HAlign selectFontHAlign(LLXMLNodePtr node);
@@ -428,12 +436,16 @@ public:
428 BOOL getVisible() const { return mVisible && !mHidden; } 436 BOOL getVisible() const { return mVisible && !mHidden; }
429 U8 getSoundFlags() const { return mSoundFlags; } 437 U8 getSoundFlags() const { return mSoundFlags; }
430 438
431 // Default to no action 439 typedef enum e_hit_test_type
432 virtual void onFocusLost(); 440 {
433 virtual void onFocusReceived(); 441 HIT_TEST_USE_BOUNDING_RECT,
442 HIT_TEST_IGNORE_BOUNDING_RECT
443 }EHitTestType;
444
445 BOOL parentPointInView(S32 x, S32 y, EHitTestType type = HIT_TEST_USE_BOUNDING_RECT) const;
446 BOOL pointInView(S32 x, S32 y, EHitTestType type = HIT_TEST_USE_BOUNDING_RECT) const;
447 BOOL blockMouseEvent(S32 x, S32 y) const;
434 448
435 BOOL parentPointInView(S32 x, S32 y) const { return mRect.pointInRect( x, y ); }
436 BOOL pointInView(S32 x, S32 y) const { return mRect.localPointInRect( x, y ); }
437 virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const; 449 virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
438 virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const; 450 virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
439 virtual BOOL localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view); 451 virtual BOOL localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view);
diff --git a/linden/indra/llui/llviewborder.cpp b/linden/indra/llui/llviewborder.cpp
index f2ff8a3..b70edec 100644
--- a/linden/indra/llui/llviewborder.cpp
+++ b/linden/indra/llui/llviewborder.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -84,7 +84,7 @@ void LLViewBorder::setColorsExtended( const LLColor4& shadow_light, const LLColo
84 84
85void LLViewBorder::setTexture( const LLUUID &image_id ) 85void LLViewBorder::setTexture( const LLUUID &image_id )
86{ 86{
87 mTexture = LLUI::sImageProvider->getUIImageByID(image_id); 87 mTexture = LLUI::sImageProvider->getImageByID(image_id);
88} 88}
89 89
90 90
diff --git a/linden/indra/llui/llviewborder.h b/linden/indra/llui/llviewborder.h
index 935257c..d9c2916 100644
--- a/linden/indra/llui/llviewborder.h
+++ b/linden/indra/llui/llviewborder.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
diff --git a/linden/indra/llui/llviewquery.cpp b/linden/indra/llui/llviewquery.cpp
index f86f855..40c2d61 100644
--- a/linden/indra/llui/llviewquery.cpp
+++ b/linden/indra/llui/llviewquery.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -37,9 +37,14 @@
37 37
38void LLQuerySorter::operator() (LLView * parent, viewList_t &children) const {} 38void LLQuerySorter::operator() (LLView * parent, viewList_t &children) const {}
39 39
40filterResult_t LLNoLeavesFilter::operator() (const LLView* const view, const viewList_t & children) const 40filterResult_t LLLeavesFilter::operator() (const LLView* const view, const viewList_t & children) const
41{ 41{
42 return filterResult_t(!(view->getChildList()->size() == 0), TRUE); 42 return filterResult_t(children.empty(), TRUE);
43}
44
45filterResult_t LLRootsFilter::operator() (const LLView* const view, const viewList_t & children) const
46{
47 return filterResult_t(TRUE, FALSE);
43} 48}
44 49
45filterResult_t LLVisibleFilter::operator() (const LLView* const view, const viewList_t & children) const 50filterResult_t LLVisibleFilter::operator() (const LLView* const view, const viewList_t & children) const
@@ -56,6 +61,16 @@ filterResult_t LLTabStopFilter::operator() (const LLView* const view, const view
56 view->canFocusChildren()); 61 view->canFocusChildren());
57} 62}
58 63
64filterResult_t LLCtrlFilter::operator() (const LLView* const view, const viewList_t & children) const
65{
66 return filterResult_t(view->isCtrl(),TRUE);
67}
68
69filterResult_t LLWidgetTypeFilter::operator() (const LLView* const view, const viewList_t & children) const
70{
71 return filterResult_t(view->getWidgetType() == mType, TRUE);
72}
73
59// LLViewQuery 74// LLViewQuery
60 75
61LLViewQuery::LLViewQuery(): mPreFilters(), mPostFilters(), mSorterp() 76LLViewQuery::LLViewQuery(): mPreFilters(), mPostFilters(), mSorterp()
@@ -73,45 +88,53 @@ const LLViewQuery::filterList_t & LLViewQuery::getPostFilters() const { return m
73void LLViewQuery::setSorter(const LLQuerySorter* sorterp) { mSorterp = sorterp; } 88void LLViewQuery::setSorter(const LLQuerySorter* sorterp) { mSorterp = sorterp; }
74const LLQuerySorter* LLViewQuery::getSorter() const { return mSorterp; } 89const LLQuerySorter* LLViewQuery::getSorter() const { return mSorterp; }
75 90
76viewList_t LLViewQuery::run(LLView * view) const 91viewList_t LLViewQuery::run(LLView* view) const
77{ 92{
78 viewList_t result; 93 viewList_t result;
79 94
80 filterResult_t pre = runFilters(view, viewList_t(), mPreFilters); 95 // prefilter gets immediate children of view
96 filterResult_t pre = runFilters(view, *view->getChildList(), mPreFilters);
81 if(!pre.first && !pre.second) 97 if(!pre.first && !pre.second)
82 { 98 {
83 // skip post filters completely if we're not including ourselves or the children 99 // not including ourselves or the children
100 // nothing more to do
84 return result; 101 return result;
85 } 102 }
103
104 viewList_t filtered_children;
105 filterResult_t post(TRUE, TRUE);
86 if(pre.second) 106 if(pre.second)
87 { 107 {
88 // run filters on children 108 // run filters on children
89 viewList_t filtered_children;
90 filterChildren(view, filtered_children); 109 filterChildren(view, filtered_children);
91 filterResult_t post = runFilters(view, filtered_children, mPostFilters); 110 // only run post filters if this element passed pre filters
92 if(pre.first && post.first) 111 // so if you failed to pass the pre filter, you can't filter out children in post
93 { 112 if (pre.first)
94 result.push_back(view);
95 }
96 if(post.second)
97 { 113 {
98 result.insert(result.end(), filtered_children.begin(), filtered_children.end()); 114 post = runFilters(view, filtered_children, mPostFilters);
99 } 115 }
100 } 116 }
101 else 117
118 if(pre.first && post.first)
102 { 119 {
103 if(pre.first) 120 result.push_back(view);
104 { 121 }
105 result.push_back(view); 122
106 } 123 if(pre.second && post.second)
124 {
125 result.insert(result.end(), filtered_children.begin(), filtered_children.end());
107 } 126 }
127
108 return result; 128 return result;
109} 129}
110 130
111void LLViewQuery::filterChildren(LLView * view, viewList_t & filtered_children) const 131void LLViewQuery::filterChildren(LLView * view, viewList_t & filtered_children) const
112{ 132{
113 LLView::child_list_t views(*(view->getChildList())); 133 LLView::child_list_t views(*(view->getChildList()));
114 (*mSorterp)(view, views); // sort the children per the sorter 134 if (mSorterp)
135 {
136 (*mSorterp)(view, views); // sort the children per the sorter
137 }
115 for(LLView::child_list_iter_t iter = views.begin(); 138 for(LLView::child_list_iter_t iter = views.begin();
116 iter != views.end(); 139 iter != views.end();
117 iter++) 140 iter++)
diff --git a/linden/indra/llui/llviewquery.h b/linden/indra/llui/llviewquery.h
index 9fe51a4..2e2b50d 100644
--- a/linden/indra/llui/llviewquery.h
+++ b/linden/indra/llui/llviewquery.h
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -35,6 +35,7 @@
35#include <list> 35#include <list>
36 36
37#include "llmemory.h" 37#include "llmemory.h"
38#include "llui.h"
38 39
39class LLView; 40class LLView;
40 41
@@ -42,35 +43,60 @@ typedef std::list<LLView *> viewList_t;
42typedef std::pair<BOOL, BOOL> filterResult_t; 43typedef std::pair<BOOL, BOOL> filterResult_t;
43 44
44// Abstract base class for all filters. 45// Abstract base class for all filters.
45class LLQueryFilter : public LLRefCount 46class LLQueryFilter
46{ 47{
47public: 48public:
49 virtual ~LLQueryFilter() {};
48 virtual filterResult_t operator() (const LLView* const view, const viewList_t & children) const =0; 50 virtual filterResult_t operator() (const LLView* const view, const viewList_t & children) const =0;
49}; 51};
50 52
51class LLQuerySorter : public LLRefCount 53class LLQuerySorter
52{ 54{
53public: 55public:
56 virtual ~LLQuerySorter() {};
54 virtual void operator() (LLView * parent, viewList_t &children) const; 57 virtual void operator() (LLView * parent, viewList_t &children) const;
55}; 58};
56 59
57class LLNoLeavesFilter : public LLQueryFilter, public LLSingleton<LLNoLeavesFilter> 60class LLLeavesFilter : public LLQueryFilter, public LLSingleton<LLLeavesFilter>
58{ 61{
59 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; 62 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
60}; 63};
64
65class LLRootsFilter : public LLQueryFilter, public LLSingleton<LLRootsFilter>
66{
67 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
68};
69
61class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter> 70class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>
62{ 71{
63 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; 72 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
64}; 73};
74
65class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter> 75class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>
66{ 76{
67 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; 77 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
68}; 78};
79
69class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter> 80class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>
70{ 81{
71 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; 82 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
72}; 83};
73 84
85class LLCtrlFilter : public LLQueryFilter, public LLSingleton<LLCtrlFilter>
86{
87 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
88};
89
90class LLWidgetTypeFilter : public LLQueryFilter
91{
92public:
93 LLWidgetTypeFilter(EWidgetType type) : mType(type) {};
94private:
95 /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
96
97 EWidgetType mType;
98};
99
74// Algorithm for flattening 100// Algorithm for flattening
75class LLViewQuery 101class LLViewQuery
76{ 102{