diff options
author | Jacek Antonelli | 2009-04-30 13:04:20 -0500 |
---|---|---|
committer | Jacek Antonelli | 2009-04-30 13:07:16 -0500 |
commit | ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e (patch) | |
tree | 8348301d0ac44a524f1819b777686bf086907d76 /linden/indra/llui | |
parent | Second Life viewer sources 1.22.11 (diff) | |
download | meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.zip meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.gz meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.bz2 meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.xz |
Second Life viewer sources 1.23.0-RC
Diffstat (limited to 'linden/indra/llui')
103 files changed, 4873 insertions, 1287 deletions
diff --git a/linden/indra/llui/CMakeLists.txt b/linden/indra/llui/CMakeLists.txt index 77efec5..32118e8 100644 --- a/linden/indra/llui/CMakeLists.txt +++ b/linden/indra/llui/CMakeLists.txt | |||
@@ -36,6 +36,7 @@ set(llui_SOURCE_FILES | |||
36 | lleditmenuhandler.cpp | 36 | lleditmenuhandler.cpp |
37 | llfloater.cpp | 37 | llfloater.cpp |
38 | llfocusmgr.cpp | 38 | llfocusmgr.cpp |
39 | llfunctorregistry.cpp | ||
39 | lliconctrl.cpp | 40 | lliconctrl.cpp |
40 | llkeywords.cpp | 41 | llkeywords.cpp |
41 | lllineeditor.cpp | 42 | lllineeditor.cpp |
@@ -43,7 +44,9 @@ set(llui_SOURCE_FILES | |||
43 | llmodaldialog.cpp | 44 | llmodaldialog.cpp |
44 | llmultislider.cpp | 45 | llmultislider.cpp |
45 | llmultisliderctrl.cpp | 46 | llmultisliderctrl.cpp |
47 | llnotifications.cpp | ||
46 | llpanel.cpp | 48 | llpanel.cpp |
49 | llprogressbar.cpp | ||
47 | llradiogroup.cpp | 50 | llradiogroup.cpp |
48 | llresizebar.cpp | 51 | llresizebar.cpp |
49 | llresizehandle.cpp | 52 | llresizehandle.cpp |
@@ -61,10 +64,12 @@ set(llui_SOURCE_FILES | |||
61 | lltabcontainervertical.cpp | 64 | lltabcontainervertical.cpp |
62 | lltextbox.cpp | 65 | lltextbox.cpp |
63 | lltexteditor.cpp | 66 | lltexteditor.cpp |
67 | lltextparser.cpp | ||
64 | llui.cpp | 68 | llui.cpp |
65 | lluictrl.cpp | 69 | lluictrl.cpp |
66 | lluictrlfactory.cpp | 70 | lluictrlfactory.cpp |
67 | lluistring.cpp | 71 | lluistring.cpp |
72 | lluitrans.cpp | ||
68 | llundo.cpp | 73 | llundo.cpp |
69 | llviewborder.cpp | 74 | llviewborder.cpp |
70 | llview.cpp | 75 | llview.cpp |
@@ -85,6 +90,7 @@ set(llui_HEADER_FILES | |||
85 | lleditmenuhandler.h | 90 | lleditmenuhandler.h |
86 | llfloater.h | 91 | llfloater.h |
87 | llfocusmgr.h | 92 | llfocusmgr.h |
93 | llfunctorregistry.h | ||
88 | llhtmlhelp.h | 94 | llhtmlhelp.h |
89 | lliconctrl.h | 95 | lliconctrl.h |
90 | llkeywords.h | 96 | llkeywords.h |
@@ -94,7 +100,9 @@ set(llui_HEADER_FILES | |||
94 | llmodaldialog.h | 100 | llmodaldialog.h |
95 | llmultisliderctrl.h | 101 | llmultisliderctrl.h |
96 | llmultislider.h | 102 | llmultislider.h |
103 | llnotifications.h | ||
97 | llpanel.h | 104 | llpanel.h |
105 | llprogressbar.h | ||
98 | llradiogroup.h | 106 | llradiogroup.h |
99 | llresizebar.h | 107 | llresizebar.h |
100 | llresizehandle.h | 108 | llresizehandle.h |
@@ -112,12 +120,14 @@ set(llui_HEADER_FILES | |||
112 | lltabcontainervertical.h | 120 | lltabcontainervertical.h |
113 | lltextbox.h | 121 | lltextbox.h |
114 | lltexteditor.h | 122 | lltexteditor.h |
123 | lltextparser.h | ||
115 | lluiconstants.h | 124 | lluiconstants.h |
116 | lluictrlfactory.h | 125 | lluictrlfactory.h |
117 | lluictrl.h | 126 | lluictrl.h |
118 | lluifwd.h | 127 | lluifwd.h |
119 | llui.h | 128 | llui.h |
120 | lluistring.h | 129 | lluistring.h |
130 | lluitrans.h | ||
121 | lluixmltags.h | 131 | lluixmltags.h |
122 | llundo.h | 132 | llundo.h |
123 | llviewborder.h | 133 | llviewborder.h |
diff --git a/linden/indra/llui/llalertdialog.cpp b/linden/indra/llui/llalertdialog.cpp index 80e54b6..f321db8 100644 --- a/linden/indra/llui/llalertdialog.cpp +++ b/linden/indra/llui/llalertdialog.cpp | |||
@@ -1,5 +1,4 @@ | |||
1 | /** | 1 | /* @file llalertdialog.cpp |
2 | * @file llalertdialog.cpp | ||
3 | * @brief LLAlertDialog base class | 2 | * @brief LLAlertDialog base class |
4 | * | 3 | * |
5 | * $LicenseInfo:firstyear=2001&license=viewergpl$ | 4 | * $LicenseInfo:firstyear=2001&license=viewergpl$ |
@@ -17,7 +16,8 @@ | |||
17 | * 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 |
18 | * 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 |
19 | * 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 |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 19 | * online at |
20 | * 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, |
@@ -46,85 +46,55 @@ | |||
46 | #include "llxmlnode.h" | 46 | #include "llxmlnode.h" |
47 | #include "lllineeditor.h" | 47 | #include "lllineeditor.h" |
48 | #include "lluictrlfactory.h" | 48 | #include "lluictrlfactory.h" |
49 | 49 | #include "llnotifications.h" | |
50 | #include "llfunctorregistry.h" | ||
50 | 51 | ||
51 | const S32 MAX_ALLOWED_MSG_WIDTH = 400; | 52 | const S32 MAX_ALLOWED_MSG_WIDTH = 400; |
52 | const F32 DEFAULT_BUTTON_DELAY = 0.5f; | 53 | const F32 DEFAULT_BUTTON_DELAY = 0.5f; |
53 | const S32 MSG_PAD = 8; | 54 | const S32 MSG_PAD = 8; |
54 | 55 | ||
55 | /*static*/ LLAlertDialog::template_map_t LLAlertDialog::sAlertTemplates; | ||
56 | /*static*/ LLAlertDialog::template_map_t LLAlertDialog::sIgnorableTemplates; | ||
57 | /*static*/ LLControlGroup* LLAlertDialog::sSettings = NULL; | 56 | /*static*/ LLControlGroup* LLAlertDialog::sSettings = NULL; |
58 | /*static*/ std::map<std::string,LLAlertDialog*> LLAlertDialog::sUniqueActiveMap; | ||
59 | /*static*/ LLAlertDialog::display_callback_t LLAlertDialog::sDisplayCallback; | ||
60 | /*static*/ std::string LLAlertDialog::sStringSkipNextTime("Skip this dialog next time"); | ||
61 | /*static*/ std::string LLAlertDialog::sStringAlwaysChoose("Always choose this option"); | ||
62 | /*static*/ LLAlertDialog::URLLoader* LLAlertDialog::sURLLoader; | 57 | /*static*/ LLAlertDialog::URLLoader* LLAlertDialog::sURLLoader; |
63 | 58 | ||
64 | |||
65 | //static | 59 | //static |
66 | LLAlertDialog* LLAlertDialog::createXml( const std::string& xml_desc, | 60 | void LLAlertDialog::initClass() |
67 | alert_callback_t callback, void *user_data) | ||
68 | { | 61 | { |
69 | LLStringUtil::format_map_t args; | 62 | LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); |
70 | return createXml(xml_desc, args, callback, user_data); | 63 | LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); |
64 | LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&onNewNotification, _1, false)); | ||
65 | LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&onNewNotification, _1, true)); | ||
71 | } | 66 | } |
72 | 67 | ||
73 | //static | 68 | //static |
74 | LLAlertDialog* LLAlertDialog::createXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, | 69 | bool LLAlertDialog::onNewNotification(const LLSD& notify, bool is_modal) |
75 | alert_callback_t callback, void *user_data) | ||
76 | { | 70 | { |
77 | template_map_t::iterator iter = sAlertTemplates.find(xml_desc); | 71 | LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); |
78 | if (iter != sAlertTemplates.end()) | 72 | |
79 | { | 73 | if(notification) |
80 | LLAlertDialogTemplate* xml_template = iter->second; | ||
81 | // deletes itself | ||
82 | llwarns << "Alert: [" << xml_desc << "] " << llendl; | ||
83 | LLAlertDialog* dialog = new LLAlertDialog( xml_template, args, callback, user_data); | ||
84 | return dialog; | ||
85 | } | ||
86 | else | ||
87 | { | 74 | { |
88 | LLStringUtil::format_map_t args; | 75 | if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") |
89 | args["[ALERT_NAME]"] = xml_desc; | ||
90 | llwarns << "Missing Alert: [" << xml_desc << "]" << llendl; | ||
91 | LLAlertDialog* dialogp = LLAlertDialog::showXml("MissingAlert", args); | ||
92 | if (dialogp == NULL) | ||
93 | { | 76 | { |
94 | llerrs << "Bad or missing alerts.xml!" << llendl; | 77 | LLAlertDialog* dialog = new LLAlertDialog(notification, is_modal); |
78 | dialog->show(); | ||
79 | } | ||
80 | else if (notify["sigtype"].asString() == "change") | ||
81 | { | ||
82 | LLAlertDialog* dialog = getInstance(notification->getID()); | ||
83 | if (dialog) | ||
84 | { | ||
85 | dialog->show(); | ||
86 | } | ||
87 | else | ||
88 | { | ||
89 | LLAlertDialog* dialog = new LLAlertDialog(notification, is_modal); | ||
90 | dialog->show(); | ||
91 | } | ||
95 | } | 92 | } |
96 | return NULL; | ||
97 | } | 93 | } |
98 | } | ||
99 | |||
100 | //static | ||
101 | LLAlertDialog* LLAlertDialog::showXml( const std::string& xml_desc, | ||
102 | alert_callback_t callback, void *user_data) | ||
103 | { | ||
104 | LLStringUtil::format_map_t args; | ||
105 | return showXml(xml_desc, args, callback, user_data); | ||
106 | } | ||
107 | 94 | ||
108 | //static | 95 | return false; |
109 | LLAlertDialog* LLAlertDialog::showXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, | ||
110 | alert_callback_t callback, void *user_data) | ||
111 | { | ||
112 | LLAlertDialog* dialog = createXml(xml_desc, args, callback, user_data); | ||
113 | return dialog && dialog->show() ? dialog : NULL; | ||
114 | } | 96 | } |
115 | 97 | ||
116 | //static | ||
117 | LLAlertDialog* LLAlertDialog::showCritical( const std::string& desc, alert_callback_t callback, void *user_data) | ||
118 | { | ||
119 | LLAlertDialogTemplate xml_template; | ||
120 | LLStringUtil::format_map_t args; | ||
121 | xml_template.mTitle = "Critical Error"; | ||
122 | xml_template.mMessage = desc; | ||
123 | xml_template.mModal = TRUE; | ||
124 | xml_template.mOptions.push_back("Quit"); | ||
125 | LLAlertDialog* dialog = new LLAlertDialog( &xml_template, args, callback, user_data); | ||
126 | return dialog && dialog->show() ? dialog : NULL; | ||
127 | } | ||
128 | 98 | ||
129 | //----------------------------------------------------------------------------- | 99 | //----------------------------------------------------------------------------- |
130 | // Private methods | 100 | // Private methods |
@@ -132,183 +102,110 @@ LLAlertDialog* LLAlertDialog::showCritical( const std::string& desc, alert_callb | |||
132 | static const S32 VPAD = 16; | 102 | static const S32 VPAD = 16; |
133 | static const S32 HPAD = 25; | 103 | static const S32 HPAD = 25; |
134 | static const S32 BTN_HPAD = 8; | 104 | static const S32 BTN_HPAD = 8; |
135 | static const LLFONT_ID font_name = LLFONT_SANSSERIF; | 105 | static const LLFONT_ID FONT_NAME = LLFONT_SANSSERIF; |
136 | 106 | ||
137 | LLAlertDialog::LLAlertDialog( const LLAlertDialogTemplate* xml_template, | 107 | LLAlertDialog::LLAlertDialog( LLNotificationPtr notification, bool modal) |
138 | const LLStringUtil::format_map_t& args, | 108 | : LLModalDialog( notification->getLabel(), 100, 100, modal ), // dummy size. Will reshape below. |
139 | alert_callback_t callback, void *user_data) | 109 | LLInstanceTracker<LLAlertDialog, LLUUID>(notification->getID()), |
140 | : LLModalDialog( xml_template->mTitle, 100, 100, xml_template->mModal ), // dummy size. Will reshape below. | ||
141 | mCallback( callback ), | ||
142 | mUserData( user_data ), | ||
143 | mNumOptions( 0 ), | ||
144 | mDefaultOption( 0 ), | 110 | mDefaultOption( 0 ), |
145 | mOptionChosen( -1 ), | ||
146 | mCheck(NULL), | 111 | mCheck(NULL), |
147 | mCaution(xml_template->mCaution), | 112 | mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH), |
148 | mUnique(xml_template->mUnique), | 113 | mLabel(notification->getName()), |
149 | mIgnorable(xml_template->mIgnorable), | ||
150 | mLabel(xml_template->mLabel), | ||
151 | mIgnoreLabel(xml_template->mIgnoreLabel), | ||
152 | mButtonData(NULL), | ||
153 | mLineEditor(NULL), | 114 | mLineEditor(NULL), |
154 | mTextCallback(NULL), | 115 | mNote(notification) |
155 | mURLOption(0) | ||
156 | { | 116 | { |
157 | mURL = xml_template->mURL; | 117 | const LLFontGL* font = LLResMgr::getInstance()->getRes( FONT_NAME ); |
158 | mURLOption = xml_template->mURLOption; | 118 | const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); |
159 | createDialog(xml_template->mOptions, xml_template->mDefaultOption, | 119 | const S32 EDITOR_HEIGHT = 20; |
160 | xml_template->mMessage, args, | ||
161 | xml_template->mEditLineText); | ||
162 | setTitle(xml_template->mTitle); | ||
163 | if (xml_template->mIgnorable) | ||
164 | { | ||
165 | if (xml_template->mIgnorable == IGNORE_USE_DEFAULT) | ||
166 | { | ||
167 | setCheckBox(sStringSkipNextTime, xml_template->mIgnoreLabel); | ||
168 | } | ||
169 | else // xml_template->mIgnorable == IGNORE_USE_SAVED | ||
170 | { | ||
171 | setCheckBox(sStringAlwaysChoose, xml_template->mIgnoreLabel); | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | 120 | ||
176 | // All logic for deciding not to show an alert is done here, | 121 | LLNotificationFormPtr form = mNote->getForm(); |
177 | // so that the alert is valid until show() is called. | 122 | std::string edit_text_name; |
178 | bool LLAlertDialog::show() | 123 | std::string edit_text_contents; |
179 | { | 124 | bool is_password = false; |
180 | // If modal, check to see if we are not displaying alerts, | 125 | |
181 | // and do any application logic before showing modal alerts | 126 | setBackgroundVisible(TRUE); |
182 | if (sDisplayCallback) | 127 | setBackgroundOpaque(TRUE); |
183 | { | ||
184 | bool show = sDisplayCallback(isModal()); | ||
185 | if (show == false) | ||
186 | { | ||
187 | mOptionChosen = mDefaultOption; | ||
188 | llinfos << "Alert: " << mLabel << llendl; | ||
189 | close(); | ||
190 | return false; | ||
191 | } | ||
192 | } | ||
193 | 128 | ||
194 | // Check to see if the user wants to ignore this alert | 129 | |
195 | if (mIgnorable > 0) | 130 | typedef std::vector<std::pair<std::string, std::string> > options_t; |
131 | options_t supplied_options; | ||
132 | |||
133 | // for now, get LLSD to iterator over form elements | ||
134 | LLSD form_sd = form->asLLSD(); | ||
135 | |||
136 | S32 option_index = 0; | ||
137 | for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it) | ||
196 | { | 138 | { |
197 | BOOL warn = sSettings->getWarning(mIgnoreLabel); | 139 | std::string type = (*it)["type"].asString(); |
198 | if (!warn) | 140 | if (type == "button") |
199 | { | 141 | { |
200 | switch(mIgnorable) | 142 | if((*it)["default"]) |
201 | { | 143 | { |
202 | case IGNORE_USE_DEFAULT: | 144 | mDefaultOption = option_index; |
203 | mOptionChosen = mDefaultOption; | ||
204 | break; | ||
205 | case IGNORE_USE_SAVED: | ||
206 | mOptionChosen = sSettings->getS32("Default" + mIgnoreLabel); | ||
207 | break; | ||
208 | case IGNORE_SHOW_AGAIN: | ||
209 | break; | ||
210 | } | 145 | } |
211 | close(); | ||
212 | return false; | ||
213 | } | ||
214 | } | ||
215 | 146 | ||
216 | // If this is a caution message, change the color and add an icon. | 147 | supplied_options.push_back(std::make_pair((*it)["name"].asString(), (*it)["text"].asString())); |
217 | if (mCaution) | ||
218 | { | ||
219 | setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertCautionBoxColor" ) ); | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertBoxColor" ) ); | ||
224 | } | ||
225 | 148 | ||
226 | // Check to see if we are already displaying the alert | 149 | ButtonData data; |
227 | if (mUnique) | 150 | data.mSelf = this; |
228 | { | 151 | if (option_index == mNote->getURLOption()) |
229 | std::map<std::string,LLAlertDialog*>::iterator iter = sUniqueActiveMap.find(mLabel); | 152 | { |
230 | if (iter != sUniqueActiveMap.end()) | 153 | data.mURL = mNote->getURL(); |
154 | } | ||
155 | |||
156 | mButtonData.push_back(data); | ||
157 | option_index++; | ||
158 | } | ||
159 | else if (type == "text") | ||
231 | { | 160 | { |
232 | gFloaterView->bringToFront(iter->second); | 161 | edit_text_contents = (*it)["value"].asString(); |
233 | mUnique = FALSE; // don't remove entry from map on destruction | 162 | edit_text_name = (*it)["name"].asString(); |
234 | close(); | 163 | } |
235 | return false; | 164 | else if (type == "password") |
165 | { | ||
166 | edit_text_contents = (*it)["value"].asString(); | ||
167 | edit_text_name = (*it)["name"].asString(); | ||
168 | is_password = true; | ||
236 | } | 169 | } |
237 | sUniqueActiveMap[mLabel] = this; | ||
238 | } | ||
239 | startModal(); | ||
240 | gFloaterView->adjustToFitScreen(this, FALSE); | ||
241 | open(); /* Flawfinder: ignore */ | ||
242 | setFocus(TRUE); | ||
243 | if (mLineEditor) | ||
244 | { | ||
245 | mLineEditor->setFocus(TRUE); | ||
246 | mLineEditor->selectAll(); | ||
247 | } | ||
248 | if(mDefaultOption >= 0) | ||
249 | { | ||
250 | // delay before enabling default button | ||
251 | mDefaultBtnTimer.start(); | ||
252 | mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY); | ||
253 | } | 170 | } |
254 | return true; | ||
255 | } | ||
256 | |||
257 | void LLAlertDialog::format(std::string& msg, const LLStringUtil::format_map_t& args) | ||
258 | { | ||
259 | // XUI:translate! | ||
260 | LLStringUtil::format_map_t targs = args; | ||
261 | targs["[SECOND_LIFE]"] = "Second Life"; | ||
262 | targs["[_URL]"] = mURL; | ||
263 | LLStringUtil::format(msg, targs); | ||
264 | } | ||
265 | 171 | ||
266 | void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_option, | ||
267 | const std::string& msg_in, const LLStringUtil::format_map_t& args, | ||
268 | const std::string& edit_text) | ||
269 | { | ||
270 | setBackgroundVisible(TRUE); | ||
271 | setBackgroundOpaque(TRUE); | ||
272 | |||
273 | const LLFontGL* font = LLResMgr::getInstance()->getRes( font_name ); | ||
274 | const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); | ||
275 | const S32 EDITOR_HEIGHT = 20; | ||
276 | |||
277 | const options_list_t* optionsp = &options_in; | ||
278 | |||
279 | // Buttons | 172 | // Buttons |
280 | options_list_t default_option_list; | 173 | options_t options; |
281 | mNumOptions = options_in.size(); | 174 | if (supplied_options.empty()) |
282 | if( 0 == mNumOptions ) | ||
283 | { | 175 | { |
284 | default_option_list.push_back("Close"); | 176 | options.push_back(std::make_pair(std::string("close"), std::string("Close"))); |
285 | optionsp = &default_option_list; | 177 | |
286 | default_option = 0; | 178 | // add data for ok button. |
287 | mNumOptions = 1; | 179 | ButtonData ok_button; |
180 | ok_button.mSelf = this; | ||
181 | |||
182 | mButtonData.push_back(ok_button); | ||
183 | mDefaultOption = 0; | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | options = supplied_options; | ||
288 | } | 188 | } |
289 | 189 | ||
290 | const options_list_t& options= *optionsp; | 190 | S32 num_options = options.size(); |
291 | |||
292 | mButtonData = new ButtonData[mNumOptions]; | ||
293 | 191 | ||
294 | // Calc total width of buttons | 192 | // Calc total width of buttons |
295 | S32 button_width = 0; | 193 | S32 button_width = 0; |
296 | S32 sp = font->getWidth(std::string("OO")); | 194 | S32 sp = font->getWidth(std::string("OO")); |
297 | for( S32 i = 0; i < mNumOptions; i++ ) | 195 | for( S32 i = 0; i < num_options; i++ ) |
298 | { | 196 | { |
299 | S32 w = S32(font->getWidth( options[i] ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD; | 197 | S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD; |
300 | button_width = llmax( w, button_width ); | 198 | button_width = llmax( w, button_width ); |
301 | } | 199 | } |
302 | S32 btn_total_width = button_width; | 200 | S32 btn_total_width = button_width; |
303 | if( mNumOptions > 1 ) | 201 | if( num_options > 1 ) |
304 | { | 202 | { |
305 | btn_total_width = (mNumOptions * button_width) + ((mNumOptions - 1) * BTN_HPAD); | 203 | btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD); |
306 | } | 204 | } |
307 | 205 | ||
308 | // Message: create text box using raw string, as text has been structure deliberately | 206 | // Message: create text box using raw string, as text has been structure deliberately |
309 | // Use size of created text box to generate dialog box size | 207 | // Use size of created text box to generate dialog box size |
310 | std::string msg = msg_in; | 208 | std::string msg = mNote->getMessage(); |
311 | format( msg, args ); | ||
312 | llwarns << "Alert: " << msg << llendl; | 209 | llwarns << "Alert: " << msg << llendl; |
313 | LLTextBox* msg_box = new LLTextBox( std::string("Alert message"), msg, (F32)MAX_ALLOWED_MSG_WIDTH, font ); | 210 | LLTextBox* msg_box = new LLTextBox( std::string("Alert message"), msg, (F32)MAX_ALLOWED_MSG_WIDTH, font ); |
314 | 211 | ||
@@ -321,16 +218,19 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o | |||
321 | dialog_height += LINE_HEIGHT; // room for title bar | 218 | dialog_height += LINE_HEIGHT; // room for title bar |
322 | } | 219 | } |
323 | 220 | ||
324 | if (edit_text.size() > 0) | 221 | // it's ok for the edit text body to be empty, but we want the name to exist if we're going to draw it |
222 | if (!edit_text_name.empty()) | ||
325 | { | 223 | { |
326 | dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f)); | 224 | dialog_height += EDITOR_HEIGHT + VPAD; |
327 | dialog_height += EDITOR_HEIGHT; | 225 | dialog_width = llmax(dialog_width, (S32)(font->getWidth( edit_text_contents ) + 0.99f)); |
328 | } | 226 | } |
227 | |||
329 | if (mCaution) | 228 | if (mCaution) |
330 | { | 229 | { |
331 | // Make room for the caution icon. | 230 | // Make room for the caution icon. |
332 | dialog_width += 32 + HPAD; | 231 | dialog_width += 32 + HPAD; |
333 | } | 232 | } |
233 | |||
334 | reshape( dialog_width, dialog_height, FALSE ); | 234 | reshape( dialog_width, dialog_height, FALSE ); |
335 | 235 | ||
336 | S32 msg_y = getRect().getHeight() - VPAD; | 236 | S32 msg_y = getRect().getHeight() - VPAD; |
@@ -352,6 +252,7 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o | |||
352 | { | 252 | { |
353 | msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) ); | 253 | msg_box->setColor( LLUI::sColorsGroup->getColor( "AlertTextColor" ) ); |
354 | } | 254 | } |
255 | |||
355 | LLRect rect; | 256 | LLRect rect; |
356 | rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() ); | 257 | rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() ); |
357 | msg_box->setRect( rect ); | 258 | msg_box->setRect( rect ); |
@@ -360,25 +261,26 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o | |||
360 | // Buttons | 261 | // Buttons |
361 | S32 button_left = (getRect().getWidth() - btn_total_width) / 2; | 262 | S32 button_left = (getRect().getWidth() - btn_total_width) / 2; |
362 | 263 | ||
363 | for( S32 i = 0; i < mNumOptions; i++ ) | 264 | for( S32 i = 0; i < num_options; i++ ) |
364 | { | 265 | { |
365 | LLRect button_rect; | 266 | LLRect button_rect; |
366 | button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ); | 267 | button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ); |
367 | 268 | ||
368 | LLButton* btn = new LLButton(std::string("btn"), button_rect, | 269 | LLButton* btn = new LLButton( |
369 | LLStringUtil::null, LLStringUtil::null, LLStringUtil::null, | 270 | options[i].first, button_rect, |
370 | &LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i]), | 271 | "","", "", |
371 | font, | 272 | NULL, NULL, |
372 | options[i], | 273 | font, |
373 | options[i]); | 274 | options[i].second, |
275 | options[i].second); | ||
374 | 276 | ||
375 | mButtonData[i].mSelf = this; | ||
376 | mButtonData[i].mButton = btn; | 277 | mButtonData[i].mButton = btn; |
377 | mButtonData[i].mOption = i; | 278 | |
279 | btn->setClickedCallback(&LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i])); | ||
378 | 280 | ||
379 | addChild(btn); | 281 | addChild(btn); |
380 | 282 | ||
381 | if( i == default_option ) | 283 | if( i == mDefaultOption ) |
382 | { | 284 | { |
383 | btn->setFocus(TRUE); | 285 | btn->setFocus(TRUE); |
384 | } | 286 | } |
@@ -387,21 +289,83 @@ void LLAlertDialog::createDialog(const options_list_t& options_in, S32 default_o | |||
387 | } | 289 | } |
388 | 290 | ||
389 | // (Optional) Edit Box | 291 | // (Optional) Edit Box |
390 | if (edit_text.size() > 0) | 292 | if (!edit_text_name.empty()) |
391 | { | 293 | { |
392 | S32 y = VPAD + BTN_HEIGHT + VPAD/2; | 294 | S32 y = VPAD + BTN_HEIGHT + VPAD/2; |
393 | mLineEditor = new LLLineEditor(std::string("lineeditor"), | 295 | mLineEditor = new LLLineEditor(edit_text_name, |
394 | LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y), | 296 | LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y), |
395 | edit_text, | 297 | edit_text_contents, |
396 | LLFontGL::sSansSerif, | 298 | LLFontGL::getFontSansSerif(), |
397 | STD_STRING_STR_LEN); | 299 | STD_STRING_STR_LEN); |
300 | |||
301 | // make sure all edit keys get handled properly (DEV-22396) | ||
302 | mLineEditor->setHandleEditKeysDirectly(TRUE); | ||
303 | |||
398 | addChild(mLineEditor); | 304 | addChild(mLineEditor); |
399 | } | 305 | } |
306 | |||
307 | if (mLineEditor) | ||
308 | { | ||
309 | mLineEditor->setDrawAsterixes(is_password); | ||
310 | |||
311 | setEditTextArgs(notification->getSubstitutions()); | ||
312 | } | ||
313 | |||
314 | std::string ignore_label; | ||
315 | |||
316 | if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE) | ||
317 | { | ||
318 | setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label); | ||
319 | } | ||
320 | else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) | ||
321 | { | ||
322 | setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label); | ||
323 | } | ||
324 | } | ||
325 | |||
326 | // All logic for deciding not to show an alert is done here, | ||
327 | // so that the alert is valid until show() is called. | ||
328 | bool LLAlertDialog::show() | ||
329 | { | ||
330 | // If this is a caution message, change the color and add an icon. | ||
331 | if (mCaution) | ||
332 | { | ||
333 | setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertCautionBoxColor" ) ); | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | setBackgroundColor( LLUI::sColorsGroup->getColor( "AlertBoxColor" ) ); | ||
338 | } | ||
339 | |||
340 | startModal(); | ||
341 | gFloaterView->adjustToFitScreen(this, FALSE); | ||
342 | open(); /* Flawfinder: ignore */ | ||
343 | setFocus(TRUE); | ||
344 | if (mLineEditor) | ||
345 | { | ||
346 | mLineEditor->setFocus(TRUE); | ||
347 | mLineEditor->selectAll(); | ||
348 | } | ||
349 | if(mDefaultOption >= 0) | ||
350 | { | ||
351 | // delay before enabling default button | ||
352 | mDefaultBtnTimer.start(); | ||
353 | mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY); | ||
354 | } | ||
355 | |||
356 | // attach to floater if necessary | ||
357 | LLUUID context_key = mNote->getPayload()["context"].asUUID(); | ||
358 | LLFloaterNotificationContext* contextp = dynamic_cast<LLFloaterNotificationContext*>(LLNotificationContext::getInstance(context_key)); | ||
359 | if (contextp && contextp->getFloater()) | ||
360 | { | ||
361 | contextp->getFloater()->addDependentFloater(this, FALSE); | ||
362 | } | ||
363 | return true; | ||
400 | } | 364 | } |
401 | 365 | ||
402 | bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::string& check_control ) | 366 | bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::string& check_control ) |
403 | { | 367 | { |
404 | const LLFontGL* font = LLResMgr::getInstance()->getRes( font_name ); | 368 | const LLFontGL* font = LLResMgr::getInstance()->getRes( FONT_NAME ); |
405 | const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); | 369 | const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); |
406 | 370 | ||
407 | // Extend dialog for "check next time" | 371 | // Extend dialog for "check next time" |
@@ -422,16 +386,9 @@ bool LLAlertDialog::setCheckBox( const std::string& check_title, const std::stri | |||
422 | check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, | 386 | check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, |
423 | max_msg_width, LINE_HEIGHT); | 387 | max_msg_width, LINE_HEIGHT); |
424 | 388 | ||
425 | mCheck = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font); | 389 | mCheck = new LLCheckboxCtrl(std::string("check"), check_rect, check_title, font, onClickIgnore, this); |
426 | addChild(mCheck); | 390 | addChild(mCheck); |
427 | 391 | ||
428 | // mCheck is sometimes "show again" and sometimes "hide" :-( | ||
429 | // If it's "Show Again", and we showed it, it must be checked. JC | ||
430 | if (mIgnorable == IGNORE_SHOW_AGAIN) | ||
431 | { | ||
432 | mCheck->setValue(TRUE); | ||
433 | } | ||
434 | |||
435 | return true; | 392 | return true; |
436 | } | 393 | } |
437 | 394 | ||
@@ -449,65 +406,12 @@ void LLAlertDialog::setVisible( BOOL visible ) | |||
449 | void LLAlertDialog::onClose(bool app_quitting) | 406 | void LLAlertDialog::onClose(bool app_quitting) |
450 | { | 407 | { |
451 | LLModalDialog::onClose(app_quitting); | 408 | LLModalDialog::onClose(app_quitting); |
452 | handleCallbacks(); | ||
453 | } | 409 | } |
454 | 410 | ||
455 | LLAlertDialog::~LLAlertDialog() | 411 | LLAlertDialog::~LLAlertDialog() |
456 | { | 412 | { |
457 | delete[] mButtonData; | ||
458 | if (mUnique) | ||
459 | { | ||
460 | sUniqueActiveMap.erase(mLabel); | ||
461 | } | ||
462 | } | 413 | } |
463 | 414 | ||
464 | void LLAlertDialog::handleCallbacks() | ||
465 | { | ||
466 | if (mOptionChosen >= 0) | ||
467 | { | ||
468 | if (mTextCallback && mLineEditor) | ||
469 | { | ||
470 | mTextCallback(mOptionChosen, mLineEditor->getText(), mUserData); | ||
471 | } | ||
472 | else if (mCallback) | ||
473 | { | ||
474 | mCallback(mOptionChosen, mUserData); | ||
475 | } | ||
476 | |||
477 | // If we declared a URL and chose the URL option, go to the url | ||
478 | if (mOptionChosen == mURLOption) | ||
479 | { | ||
480 | if (!mURL.empty() && sURLLoader != NULL) | ||
481 | { | ||
482 | sURLLoader->load(mURL); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | // Only change warn state if we actually warned. | ||
487 | if (mCheck | ||
488 | && sSettings->getWarning(mIgnoreLabel)) | ||
489 | { | ||
490 | // mCheck sometimes means "hide and do the default" and | ||
491 | // other times means "warn me again". Yuck. JC | ||
492 | BOOL check = mCheck->getValue(); | ||
493 | switch(mIgnorable) | ||
494 | { | ||
495 | case IGNORE_USE_DEFAULT: | ||
496 | sSettings->setWarning(mIgnoreLabel, !check); | ||
497 | break; | ||
498 | case IGNORE_USE_SAVED: | ||
499 | sSettings->setWarning(mIgnoreLabel, !check); | ||
500 | sSettings->setS32("Default" + mIgnoreLabel, mOptionChosen); | ||
501 | break; | ||
502 | case IGNORE_SHOW_AGAIN: | ||
503 | sSettings->setWarning(mIgnoreLabel, check); | ||
504 | break; | ||
505 | default: | ||
506 | break; | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | BOOL LLAlertDialog::hasTitleBar() const | 415 | BOOL LLAlertDialog::hasTitleBar() const |
512 | { | 416 | { |
513 | return (getCurrentTitle() != "" && getCurrentTitle() != " ") // has title | 417 | return (getCurrentTitle() != "" && getCurrentTitle() != " ") // has title |
@@ -567,33 +471,11 @@ void LLAlertDialog::draw() | |||
567 | LLModalDialog::draw(); | 471 | LLModalDialog::draw(); |
568 | } | 472 | } |
569 | 473 | ||
570 | void LLAlertDialog::setOptionEnabled( S32 option, BOOL enable ) | 474 | void LLAlertDialog::setEditTextArgs(const LLSD& edit_args) |
571 | { | ||
572 | if( (option >= 0) && (option < mNumOptions) ) | ||
573 | { | ||
574 | mButtonData[option].mButton->setEnabled( enable ); | ||
575 | } | ||
576 | } | ||
577 | |||
578 | void LLAlertDialog::setEditTextCallback(alert_text_callback_t callback, void *user_data) | ||
579 | { | ||
580 | if (mLineEditor) | ||
581 | { | ||
582 | mTextCallback = callback; | ||
583 | mUserData = user_data; | ||
584 | } | ||
585 | else | ||
586 | { | ||
587 | llwarns << "LLAlertDialog::setEditTextCallback called on dialog with no line editor" << llendl; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | void LLAlertDialog::setEditTextArgs(const LLStringUtil::format_map_t& edit_args) | ||
592 | { | 475 | { |
593 | if (mLineEditor) | 476 | if (mLineEditor) |
594 | { | 477 | { |
595 | std::string msg = mLineEditor->getText(); | 478 | std::string msg = mLineEditor->getText(); |
596 | format(msg, edit_args); | ||
597 | mLineEditor->setText(msg); | 479 | mLineEditor->setText(msg); |
598 | } | 480 | } |
599 | else | 481 | else |
@@ -602,268 +484,44 @@ void LLAlertDialog::setEditTextArgs(const LLStringUtil::format_map_t& edit_args) | |||
602 | } | 484 | } |
603 | } | 485 | } |
604 | 486 | ||
605 | void LLAlertDialog::setDrawAsterixes(BOOL enable) | ||
606 | { | ||
607 | if (mLineEditor) | ||
608 | { | ||
609 | if (enable) | ||
610 | { | ||
611 | mLineEditor->clear(); | ||
612 | } | ||
613 | mLineEditor->setDrawAsterixes(enable); | ||
614 | } | ||
615 | } | ||
616 | |||
617 | // static | 487 | // static |
618 | void LLAlertDialog::onButtonPressed( void* userdata ) | 488 | void LLAlertDialog::onButtonPressed( void* userdata ) |
619 | { | 489 | { |
620 | ButtonData* button_data = (ButtonData*)userdata; | 490 | ButtonData* button_data = (ButtonData*)userdata; |
621 | LLAlertDialog* self = button_data->mSelf; | 491 | LLAlertDialog* self = button_data->mSelf; |
622 | 492 | ||
623 | self->mOptionChosen = button_data->mOption; | 493 | LLSD response = self->mNote->getResponseTemplate(); |
624 | self->close(); // deletes self | 494 | if (self->mLineEditor) |
625 | } | ||
626 | |||
627 | //============================================================================= | ||
628 | |||
629 | //static | ||
630 | const std::string& LLAlertDialog::getTemplateMessage(const std::string& xml_desc) | ||
631 | { | ||
632 | template_map_t::iterator iter = sAlertTemplates.find(xml_desc); | ||
633 | if (iter != sAlertTemplates.end()) | ||
634 | { | 495 | { |
635 | return iter->second->mMessage; | 496 | response[self->mLineEditor->getName()] = self->mLineEditor->getValue(); |
636 | } | 497 | } |
637 | else | 498 | response[button_data->mButton->getName()] = true; |
499 | |||
500 | // If we declared a URL and chose the URL option, go to the url | ||
501 | if (!button_data->mURL.empty() && sURLLoader != NULL) | ||
638 | { | 502 | { |
639 | return xml_desc; | 503 | sURLLoader->load(button_data->mURL); |
640 | } | 504 | } |
505 | |||
506 | self->mNote->respond(response); // new notification reponse | ||
507 | self->close(); // deletes self | ||
641 | } | 508 | } |
642 | 509 | ||
643 | //static | 510 | //static |
644 | bool LLAlertDialog::parseAlerts(const std::string& xml_filename, LLControlGroup* settings, BOOL settings_only) | 511 | void LLAlertDialog::onClickIgnore(LLUICtrl* ctrl, void* user_data) |
645 | { | 512 | { |
646 | LLXMLNodePtr root; | 513 | LLAlertDialog* self = (LLAlertDialog*)user_data; |
647 | BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); | ||
648 | 514 | ||
649 | if (!success || root.isNull() || !root->hasName( "alerts" )) | 515 | // checkbox sometimes means "hide and do the default" and |
516 | // other times means "warn me again". Yuck. JC | ||
517 | BOOL check = ctrl->getValue(); | ||
518 | if (self->mNote->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) | ||
650 | { | 519 | { |
651 | llerrs << "Problem reading UI Alerts file: " << xml_filename << llendl; | 520 | // question was "show again" so invert value to get "ignore" |
652 | return false; | 521 | check = !check; |
653 | } | 522 | } |
654 | 523 | ||
655 | BOOL add_settings = FALSE; | 524 | self->mNote->setIgnored(check); |
656 | if (settings) | 525 | } |
657 | { | ||
658 | sSettings = settings; | ||
659 | add_settings = TRUE; | ||
660 | } | ||
661 | llassert(sSettings); | ||
662 | |||
663 | for (LLXMLNode* alert = root->getFirstChild(); | ||
664 | alert != NULL; alert = alert->getNextSibling()) | ||
665 | { | ||
666 | if (alert->hasName("global")) | ||
667 | { | ||
668 | std::string global_name; | ||
669 | if (alert->getAttributeString("name", global_name)) | ||
670 | { | ||
671 | if (global_name == "skipnexttime") | ||
672 | { | ||
673 | sStringSkipNextTime = alert->getTextContents(); | ||
674 | } | ||
675 | else if (global_name == "alwayschoose") | ||
676 | { | ||
677 | sStringAlwaysChoose = alert->getTextContents(); | ||
678 | } | ||
679 | } | ||
680 | continue; | ||
681 | } | ||
682 | |||
683 | if (!alert->hasName("alert")) | ||
684 | { | ||
685 | continue; | ||
686 | } | ||
687 | |||
688 | LLAlertDialogTemplate* xml_template = settings_only ? NULL : new LLAlertDialogTemplate; | ||
689 | |||
690 | // name= | ||
691 | std::string alert_name; | ||
692 | if (alert->getAttributeString("name", alert_name)) | ||
693 | { | ||
694 | if (xml_template) | ||
695 | { | ||
696 | xml_template->mLabel = alert_name; | ||
697 | } | ||
698 | } | ||
699 | else | ||
700 | { | ||
701 | llwarns << "Unable to parse alert with no name" << llendl; | ||
702 | delete xml_template; | ||
703 | continue; | ||
704 | } | ||
705 | // title= | ||
706 | std::string title; | ||
707 | if (alert->getAttributeString("title", title)) | ||
708 | { | ||
709 | if (xml_template) | ||
710 | { | ||
711 | xml_template->mTitle = title; | ||
712 | } | ||
713 | } | ||
714 | // modal= | ||
715 | BOOL modal; | ||
716 | if (alert->getAttributeBOOL("modal", modal)) | ||
717 | { | ||
718 | if (xml_template) | ||
719 | { | ||
720 | xml_template->mModal = modal; | ||
721 | } | ||
722 | } | ||
723 | // caution= | ||
724 | BOOL caution; | ||
725 | if (alert->getAttributeBOOL("caution", caution)) | ||
726 | { | ||
727 | if (xml_template) | ||
728 | { | ||
729 | xml_template->mCaution = caution; | ||
730 | } | ||
731 | } | ||
732 | // unique= | ||
733 | BOOL unique; | ||
734 | if (alert->getAttributeBOOL("unique", unique)) | ||
735 | { | ||
736 | if (xml_template) | ||
737 | { | ||
738 | xml_template->mUnique = unique; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | S32 default_option = 0; | ||
743 | BOOL nodefault; | ||
744 | if (alert->getAttributeBOOL("nodefault", nodefault)) | ||
745 | { | ||
746 | if (nodefault) | ||
747 | { | ||
748 | if (xml_template) | ||
749 | { | ||
750 | xml_template->mDefaultOption = -1; | ||
751 | } | ||
752 | default_option = -1; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | S32 btn_idx = 0; | ||
757 | for (LLXMLNode* child = alert->getFirstChild(); | ||
758 | child != NULL; child = child->getNextSibling()) | ||
759 | { | ||
760 | // <message> | ||
761 | if (child->hasName("message")) | ||
762 | { | ||
763 | if (xml_template) | ||
764 | { | ||
765 | xml_template->mMessage = child->getTextContents(); | ||
766 | } | ||
767 | } | ||
768 | 526 | ||
769 | // <option> | ||
770 | if (child->hasName("option")) | ||
771 | { | ||
772 | std::string label = child->getTextContents(); | ||
773 | BOOL is_default = FALSE; | ||
774 | child->getAttributeBOOL("default", is_default); | ||
775 | std::string ignore_text; | ||
776 | if (!child->getAttributeString("ignore", ignore_text)) | ||
777 | { | ||
778 | ignore_text = label; | ||
779 | } | ||
780 | if (xml_template) | ||
781 | { | ||
782 | xml_template->addOption(label, ignore_text, is_default); | ||
783 | } | ||
784 | if (is_default) | ||
785 | { | ||
786 | default_option = btn_idx; | ||
787 | } | ||
788 | btn_idx++; | ||
789 | } | ||
790 | |||
791 | // <editline> | ||
792 | if (child->hasName("editline")) | ||
793 | { | ||
794 | if (xml_template) | ||
795 | { | ||
796 | xml_template->mEditLineText = child->getTextContents(); | ||
797 | if (xml_template->mEditLineText.empty()) | ||
798 | { | ||
799 | xml_template->mEditLineText = " "; | ||
800 | } | ||
801 | } | ||
802 | } | ||
803 | |||
804 | // <ignore> | ||
805 | if (child->hasName("ignore")) | ||
806 | { | ||
807 | std::string ignore_text = child->getTextContents(); | ||
808 | // label= | ||
809 | std::string name; | ||
810 | child->getAttributeString("name", name); | ||
811 | |||
812 | //always set to alert_name for the sake of i18n | ||
813 | //if (name.empty()) | ||
814 | name = alert_name; | ||
815 | |||
816 | if (xml_template) | ||
817 | { | ||
818 | xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_DEFAULT; | ||
819 | xml_template->mIgnoreListText = ignore_text; | ||
820 | xml_template->mIgnoreLabel = name; | ||
821 | } | ||
822 | if (!ignore_text.empty()) | ||
823 | { | ||
824 | if (add_settings) | ||
825 | { | ||
826 | settings->addWarning(name); | ||
827 | } | ||
828 | if (xml_template) | ||
829 | { | ||
830 | sIgnorableTemplates[name] = xml_template; // will override any previous entry | ||
831 | } | ||
832 | } | ||
833 | // save_option= | ||
834 | BOOL save_option = FALSE; | ||
835 | child->getAttributeBOOL("save_option", save_option); | ||
836 | if (save_option) | ||
837 | { | ||
838 | if (xml_template) | ||
839 | { | ||
840 | xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_SAVED; | ||
841 | } | ||
842 | if (add_settings) | ||
843 | { | ||
844 | settings->declareS32(std::string("Default") + name, default_option, std::string("Default option number for this alert dialog")); | ||
845 | } | ||
846 | } | ||
847 | } | ||
848 | 527 | ||
849 | // <url> | ||
850 | if (child->hasName("url")) | ||
851 | { | ||
852 | S32 url_option = 0; | ||
853 | child->getAttributeS32("option", url_option); | ||
854 | if (xml_template) | ||
855 | { | ||
856 | xml_template->mURL = child->getTextContents(); | ||
857 | xml_template->mURLOption = url_option; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | } | ||
862 | if (xml_template) | ||
863 | { | ||
864 | xml_template->mDefaultOption = default_option; | ||
865 | sAlertTemplates[xml_template->mLabel] = xml_template; | ||
866 | } | ||
867 | } | ||
868 | return true; | ||
869 | } | ||
diff --git a/linden/indra/llui/llalertdialog.h b/linden/indra/llui/llalertdialog.h index 7d82fb5..04caea6 100644 --- a/linden/indra/llui/llalertdialog.h +++ b/linden/indra/llui/llalertdialog.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -36,6 +37,7 @@ | |||
36 | #include "llmodaldialog.h" | 37 | #include "llmodaldialog.h" |
37 | #include "llmemory.h" | 38 | #include "llmemory.h" |
38 | #include "llui.h" | 39 | #include "llui.h" |
40 | #include "llnotifications.h" | ||
39 | 41 | ||
40 | class LLButton; | 42 | class LLButton; |
41 | class LLCheckBoxCtrl; | 43 | class LLCheckBoxCtrl; |
@@ -43,21 +45,20 @@ class LLAlertDialogTemplate; | |||
43 | class LLLineEditor; | 45 | class LLLineEditor; |
44 | 46 | ||
45 | // https://wiki.lindenlab.com/mediawiki/index.php?title=LLAlertDialog&oldid=81388 | 47 | // https://wiki.lindenlab.com/mediawiki/index.php?title=LLAlertDialog&oldid=81388 |
46 | class LLAlertDialog : public LLModalDialog | 48 | class LLAlertDialog |
49 | : public LLModalDialog, | ||
50 | public LLInitClass<LLAlertDialog>, | ||
51 | public LLInstanceTracker<LLAlertDialog, LLUUID> | ||
52 | |||
47 | { | 53 | { |
48 | public: | 54 | public: |
49 | typedef void (*alert_callback_t)(S32 option, void* user_data); | ||
50 | typedef void (*alert_text_callback_t)(S32 option, const std::string& text, void* user_data); | ||
51 | typedef bool (*display_callback_t)(S32 modal); | 55 | typedef bool (*display_callback_t)(S32 modal); |
52 | typedef std::vector<std::string> options_list_t; | ||
53 | |||
54 | enum { IGNORE_USE_DEFAULT=1, IGNORE_USE_SAVED=2, IGNORE_SHOW_AGAIN=3 }; | ||
55 | 56 | ||
56 | class URLLoader | 57 | class URLLoader |
57 | { | 58 | { |
58 | public: | 59 | public: |
59 | virtual void load(const std::string& url) = 0; | 60 | virtual void load(const std::string& url) = 0; |
60 | virtual ~URLLoader() {} | 61 | virtual ~URLLoader() {} |
61 | }; | 62 | }; |
62 | 63 | ||
63 | static void setURLLoader(URLLoader* loader) | 64 | static void setURLLoader(URLLoader* loader) |
@@ -67,8 +68,7 @@ public: | |||
67 | 68 | ||
68 | public: | 69 | public: |
69 | // User's responsibility to call show() after creating these. | 70 | // User's responsibility to call show() after creating these. |
70 | LLAlertDialog( const LLAlertDialogTemplate* xml_template, const LLStringUtil::format_map_t& args, | 71 | LLAlertDialog( LLNotificationPtr notep, bool is_modal ); |
71 | alert_callback_t callback = NULL, void *user_data = NULL); | ||
72 | 72 | ||
73 | virtual BOOL handleKeyHere(KEY key, MASK mask ); | 73 | virtual BOOL handleKeyHere(KEY key, MASK mask ); |
74 | 74 | ||
@@ -77,150 +77,52 @@ public: | |||
77 | virtual void onClose(bool app_quitting); | 77 | virtual void onClose(bool app_quitting); |
78 | 78 | ||
79 | bool setCheckBox( const std::string&, const std::string& ); | 79 | bool setCheckBox( const std::string&, const std::string& ); |
80 | void setOptionEnabled( S32 option, BOOL enable ); | ||
81 | void setCaution(BOOL val = TRUE) { mCaution = val; } | 80 | void setCaution(BOOL val = TRUE) { mCaution = val; } |
82 | // If mUnique==TRUE only one copy of this message should exist | 81 | // If mUnique==TRUE only one copy of this message should exist |
83 | void setUnique(BOOL val = TRUE) { mUnique = val; } | 82 | void setUnique(BOOL val = TRUE) { mUnique = val; } |
84 | void setEditTextCallback(alert_text_callback_t callback, void *user_data); | 83 | void setEditTextArgs(const LLSD& edit_args); |
85 | void setEditTextArgs(const LLStringUtil::format_map_t& edit_args); | ||
86 | void setDrawAsterixes(BOOL enable); | ||
87 | 84 | ||
88 | bool show(); // May instantly destroy the message if it is unique (returns false) | 85 | bool show(); // May instantly destroy the message if it is unique (returns false) |
89 | 86 | ||
90 | //statics | 87 | //statics |
91 | static void onButtonPressed(void* userdata); | 88 | static void initClass(); |
92 | 89 | static bool onNewNotification(const LLSD& notify, bool is_modal); | |
93 | static LLAlertDialog* createXml( const std::string& xml_desc, | 90 | static void onButtonPressed(void* userdata); |
94 | alert_callback_t callback = NULL, void *user_data = NULL); | 91 | static void onClickIgnore(LLUICtrl* ctrl, void* user_data); |
95 | static LLAlertDialog* createXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, | ||
96 | alert_callback_t callback = NULL, void *user_data = NULL); | ||
97 | |||
98 | static LLAlertDialog* showXml( const std::string& xml_desc, | ||
99 | alert_callback_t callback = NULL, void *user_data = NULL); | ||
100 | static LLAlertDialog* showXml( const std::string& xml_desc, const LLStringUtil::format_map_t& args, | ||
101 | alert_callback_t callback = NULL, void *user_data = NULL); | ||
102 | |||
103 | static LLAlertDialog* showCritical( const std::string& msg, alert_callback_t callback = NULL, void *user_data = NULL); | ||
104 | |||
105 | static bool parseAlerts(const std::string& xml_filename, LLControlGroup* settings = NULL, BOOL settings_only = FALSE); | ||
106 | static const std::string& getTemplateMessage(const std::string& xml_desc); | ||
107 | |||
108 | static void setDisplayCallback(display_callback_t callback) { sDisplayCallback = callback; } | ||
109 | |||
110 | private: | ||
111 | void format(std::string& msg, const LLStringUtil::format_map_t& args); | ||
112 | |||
113 | public: | ||
114 | static LLControlGroup* sSettings; | ||
115 | |||
116 | // use LLPointer so they delete themselves when sTemplates is destroyed | ||
117 | typedef std::map<std::string, LLPointer<LLAlertDialogTemplate> > template_map_t; | ||
118 | static template_map_t sAlertTemplates; // by mLabel | ||
119 | static template_map_t sIgnorableTemplates; // by mIgnoreLabel | ||
120 | 92 | ||
121 | private: | 93 | private: |
94 | LLNotificationPtr mNote; | ||
122 | 95 | ||
123 | static std::map<std::string, LLAlertDialog*> sUniqueActiveMap; | 96 | static std::map<std::string, LLAlertDialog*> sUniqueActiveMap; |
124 | static display_callback_t sDisplayCallback; | ||
125 | 97 | ||
126 | static std::string sStringSkipNextTime; | ||
127 | static std::string sStringAlwaysChoose; | ||
128 | |||
129 | void createDialog(const options_list_t& options_in, S32 default_option, | ||
130 | const std::string& msg, const LLStringUtil::format_map_t& args, | ||
131 | const std::string& edit_text); | ||
132 | |||
133 | virtual ~LLAlertDialog(); | 98 | virtual ~LLAlertDialog(); |
134 | void handleCallbacks(); | ||
135 | // No you can't kill it. It can only kill itself. | 99 | // No you can't kill it. It can only kill itself. |
136 | 100 | ||
137 | // Does it have a readable title label, or minimize or close buttons? | 101 | // Does it have a readable title label, or minimize or close buttons? |
138 | BOOL hasTitleBar() const; | 102 | BOOL hasTitleBar() const; |
139 | 103 | ||
104 | private: | ||
105 | static URLLoader* sURLLoader; | ||
106 | static LLControlGroup* sSettings; | ||
107 | |||
140 | struct ButtonData | 108 | struct ButtonData |
141 | { | 109 | { |
142 | LLAlertDialog* mSelf; | 110 | LLAlertDialog* mSelf; |
143 | LLButton* mButton; | 111 | LLButton* mButton; |
144 | S32 mOption; | 112 | std::string mURL; |
145 | } * mButtonData; | 113 | }; |
146 | 114 | std::vector<ButtonData> mButtonData; | |
147 | alert_callback_t mCallback; | 115 | |
148 | void* mUserData; | 116 | S32 mDefaultOption; |
149 | S32 mNumOptions; | ||
150 | S32 mDefaultOption; | ||
151 | BOOL mOptionChosen; | ||
152 | LLCheckBoxCtrl* mCheck; | 117 | LLCheckBoxCtrl* mCheck; |
153 | BOOL mCaution; | 118 | BOOL mCaution; |
154 | BOOL mUnique; | 119 | BOOL mUnique; |
155 | S32 mIgnorable; | 120 | std::string mLabel; |
156 | std::string mLabel; | 121 | LLFrameTimer mDefaultBtnTimer; |
157 | std::string mIgnoreLabel; | ||
158 | LLFrameTimer mDefaultBtnTimer; | ||
159 | // For Dialogs that take a line as text as input: | 122 | // For Dialogs that take a line as text as input: |
160 | LLLineEditor* mLineEditor; | 123 | LLLineEditor* mLineEditor; |
161 | alert_text_callback_t mTextCallback; | ||
162 | // For Dialogs linked to a URL | ||
163 | std::string mURL; // Some alerts will direct the resident to a URL | ||
164 | S32 mURLOption; | ||
165 | 124 | ||
166 | private: | ||
167 | static URLLoader* sURLLoader; | ||
168 | }; | 125 | }; |
169 | 126 | ||
170 | //============================================================================ | ||
171 | |||
172 | class LLAlertDialogTemplate : public LLRefCount | ||
173 | { | ||
174 | public: | ||
175 | LLAlertDialogTemplate() : mTitle(), mURLOption(0), mModal(FALSE), mCaution(FALSE), mUnique(FALSE), mIgnorable(0), mDefaultOption(0) {} | ||
176 | |||
177 | void addOption(const std::string& label, const std::string& ignore_text, BOOL is_default = FALSE) | ||
178 | { | ||
179 | if (is_default) | ||
180 | { | ||
181 | mDefaultOption = mOptions.size(); | ||
182 | } | ||
183 | mOptions.push_back(label); | ||
184 | mOptionDefaultText.push_back(ignore_text); | ||
185 | } | ||
186 | |||
187 | S32 getIgnore() | ||
188 | { | ||
189 | if (mIgnorable) | ||
190 | { | ||
191 | return LLAlertDialog::sSettings->getWarning(mIgnoreLabel) ? FALSE : mIgnorable; | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | return FALSE; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | void setIgnore(bool state) | ||
200 | { | ||
201 | if (mIgnorable) | ||
202 | { | ||
203 | LLAlertDialog::sSettings->setWarning(mIgnoreLabel, !state); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | |||
208 | public: | ||
209 | std::string mLabel; // Handle for access from code, etc | ||
210 | std::string mTitle; // (optional) text to display in title bar | ||
211 | std::string mMessage; // Message to display | ||
212 | std::string mIgnoreListText; // Text to display in enable/disable dialog (if mIgnorable == TRUE) | ||
213 | std::string mIgnoreLabel; // Handle for ignore variable (may be shared by multiple templates) | ||
214 | std::string mURL; // Some alerts will direct the resident to a URL | ||
215 | S32 mURLOption; | ||
216 | BOOL mModal; | ||
217 | BOOL mCaution; | ||
218 | BOOL mUnique; | ||
219 | S32 mIgnorable; // 0 = Never Ignore, 1 = Do default option, 2 = Do saved option | ||
220 | LLAlertDialog::options_list_t mOptions; | ||
221 | LLAlertDialog::options_list_t mOptionDefaultText; | ||
222 | S32 mDefaultOption; | ||
223 | std::string mEditLineText; | ||
224 | }; | ||
225 | 127 | ||
226 | #endif // LL_ALERTDIALOG_H | 128 | #endif // LL_ALERTDIALOG_H |
diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp index 34e62c8..2c2c1c2 100644 --- a/linden/indra/llui/llbutton.cpp +++ b/linden/indra/llui/llbutton.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -187,7 +188,7 @@ LLButton::LLButton(const std::string& name, const LLRect& rect, | |||
187 | 188 | ||
188 | void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name) | 189 | void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name) |
189 | { | 190 | { |
190 | mGLFont = ( font ? font : LLFontGL::sSansSerif); | 191 | mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); |
191 | 192 | ||
192 | // Hack to make sure there is space for at least one character | 193 | // Hack to make sure there is space for at least one character |
193 | if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) | 194 | if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) |
@@ -422,13 +423,7 @@ void LLButton::draw() | |||
422 | // Unselected image assignments | 423 | // Unselected image assignments |
423 | S32 local_mouse_x; | 424 | S32 local_mouse_x; |
424 | S32 local_mouse_y; | 425 | S32 local_mouse_y; |
425 | LLCoordWindow cursor_pos_window; | 426 | LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); |
426 | getWindow()->getCursorPosition(&cursor_pos_window); | ||
427 | LLCoordGL cursor_pos_gl; | ||
428 | getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); | ||
429 | cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]); | ||
430 | cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); | ||
431 | screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); | ||
432 | 427 | ||
433 | BOOL pressed = pressed_by_keyboard | 428 | BOOL pressed = pressed_by_keyboard |
434 | || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) | 429 | || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) |
diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h index 556e12c..724b775 100644 --- a/linden/indra/llui/llbutton.h +++ b/linden/indra/llui/llbutton.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -163,7 +164,7 @@ public: | |||
163 | void setDisabledLabelColor( const LLColor4& c ) { mDisabledLabelColor = c; } | 164 | void setDisabledLabelColor( const LLColor4& c ) { mDisabledLabelColor = c; } |
164 | 165 | ||
165 | void setFont(const LLFontGL *font) | 166 | void setFont(const LLFontGL *font) |
166 | { mGLFont = ( font ? font : LLFontGL::sSansSerif); } | 167 | { mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); } |
167 | void setScaleImage(BOOL scale) { mScaleImage = scale; } | 168 | void setScaleImage(BOOL scale) { mScaleImage = scale; } |
168 | BOOL getScaleImage() const { return mScaleImage; } | 169 | BOOL getScaleImage() const { return mScaleImage; } |
169 | 170 | ||
diff --git a/linden/indra/llui/llcallbackmap.h b/linden/indra/llui/llcallbackmap.h index db11c39..eadb9c9 100644 --- a/linden/indra/llui/llcallbackmap.h +++ b/linden/indra/llui/llcallbackmap.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llcheckboxctrl.cpp b/linden/indra/llui/llcheckboxctrl.cpp index d4c372a..eda9467 100644 --- a/linden/indra/llui/llcheckboxctrl.cpp +++ b/linden/indra/llui/llcheckboxctrl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -72,7 +73,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, | |||
72 | } | 73 | } |
73 | else | 74 | else |
74 | { | 75 | { |
75 | mFont = LLFontGL::sSansSerifSmall; | 76 | mFont = LLFontGL::getFontSansSerifSmall(); |
76 | } | 77 | } |
77 | 78 | ||
78 | // must be big enough to hold all children | 79 | // must be big enough to hold all children |
@@ -122,7 +123,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, | |||
122 | inactive_false_id = "UIImgRadioInactiveUUID"; | 123 | inactive_false_id = "UIImgRadioInactiveUUID"; |
123 | mButton = new LLButton(std::string("Radio control button"), btn_rect, | 124 | mButton = new LLButton(std::string("Radio control button"), btn_rect, |
124 | active_false_id, active_true_id, control_which, | 125 | active_false_id, active_true_id, control_which, |
125 | &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::sSansSerif ); | 126 | &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); |
126 | mButton->setDisabledImages( inactive_false_id, inactive_true_id ); | 127 | mButton->setDisabledImages( inactive_false_id, inactive_true_id ); |
127 | mButton->setHoverGlowStrength(0.35f); | 128 | mButton->setHoverGlowStrength(0.35f); |
128 | } | 129 | } |
@@ -134,7 +135,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, | |||
134 | inactive_false_id = "UIImgCheckboxInactiveUUID"; | 135 | inactive_false_id = "UIImgCheckboxInactiveUUID"; |
135 | mButton = new LLButton(std::string("Checkbox control button"), btn_rect, | 136 | mButton = new LLButton(std::string("Checkbox control button"), btn_rect, |
136 | active_false_id, active_true_id, control_which, | 137 | active_false_id, active_true_id, control_which, |
137 | &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::sSansSerif ); | 138 | &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); |
138 | mButton->setDisabledImages( inactive_false_id, inactive_true_id ); | 139 | mButton->setDisabledImages( inactive_false_id, inactive_true_id ); |
139 | mButton->setHoverGlowStrength(0.35f); | 140 | mButton->setHoverGlowStrength(0.35f); |
140 | } | 141 | } |
diff --git a/linden/indra/llui/llcheckboxctrl.h b/linden/indra/llui/llcheckboxctrl.h index 8a70c62..ff867f5 100644 --- a/linden/indra/llui/llcheckboxctrl.h +++ b/linden/indra/llui/llcheckboxctrl.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llclipboard.cpp b/linden/indra/llui/llclipboard.cpp index d5255e7..8a7a214 100644 --- a/linden/indra/llui/llclipboard.cpp +++ b/linden/indra/llui/llclipboard.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llclipboard.h b/linden/indra/llui/llclipboard.h index 706ed2a..37ed1ff 100644 --- a/linden/indra/llui/llclipboard.h +++ b/linden/indra/llui/llclipboard.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llcombobox.cpp b/linden/indra/llui/llcombobox.cpp index 3aec2ee..28a05c1 100644 --- a/linden/indra/llui/llcombobox.cpp +++ b/linden/indra/llui/llcombobox.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -72,11 +73,12 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std:: | |||
72 | mTextEntryTentative(TRUE), | 73 | mTextEntryTentative(TRUE), |
73 | mListPosition(BELOW), | 74 | mListPosition(BELOW), |
74 | mPrearrangeCallback( NULL ), | 75 | mPrearrangeCallback( NULL ), |
75 | mTextEntryCallback( NULL ) | 76 | mTextEntryCallback( NULL ), |
77 | mLabel(label) | ||
76 | { | 78 | { |
77 | // Always use text box | 79 | // Always use text box |
78 | // Text label button | 80 | // Text label button |
79 | mButton = new LLButton(label, | 81 | mButton = new LLButton(mLabel, |
80 | LLRect(), | 82 | LLRect(), |
81 | LLStringUtil::null, | 83 | LLStringUtil::null, |
82 | NULL, this); | 84 | NULL, this); |
@@ -87,7 +89,7 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std:: | |||
87 | mButton->setScaleImage(TRUE); | 89 | mButton->setScaleImage(TRUE); |
88 | 90 | ||
89 | mButton->setMouseDownCallback(onButtonDown); | 91 | mButton->setMouseDownCallback(onButtonDown); |
90 | mButton->setFont(LLFontGL::sSansSerifSmall); | 92 | mButton->setFont(LLFontGL::getFontSansSerifSmall()); |
91 | mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); | 93 | mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); |
92 | mButton->setHAlign( LLFontGL::LEFT ); | 94 | mButton->setHAlign( LLFontGL::LEFT ); |
93 | mButton->setRightHPad(2); | 95 | mButton->setRightHPad(2); |
@@ -197,7 +199,12 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * | |||
197 | } | 199 | } |
198 | } | 200 | } |
199 | 201 | ||
200 | combo_box->selectFirstItem(); | 202 | // if providing user text entry or descriptive label |
203 | // don't select an item under the hood | ||
204 | if (!combo_box->acceptsTextInput() && combo_box->mLabel.empty()) | ||
205 | { | ||
206 | combo_box->selectFirstItem(); | ||
207 | } | ||
201 | 208 | ||
202 | return combo_box; | 209 | return combo_box; |
203 | } | 210 | } |
@@ -259,7 +266,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, BOO | |||
259 | { | 266 | { |
260 | LLScrollListItem* item = mList->addSimpleElement(name, pos); | 267 | LLScrollListItem* item = mList->addSimpleElement(name, pos); |
261 | item->setEnabled(enabled); | 268 | item->setEnabled(enabled); |
262 | mList->selectFirstItem(); | 269 | if (!mAllowTextEntry && mLabel.empty()) |
270 | { | ||
271 | selectFirstItem(); | ||
272 | } | ||
263 | return item; | 273 | return item; |
264 | } | 274 | } |
265 | 275 | ||
@@ -268,7 +278,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAd | |||
268 | { | 278 | { |
269 | LLScrollListItem* item = mList->addSimpleElement(name, pos, id); | 279 | LLScrollListItem* item = mList->addSimpleElement(name, pos, id); |
270 | item->setEnabled(enabled); | 280 | item->setEnabled(enabled); |
271 | mList->selectFirstItem(); | 281 | if (!mAllowTextEntry && mLabel.empty()) |
282 | { | ||
283 | selectFirstItem(); | ||
284 | } | ||
272 | return item; | 285 | return item; |
273 | } | 286 | } |
274 | 287 | ||
@@ -278,7 +291,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddP | |||
278 | LLScrollListItem* item = mList->addSimpleElement(name, pos); | 291 | LLScrollListItem* item = mList->addSimpleElement(name, pos); |
279 | item->setEnabled(enabled); | 292 | item->setEnabled(enabled); |
280 | item->setUserdata( userdata ); | 293 | item->setUserdata( userdata ); |
281 | mList->selectFirstItem(); | 294 | if (!mAllowTextEntry && mLabel.empty()) |
295 | { | ||
296 | selectFirstItem(); | ||
297 | } | ||
282 | return item; | 298 | return item; |
283 | } | 299 | } |
284 | 300 | ||
@@ -287,7 +303,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosit | |||
287 | { | 303 | { |
288 | LLScrollListItem* item = mList->addSimpleElement(name, pos, value); | 304 | LLScrollListItem* item = mList->addSimpleElement(name, pos, value); |
289 | item->setEnabled(enabled); | 305 | item->setEnabled(enabled); |
290 | mList->selectFirstItem(); | 306 | if (!mAllowTextEntry && mLabel.empty()) |
307 | { | ||
308 | selectFirstItem(); | ||
309 | } | ||
291 | return item; | 310 | return item; |
292 | } | 311 | } |
293 | 312 | ||
@@ -498,7 +517,7 @@ void LLComboBox::updateLayout() | |||
498 | mTextEntry = new LLLineEditor(std::string("combo_text_entry"), | 517 | mTextEntry = new LLLineEditor(std::string("combo_text_entry"), |
499 | text_entry_rect, | 518 | text_entry_rect, |
500 | LLStringUtil::null, | 519 | LLStringUtil::null, |
501 | LLFontGL::sSansSerifSmall, | 520 | LLFontGL::getFontSansSerifSmall(), |
502 | mMaxChars, | 521 | mMaxChars, |
503 | onTextCommit, | 522 | onTextCommit, |
504 | onTextEntry, | 523 | onTextEntry, |
diff --git a/linden/indra/llui/llcombobox.h b/linden/indra/llui/llcombobox.h index efcb798..33e1baa 100644 --- a/linden/indra/llui/llcombobox.h +++ b/linden/indra/llui/llcombobox.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -188,6 +189,7 @@ protected: | |||
188 | LLScrollListCtrl* mList; | 189 | LLScrollListCtrl* mList; |
189 | EPreferredPosition mListPosition; | 190 | EPreferredPosition mListPosition; |
190 | LLPointer<LLUIImage> mArrowImage; | 191 | LLPointer<LLUIImage> mArrowImage; |
192 | std::string mLabel; | ||
191 | 193 | ||
192 | private: | 194 | private: |
193 | S32 mButtonPadding; | 195 | S32 mButtonPadding; |
diff --git a/linden/indra/llui/llctrlselectioninterface.cpp b/linden/indra/llui/llctrlselectioninterface.cpp index 282f43c..dac0939 100644 --- a/linden/indra/llui/llctrlselectioninterface.cpp +++ b/linden/indra/llui/llctrlselectioninterface.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llctrlselectioninterface.h b/linden/indra/llui/llctrlselectioninterface.h index 6f5f5c8..45727d6 100644 --- a/linden/indra/llui/llctrlselectioninterface.h +++ b/linden/indra/llui/llctrlselectioninterface.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lldraghandle.cpp b/linden/indra/llui/lldraghandle.cpp index c76bdfb..6c92ea1 100644 --- a/linden/indra/llui/lldraghandle.cpp +++ b/linden/indra/llui/lldraghandle.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lldraghandle.h b/linden/indra/llui/lldraghandle.h index 35408da..9eb3e55 100644 --- a/linden/indra/llui/lldraghandle.h +++ b/linden/indra/llui/lldraghandle.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lleditmenuhandler.cpp b/linden/indra/llui/lleditmenuhandler.cpp index d6f04f2..821afae 100644 --- a/linden/indra/llui/lleditmenuhandler.cpp +++ b/linden/indra/llui/lleditmenuhandler.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lleditmenuhandler.h b/linden/indra/llui/lleditmenuhandler.h index c0c6d7b..1de9c56 100644 --- a/linden/indra/llui/lleditmenuhandler.h +++ b/linden/indra/llui/lleditmenuhandler.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llfloater.cpp b/linden/indra/llui/llfloater.cpp index 2924c29..94af186 100644 --- a/linden/indra/llui/llfloater.cpp +++ b/linden/indra/llui/llfloater.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -147,6 +148,7 @@ LLFloater::LLFloater() : | |||
147 | } | 148 | } |
148 | mDragHandle = NULL; | 149 | mDragHandle = NULL; |
149 | mHandle.bind(this); | 150 | mHandle.bind(this); |
151 | mNotificationContext = new LLFloaterNotificationContext(getHandle()); | ||
150 | } | 152 | } |
151 | 153 | ||
152 | LLFloater::LLFloater(const std::string& name) | 154 | LLFloater::LLFloater(const std::string& name) |
@@ -220,6 +222,7 @@ void LLFloater::initFloater(const std::string& title, | |||
220 | BOOL drag_on_left, BOOL minimizable, BOOL close_btn) | 222 | BOOL drag_on_left, BOOL minimizable, BOOL close_btn) |
221 | { | 223 | { |
222 | mHandle.bind(this); | 224 | mHandle.bind(this); |
225 | mNotificationContext = new LLFloaterNotificationContext(getHandle()); | ||
223 | 226 | ||
224 | // Init function can be called more than once, so clear out old data. | 227 | // Init function can be called more than once, so clear out old data. |
225 | for (S32 i = 0; i < BUTTON_COUNT; i++) | 228 | for (S32 i = 0; i < BUTTON_COUNT; i++) |
@@ -429,6 +432,9 @@ void LLFloater::initFloater(const std::string& title, | |||
429 | // virtual | 432 | // virtual |
430 | LLFloater::~LLFloater() | 433 | LLFloater::~LLFloater() |
431 | { | 434 | { |
435 | delete mNotificationContext; | ||
436 | mNotificationContext = NULL; | ||
437 | |||
432 | control_map_t::iterator itor; | 438 | control_map_t::iterator itor; |
433 | for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor) | 439 | for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor) |
434 | { | 440 | { |
@@ -774,7 +780,7 @@ void LLFloater::snappedTo(const LLView* snap_view) | |||
774 | 780 | ||
775 | void LLFloater::userSetShape(const LLRect& new_rect) | 781 | void LLFloater::userSetShape(const LLRect& new_rect) |
776 | { | 782 | { |
777 | const LLRect& old_rect = getRect(); | 783 | const LLRect old_rect = getRect(); |
778 | LLView::userSetShape(new_rect); | 784 | LLView::userSetShape(new_rect); |
779 | 785 | ||
780 | // if not minimized, adjust all snapped dependents to new shape | 786 | // if not minimized, adjust all snapped dependents to new shape |
@@ -1697,7 +1703,7 @@ void LLFloater::buildButtons() | |||
1697 | LLStringUtil::null, | 1703 | LLStringUtil::null, |
1698 | sButtonCallbacks[i], | 1704 | sButtonCallbacks[i], |
1699 | this, | 1705 | this, |
1700 | LLFontGL::sSansSerif); | 1706 | LLFontGL::getFontSansSerif()); |
1701 | 1707 | ||
1702 | buttonp->setTabStop(FALSE); | 1708 | buttonp->setTabStop(FALSE); |
1703 | buttonp->setFollowsTop(); | 1709 | buttonp->setFollowsTop(); |
diff --git a/linden/indra/llui/llfloater.h b/linden/indra/llui/llfloater.h index a6fe3cc..a8f7c21 100644 --- a/linden/indra/llui/llfloater.h +++ b/linden/indra/llui/llfloater.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -39,6 +40,7 @@ | |||
39 | #include "llpanel.h" | 40 | #include "llpanel.h" |
40 | #include "lluuid.h" | 41 | #include "lluuid.h" |
41 | #include "lltabcontainer.h" | 42 | #include "lltabcontainer.h" |
43 | #include "llnotifications.h" | ||
42 | #include <set> | 44 | #include <set> |
43 | 45 | ||
44 | class LLDragHandle; | 46 | class LLDragHandle; |
@@ -46,6 +48,7 @@ class LLResizeHandle; | |||
46 | class LLResizeBar; | 48 | class LLResizeBar; |
47 | class LLButton; | 49 | class LLButton; |
48 | class LLMultiFloater; | 50 | class LLMultiFloater; |
51 | class LLFloater; | ||
49 | 52 | ||
50 | const S32 LLFLOATER_VPAD = 6; | 53 | const S32 LLFLOATER_VPAD = 6; |
51 | const S32 LLFLOATER_HPAD = 6; | 54 | const S32 LLFLOATER_HPAD = 6; |
@@ -70,6 +73,20 @@ const BOOL CLOSE_NO = FALSE; | |||
70 | const BOOL ADJUST_VERTICAL_YES = TRUE; | 73 | const BOOL ADJUST_VERTICAL_YES = TRUE; |
71 | const BOOL ADJUST_VERTICAL_NO = FALSE; | 74 | const BOOL ADJUST_VERTICAL_NO = FALSE; |
72 | 75 | ||
76 | // associates a given notification instance with a particular floater | ||
77 | class LLFloaterNotificationContext : | ||
78 | public LLNotificationContext | ||
79 | { | ||
80 | public: | ||
81 | LLFloaterNotificationContext(LLHandle<LLFloater> floater_handle) : | ||
82 | mFloaterHandle(floater_handle) | ||
83 | {} | ||
84 | |||
85 | LLFloater* getFloater() { return mFloaterHandle.get(); } | ||
86 | private: | ||
87 | LLHandle<LLFloater> mFloaterHandle; | ||
88 | }; | ||
89 | |||
73 | 90 | ||
74 | class LLFloater : public LLPanel | 91 | class LLFloater : public LLPanel |
75 | { | 92 | { |
@@ -213,6 +230,11 @@ public: | |||
213 | // handle refocusing. | 230 | // handle refocusing. |
214 | static void closeFocusedFloater(); | 231 | static void closeFocusedFloater(); |
215 | 232 | ||
233 | LLNotification::Params contextualNotification(const std::string& name) | ||
234 | { | ||
235 | return LLNotification::Params(name).context(mNotificationContext); | ||
236 | } | ||
237 | |||
216 | static void onClickClose(void *userdata); | 238 | static void onClickClose(void *userdata); |
217 | static void onClickMinimize(void *userdata); | 239 | static void onClickMinimize(void *userdata); |
218 | static void onClickTearOff(void *userdata); | 240 | static void onClickTearOff(void *userdata); |
@@ -299,7 +321,7 @@ private: | |||
299 | S32 mPreviousMinimizedBottom; | 321 | S32 mPreviousMinimizedBottom; |
300 | S32 mPreviousMinimizedLeft; | 322 | S32 mPreviousMinimizedLeft; |
301 | 323 | ||
302 | private: | 324 | LLFloaterNotificationContext* mNotificationContext; |
303 | LLRootHandle<LLFloater> mHandle; | 325 | LLRootHandle<LLFloater> mHandle; |
304 | }; | 326 | }; |
305 | 327 | ||
@@ -461,13 +483,12 @@ public: | |||
461 | 483 | ||
462 | 484 | ||
463 | // singleton implementation for floaters (provides visibility policy) | 485 | // singleton implementation for floaters (provides visibility policy) |
464 | // https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=79410 | 486 | // https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 |
465 | 487 | ||
466 | template <class T> class LLFloaterSingleton : public LLUISingleton<T, VisibilityPolicy<LLFloater> > | 488 | template <class T> class LLFloaterSingleton : public LLUISingleton<T, VisibilityPolicy<LLFloater> > |
467 | { | 489 | { |
468 | }; | 490 | }; |
469 | 491 | ||
470 | |||
471 | extern LLFloaterView* gFloaterView; | 492 | extern LLFloaterView* gFloaterView; |
472 | 493 | ||
473 | #endif // LL_FLOATER_H | 494 | #endif // LL_FLOATER_H |
diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp index 69010cd..661ffdd 100644 --- a/linden/indra/llui/llfocusmgr.cpp +++ b/linden/indra/llui/llfocusmgr.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h index 61daca7..aaeb25a 100644 --- a/linden/indra/llui/llfocusmgr.h +++ b/linden/indra/llui/llfocusmgr.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llfunctorregistry.cpp b/linden/indra/llui/llfunctorregistry.cpp new file mode 100644 index 0000000..0c5b165 --- /dev/null +++ b/linden/indra/llui/llfunctorregistry.cpp | |||
@@ -0,0 +1,38 @@ | |||
1 | /** | ||
2 | * @file llfunctorregistry.cpp | ||
3 | * @author Kent Quirk | ||
4 | * @brief Maintains a registry of named callback functors taking a single LLSD parameter | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
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 | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | **/ | ||
33 | |||
34 | #include "llfunctorregistry.h" | ||
35 | |||
36 | // This is a default functor always resident in the system. | ||
37 | // It's used whenever a functor isn't found in the registry, so that | ||
38 | // we at least log the data relating to the user response. | ||
diff --git a/linden/indra/llui/llfunctorregistry.h b/linden/indra/llui/llfunctorregistry.h new file mode 100644 index 0000000..8864f7a --- /dev/null +++ b/linden/indra/llui/llfunctorregistry.h | |||
@@ -0,0 +1,146 @@ | |||
1 | /** | ||
2 | * @file llfunctorregistry.h | ||
3 | * @author Kent Quirk | ||
4 | * @brief Maintains a registry of named callback functors taking a single LLSD parameter | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
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 | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LLFUNCTORREGISTRY_H | ||
35 | #define LL_LLFUNCTORREGISTRY_H | ||
36 | |||
37 | #include <string> | ||
38 | #include <map> | ||
39 | |||
40 | #include <boost/function.hpp> | ||
41 | |||
42 | #include "llsd.h" | ||
43 | #include "llmemory.h" | ||
44 | |||
45 | /** | ||
46 | * @class LLFunctorRegistry | ||
47 | * @brief Maintains a collection of named functors for remote binding | ||
48 | * (mainly for use in callbacks from notifications and other signals) | ||
49 | * @see LLNotifications | ||
50 | * | ||
51 | * This class maintains a collection of named functors in a singleton. | ||
52 | * We wanted to be able to persist notifications with their callbacks | ||
53 | * across restarts of the viewer; we couldn't store functors that way. | ||
54 | * Using this registry, systems that require a functor to be maintained | ||
55 | * long term can register it at system startup, and then pass in the | ||
56 | * functor by name. | ||
57 | */ | ||
58 | |||
59 | template <typename FUNCTOR_TYPE> | ||
60 | class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> > | ||
61 | { | ||
62 | friend class LLSingleton<LLFunctorRegistry>; | ||
63 | LOG_CLASS(LLFunctorRegistry); | ||
64 | private: | ||
65 | LLFunctorRegistry() : LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") | ||
66 | { | ||
67 | mMap[LOGFUNCTOR] = log_functor; | ||
68 | mMap[DONOTHING] = do_nothing; | ||
69 | } | ||
70 | |||
71 | public: | ||
72 | typedef FUNCTOR_TYPE ResponseFunctor; | ||
73 | typedef typename std::map<std::string, FUNCTOR_TYPE> FunctorMap; | ||
74 | |||
75 | bool registerFunctor(const std::string& name, ResponseFunctor f) | ||
76 | { | ||
77 | bool retval = true; | ||
78 | typename FunctorMap::iterator it = mMap.find(name); | ||
79 | if (mMap.count(name) == 0) | ||
80 | { | ||
81 | mMap[name] = f; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | llerrs << "attempt to store duplicate name '" << name << "' in LLFunctorRegistry. NOT ADDED." << llendl; | ||
86 | retval = false; | ||
87 | } | ||
88 | |||
89 | return retval; | ||
90 | } | ||
91 | |||
92 | bool unregisterFunctor(const std::string& name) | ||
93 | { | ||
94 | if (mMap.count(name) == 0) | ||
95 | { | ||
96 | llwarns << "trying to remove '" << name << "' from LLFunctorRegistry but it's not there." << llendl; | ||
97 | return false; | ||
98 | } | ||
99 | mMap.erase(name); | ||
100 | return true; | ||
101 | } | ||
102 | |||
103 | FUNCTOR_TYPE getFunctor(const std::string& name) | ||
104 | { | ||
105 | typename FunctorMap::iterator it = mMap.find(name); | ||
106 | if (mMap.count(name) != 0) | ||
107 | { | ||
108 | return mMap[name]; | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | llwarns << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl; | ||
113 | return mMap[LOGFUNCTOR]; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | const std::string LOGFUNCTOR; | ||
118 | const std::string DONOTHING; | ||
119 | |||
120 | private: | ||
121 | |||
122 | static void log_functor(const LLSD& notification, const LLSD& payload) | ||
123 | { | ||
124 | llwarns << "log_functor called with payload: " << payload << llendl; | ||
125 | } | ||
126 | |||
127 | static void do_nothing(const LLSD& notification, const LLSD& payload) | ||
128 | { | ||
129 | // what the sign sez | ||
130 | } | ||
131 | |||
132 | FunctorMap mMap; | ||
133 | }; | ||
134 | |||
135 | template <typename FUNCTOR_TYPE> | ||
136 | class LLFunctorRegistration | ||
137 | { | ||
138 | public: | ||
139 | LLFunctorRegistration(const std::string& name, FUNCTOR_TYPE functor) | ||
140 | { | ||
141 | LLFunctorRegistry<FUNCTOR_TYPE>::instance().registerFunctor(name, functor); | ||
142 | } | ||
143 | }; | ||
144 | |||
145 | #endif//LL_LLFUNCTORREGISTRY_H | ||
146 | |||
diff --git a/linden/indra/llui/llhtmlhelp.h b/linden/indra/llui/llhtmlhelp.h index 3383148..2841a12 100644 --- a/linden/indra/llui/llhtmlhelp.h +++ b/linden/indra/llui/llhtmlhelp.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lliconctrl.cpp b/linden/indra/llui/lliconctrl.cpp index 71c2315..cb3b2a3 100644 --- a/linden/indra/llui/lliconctrl.cpp +++ b/linden/indra/llui/lliconctrl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lliconctrl.h b/linden/indra/llui/lliconctrl.h index a8a265d..50778cf 100644 --- a/linden/indra/llui/lliconctrl.h +++ b/linden/indra/llui/lliconctrl.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llkeywords.cpp b/linden/indra/llui/llkeywords.cpp index 53df1c1..51ef3db 100644 --- a/linden/indra/llui/llkeywords.cpp +++ b/linden/indra/llui/llkeywords.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llkeywords.h b/linden/indra/llui/llkeywords.h index 1ae0b3c..38f5e99 100644 --- a/linden/indra/llui/llkeywords.h +++ b/linden/indra/llui/llkeywords.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp index 64b1284..6aa2aac 100644 --- a/linden/indra/llui/lllineeditor.cpp +++ b/linden/indra/llui/lllineeditor.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -151,7 +152,7 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, | |||
151 | } | 152 | } |
152 | else | 153 | else |
153 | { | 154 | { |
154 | mGLFont = LLFontGL::sSansSerifSmall; | 155 | mGLFont = LLFontGL::getFontSansSerifSmall(); |
155 | } | 156 | } |
156 | 157 | ||
157 | setFocusLostCallback(focus_lost_callback); | 158 | setFocusLostCallback(focus_lost_callback); |
@@ -361,7 +362,7 @@ void LLLineEditor::setCursor( S32 pos ) | |||
361 | { | 362 | { |
362 | S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); | 363 | S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); |
363 | S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left))); | 364 | S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left))); |
364 | S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels), mText.length(), getCursor()); | 365 | S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels - UI_LINEEDITOR_CURSOR_THICKNESS - UI_LINEEDITOR_H_PAD), mText.length(), getCursor()); |
365 | if (old_cursor_pos == last_visible_char) | 366 | if (old_cursor_pos == last_visible_char) |
366 | { | 367 | { |
367 | mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); | 368 | mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); |
diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h index 52cbfcf..254ba19 100644 --- a/linden/indra/llui/lllineeditor.h +++ b/linden/indra/llui/lllineeditor.h | |||
@@ -26,7 +26,8 @@ | |||
26 | * There are special exceptions to the terms and conditions of the GPL as | 26 | * There are special exceptions to the terms and conditions of the GPL as |
27 | * it is applied to this Source Code. View the full text of the exception | 27 | * it is applied to this Source Code. View the full text of the exception |
28 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 28 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
29 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 29 | * online at |
30 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
30 | * | 31 | * |
31 | * By copying, modifying or distributing this software, you acknowledge | 32 | * By copying, modifying or distributing this software, you acknowledge |
32 | * that you have read and understood your obligations described above, | 33 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llui/llmemberlistener.h b/linden/indra/llui/llmemberlistener.h index 3b702ed..a5e019c 100644 --- a/linden/indra/llui/llmemberlistener.h +++ b/linden/indra/llui/llmemberlistener.h | |||
@@ -43,7 +43,8 @@ | |||
43 | * There are special exceptions to the terms and conditions of the GPL as | 43 | * There are special exceptions to the terms and conditions of the GPL as |
44 | * it is applied to this Source Code. View the full text of the exception | 44 | * it is applied to this Source Code. View the full text of the exception |
45 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 45 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
46 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 46 | * online at |
47 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
47 | * | 48 | * |
48 | * By copying, modifying or distributing this software, you acknowledge | 49 | * By copying, modifying or distributing this software, you acknowledge |
49 | * that you have read and understood your obligations described above, | 50 | * 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 907777d..f2f2aae 100644 --- a/linden/indra/llui/llmenugl.cpp +++ b/linden/indra/llui/llmenugl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -58,6 +59,8 @@ | |||
58 | #include "llresmgr.h" | 59 | #include "llresmgr.h" |
59 | #include "llui.h" | 60 | #include "llui.h" |
60 | 61 | ||
62 | #include "lluitrans.h" | ||
63 | |||
61 | #include "llstl.h" | 64 | #include "llstl.h" |
62 | 65 | ||
63 | #include "v2math.h" | 66 | #include "v2math.h" |
@@ -139,7 +142,7 @@ LLMenuItemGL::LLMenuItemGL( const std::string& name, const std::string& label, K | |||
139 | mHighlight( FALSE ), | 142 | mHighlight( FALSE ), |
140 | mGotHover( FALSE ), | 143 | mGotHover( FALSE ), |
141 | mBriefItem( FALSE ), | 144 | mBriefItem( FALSE ), |
142 | mFont( LLFontGL::sSansSerif ), | 145 | mFont( LLFontGL::getFontSansSerif() ), |
143 | mStyle(LLFontGL::NORMAL), | 146 | mStyle(LLFontGL::NORMAL), |
144 | mDrawTextDisabled( FALSE ) | 147 | mDrawTextDisabled( FALSE ) |
145 | { | 148 | { |
@@ -266,24 +269,24 @@ void LLMenuItemGL::appendAcceleratorString( std::string& st ) const | |||
266 | { | 269 | { |
267 | if ( mAcceleratorMask & MASK_MAC_CONTROL ) | 270 | if ( mAcceleratorMask & MASK_MAC_CONTROL ) |
268 | { | 271 | { |
269 | st.append( "Ctrl-" ); | 272 | st.append( LLUITrans::getString("accel-mac-control") ); |
270 | } | 273 | } |
271 | else | 274 | else |
272 | { | 275 | { |
273 | st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98" | 276 | st.append( LLUITrans::getString("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98" |
274 | } | 277 | } |
275 | } | 278 | } |
276 | if( mAcceleratorMask & MASK_ALT ) | 279 | if( mAcceleratorMask & MASK_ALT ) |
277 | st.append( "Opt-" ); // Symbol would be "\xE2\x8C\xA5" | 280 | st.append( LLUITrans::getString("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5" |
278 | if( mAcceleratorMask & MASK_SHIFT ) | 281 | if( mAcceleratorMask & MASK_SHIFT ) |
279 | st.append( "Shift-" ); // Symbol would be "\xE2\x8C\xA7" | 282 | st.append( LLUITrans::getString("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7" |
280 | #else | 283 | #else |
281 | if( mAcceleratorMask & MASK_CONTROL ) | 284 | if( mAcceleratorMask & MASK_CONTROL ) |
282 | st.append( "Ctrl-" ); | 285 | st.append( LLUITrans::getString("accel-win-control") ); |
283 | if( mAcceleratorMask & MASK_ALT ) | 286 | if( mAcceleratorMask & MASK_ALT ) |
284 | st.append( "Alt-" ); | 287 | st.append( LLUITrans::getString("accel-win-alt") ); |
285 | if( mAcceleratorMask & MASK_SHIFT ) | 288 | if( mAcceleratorMask & MASK_SHIFT ) |
286 | st.append( "Shift-" ); | 289 | st.append( LLUITrans::getString("accel-win-shift") ); |
287 | #endif | 290 | #endif |
288 | 291 | ||
289 | std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey ); | 292 | std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey ); |
@@ -2165,8 +2168,8 @@ void LLMenuGL::arrange( void ) | |||
2165 | U32 max_width = getTornOff() ? U32_MAX : menu_region_rect.getWidth(); | 2168 | U32 max_width = getTornOff() ? U32_MAX : menu_region_rect.getWidth(); |
2166 | U32 max_height = getTornOff() ? U32_MAX : menu_region_rect.getHeight(); | 2169 | U32 max_height = getTornOff() ? U32_MAX : menu_region_rect.getHeight(); |
2167 | // *FIX: create the item first and then ask for its dimensions? | 2170 | // *FIX: create the item first and then ask for its dimensions? |
2168 | S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::sSansSerif->getWidth( std::string("More") ); | 2171 | S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); |
2169 | S32 spillover_item_height = llround(LLFontGL::sSansSerif->getLineHeight()) + MENU_ITEM_PADDING; | 2172 | S32 spillover_item_height = llround(LLFontGL::getFontSansSerif()->getLineHeight()) + MENU_ITEM_PADDING; |
2170 | 2173 | ||
2171 | if (mHorizontalLayout) | 2174 | if (mHorizontalLayout) |
2172 | { | 2175 | { |
@@ -3492,7 +3495,7 @@ void LLPieMenu::drawBackground(LLMenuItemGL* itemp, LLColor4& color) | |||
3492 | BOOL LLPieMenu::append(LLMenuItemGL *item) | 3495 | BOOL LLPieMenu::append(LLMenuItemGL *item) |
3493 | { | 3496 | { |
3494 | item->setBriefItem(TRUE); | 3497 | item->setBriefItem(TRUE); |
3495 | item->setFont( LLFontGL::sSansSerifSmall ); | 3498 | item->setFont( LLFontGL::getFontSansSerifSmall() ); |
3496 | return LLMenuGL::append(item); | 3499 | return LLMenuGL::append(item); |
3497 | } | 3500 | } |
3498 | 3501 | ||
@@ -3500,7 +3503,7 @@ BOOL LLPieMenu::append(LLMenuItemGL *item) | |||
3500 | BOOL LLPieMenu::appendSeparator(const std::string &separator_name) | 3503 | BOOL LLPieMenu::appendSeparator(const std::string &separator_name) |
3501 | { | 3504 | { |
3502 | LLMenuItemGL* separator = new LLMenuItemBlankGL(); | 3505 | LLMenuItemGL* separator = new LLMenuItemBlankGL(); |
3503 | separator->setFont( LLFontGL::sSansSerifSmall ); | 3506 | separator->setFont( LLFontGL::getFontSansSerifSmall() ); |
3504 | return append( separator ); | 3507 | return append( separator ); |
3505 | } | 3508 | } |
3506 | 3509 | ||
@@ -3514,7 +3517,7 @@ BOOL LLPieMenu::appendPieMenu(LLPieMenu *menu) | |||
3514 | LLPieMenuBranch *item; | 3517 | LLPieMenuBranch *item; |
3515 | item = new LLPieMenuBranch(menu->getName(), menu->getLabel(), menu); | 3518 | item = new LLPieMenuBranch(menu->getName(), menu->getLabel(), menu); |
3516 | getParent()->addChild(item->getBranch()); | 3519 | getParent()->addChild(item->getBranch()); |
3517 | item->setFont( LLFontGL::sSansSerifSmall ); | 3520 | item->setFont( LLFontGL::getFontSansSerifSmall() ); |
3518 | return append( item ); | 3521 | return append( item ); |
3519 | } | 3522 | } |
3520 | 3523 | ||
diff --git a/linden/indra/llui/llmenugl.h b/linden/indra/llui/llmenugl.h index d981e78..a2ef968 100644 --- a/linden/indra/llui/llmenugl.h +++ b/linden/indra/llui/llmenugl.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llmodaldialog.cpp b/linden/indra/llui/llmodaldialog.cpp index 682cc08..1662ff7 100644 --- a/linden/indra/llui/llmodaldialog.cpp +++ b/linden/indra/llui/llmodaldialog.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llmodaldialog.h b/linden/indra/llui/llmodaldialog.h index 5bb1a74..f6abd0a 100644 --- a/linden/indra/llui/llmodaldialog.h +++ b/linden/indra/llui/llmodaldialog.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llmultislider.cpp b/linden/indra/llui/llmultislider.cpp index 415e96b..c1487be 100644 --- a/linden/indra/llui/llmultislider.cpp +++ b/linden/indra/llui/llmultislider.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llmultislider.h b/linden/indra/llui/llmultislider.h index 08cfa78..cdbdb59 100644 --- a/linden/indra/llui/llmultislider.h +++ b/linden/indra/llui/llmultislider.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llmultisliderctrl.cpp b/linden/indra/llui/llmultisliderctrl.cpp index 53c0799..8bcf9f9 100644 --- a/linden/indra/llui/llmultisliderctrl.cpp +++ b/linden/indra/llui/llmultisliderctrl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -543,7 +544,7 @@ LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFa | |||
543 | // HACK: Font might not be specified. | 544 | // HACK: Font might not be specified. |
544 | if (!font) | 545 | if (!font) |
545 | { | 546 | { |
546 | font = LLFontGL::sSansSerifSmall; | 547 | font = LLFontGL::getFontSansSerifSmall(); |
547 | } | 548 | } |
548 | 549 | ||
549 | S32 label_width = 0; | 550 | S32 label_width = 0; |
diff --git a/linden/indra/llui/llmultisliderctrl.h b/linden/indra/llui/llmultisliderctrl.h index 4145d70..b62b5ec 100644 --- a/linden/indra/llui/llmultisliderctrl.h +++ b/linden/indra/llui/llmultisliderctrl.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llnotifications.cpp b/linden/indra/llui/llnotifications.cpp new file mode 100644 index 0000000..2ae9672 --- /dev/null +++ b/linden/indra/llui/llnotifications.cpp | |||
@@ -0,0 +1,1487 @@ | |||
1 | /** | ||
2 | * @file llnotifications.cpp | ||
3 | * @brief Non-UI queue manager for keeping a prioritized list of notifications | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | #include "lluictrlfactory.h" | ||
35 | #include "lldir.h" | ||
36 | #include "llsdserialize.h" | ||
37 | |||
38 | #include "llnotifications.h" | ||
39 | |||
40 | #include <algorithm> | ||
41 | #include <boost/regex.hpp> | ||
42 | |||
43 | |||
44 | const std::string NOTIFICATION_PERSIST_VERSION = "0.93"; | ||
45 | |||
46 | // local channel for notification history | ||
47 | class LLNotificationHistoryChannel : public LLNotificationChannel | ||
48 | { | ||
49 | LOG_CLASS(LLNotificationHistoryChannel); | ||
50 | public: | ||
51 | LLNotificationHistoryChannel(const std::string& filename) : | ||
52 | LLNotificationChannel("History", "Visible", &historyFilter, LLNotificationComparators::orderByUUID()), | ||
53 | mFileName(filename) | ||
54 | { | ||
55 | connectChanged(boost::bind(&LLNotificationHistoryChannel::historyHandler, this, _1)); | ||
56 | loadPersistentNotifications(); | ||
57 | } | ||
58 | |||
59 | private: | ||
60 | bool historyHandler(const LLSD& payload) | ||
61 | { | ||
62 | // we ignore "load" messages, but rewrite the persistence file on any other | ||
63 | std::string sigtype = payload["sigtype"]; | ||
64 | if (sigtype != "load") | ||
65 | { | ||
66 | savePersistentNotifications(); | ||
67 | } | ||
68 | return false; | ||
69 | } | ||
70 | |||
71 | // The history channel gets all notifications except those that have been cancelled | ||
72 | static bool historyFilter(LLNotificationPtr pNotification) | ||
73 | { | ||
74 | return !pNotification->isCancelled(); | ||
75 | } | ||
76 | |||
77 | void savePersistentNotifications() | ||
78 | { | ||
79 | llinfos << "Saving open notifications to " << mFileName << llendl; | ||
80 | |||
81 | llofstream notify_file(mFileName.c_str()); | ||
82 | if (!notify_file.is_open()) | ||
83 | { | ||
84 | llwarns << "Failed to open " << mFileName << llendl; | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | LLSD output; | ||
89 | output["version"] = NOTIFICATION_PERSIST_VERSION; | ||
90 | LLSD& data = output["data"]; | ||
91 | |||
92 | for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) | ||
93 | { | ||
94 | if (!LLNotifications::instance().templateExists((*it)->getName())) continue; | ||
95 | |||
96 | // only store notifications flagged as persisting | ||
97 | LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate((*it)->getName()); | ||
98 | if (!templatep->mPersist) continue; | ||
99 | |||
100 | data.append((*it)->asLLSD()); | ||
101 | } | ||
102 | |||
103 | LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); | ||
104 | formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY); | ||
105 | } | ||
106 | |||
107 | void loadPersistentNotifications() | ||
108 | { | ||
109 | llinfos << "Loading open notifications from " << mFileName << llendl; | ||
110 | |||
111 | llifstream notify_file(mFileName.c_str()); | ||
112 | if (!notify_file.is_open()) | ||
113 | { | ||
114 | llwarns << "Failed to open " << mFileName << llendl; | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | LLSD input; | ||
119 | LLPointer<LLSDParser> parser = new LLSDXMLParser(); | ||
120 | if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) | ||
121 | { | ||
122 | llwarns << "Failed to parse open notifications" << llendl; | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | if (input.isUndefined()) return; | ||
127 | std::string version = input["version"]; | ||
128 | if (version != NOTIFICATION_PERSIST_VERSION) | ||
129 | { | ||
130 | llwarns << "Bad open notifications version: " << version << llendl; | ||
131 | return; | ||
132 | } | ||
133 | LLSD& data = input["data"]; | ||
134 | if (data.isUndefined()) return; | ||
135 | |||
136 | LLNotifications& instance = LLNotifications::instance(); | ||
137 | for (LLSD::array_const_iterator notification_it = data.beginArray(); | ||
138 | notification_it != data.endArray(); | ||
139 | ++notification_it) | ||
140 | { | ||
141 | instance.add(LLNotificationPtr(new LLNotification(*notification_it))); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | //virtual | ||
146 | void onDelete(LLNotificationPtr pNotification) | ||
147 | { | ||
148 | // we want to keep deleted notifications in our log | ||
149 | mItems.insert(pNotification); | ||
150 | |||
151 | return; | ||
152 | } | ||
153 | |||
154 | private: | ||
155 | std::string mFileName; | ||
156 | }; | ||
157 | |||
158 | bool filterIgnoredNotifications(LLNotificationPtr notification) | ||
159 | { | ||
160 | LLNotificationFormPtr form = notification->getForm(); | ||
161 | // Check to see if the user wants to ignore this alert | ||
162 | if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO) | ||
163 | { | ||
164 | return LLUI::sConfigGroup->getWarning(notification->getName()); | ||
165 | } | ||
166 | |||
167 | return true; | ||
168 | } | ||
169 | |||
170 | bool handleIgnoredNotification(const LLSD& payload) | ||
171 | { | ||
172 | if (payload["sigtype"].asString() == "add") | ||
173 | { | ||
174 | LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); | ||
175 | if (!pNotif) return false; | ||
176 | |||
177 | LLNotificationFormPtr form = pNotif->getForm(); | ||
178 | LLSD response; | ||
179 | switch(form->getIgnoreType()) | ||
180 | { | ||
181 | case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE: | ||
182 | response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON); | ||
183 | break; | ||
184 | case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE: | ||
185 | response = LLUI::sIgnoresGroup->getLLSD("Default" + pNotif->getName()); | ||
186 | break; | ||
187 | case LLNotificationForm::IGNORE_SHOW_AGAIN: | ||
188 | break; | ||
189 | default: | ||
190 | return false; | ||
191 | } | ||
192 | pNotif->setIgnored(true); | ||
193 | pNotif->respond(response); | ||
194 | return true; // don't process this item any further | ||
195 | } | ||
196 | return false; | ||
197 | } | ||
198 | |||
199 | namespace LLNotificationFilters | ||
200 | { | ||
201 | // a sample filter | ||
202 | bool includeEverything(LLNotificationPtr p) | ||
203 | { | ||
204 | return true; | ||
205 | } | ||
206 | }; | ||
207 | |||
208 | LLNotificationForm::LLNotificationForm() | ||
209 | : mFormData(LLSD::emptyArray()), | ||
210 | mIgnore(IGNORE_NO) | ||
211 | { | ||
212 | } | ||
213 | |||
214 | |||
215 | LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node) | ||
216 | : mFormData(LLSD::emptyArray()), | ||
217 | mIgnore(IGNORE_NO) | ||
218 | { | ||
219 | if (!xml_node->hasName("form")) | ||
220 | { | ||
221 | llwarns << "Bad xml node for form: " << xml_node->getName() << llendl; | ||
222 | } | ||
223 | LLXMLNodePtr child = xml_node->getFirstChild(); | ||
224 | while(child) | ||
225 | { | ||
226 | child = LLNotifications::instance().checkForXMLTemplate(child); | ||
227 | |||
228 | LLSD item_entry; | ||
229 | std::string element_name = child->getName()->mString; | ||
230 | |||
231 | if (element_name == "ignore") | ||
232 | { | ||
233 | bool save_option = false; | ||
234 | child->getAttribute_bool("save_option", save_option); | ||
235 | if (!save_option) | ||
236 | { | ||
237 | mIgnore = IGNORE_WITH_DEFAULT_RESPONSE; | ||
238 | } | ||
239 | else | ||
240 | { | ||
241 | // remember last option chosen by user and automatically respond with that in the future | ||
242 | mIgnore = IGNORE_WITH_LAST_RESPONSE; | ||
243 | LLUI::sIgnoresGroup->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name)); | ||
244 | } | ||
245 | child->getAttributeString("text", mIgnoreMsg); | ||
246 | LLUI::sIgnoresGroup->addWarning(name); | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | // flatten xml form entry into single LLSD map with type==name | ||
251 | item_entry["type"] = element_name; | ||
252 | const LLXMLAttribList::iterator attrib_end = child->mAttributes.end(); | ||
253 | for(LLXMLAttribList::iterator attrib_it = child->mAttributes.begin(); | ||
254 | attrib_it != attrib_end; | ||
255 | ++attrib_it) | ||
256 | { | ||
257 | item_entry[std::string(attrib_it->second->getName()->mString)] = attrib_it->second->getValue(); | ||
258 | } | ||
259 | item_entry["value"] = child->getTextContents(); | ||
260 | mFormData.append(item_entry); | ||
261 | } | ||
262 | |||
263 | child = child->getNextSibling(); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | LLNotificationForm::LLNotificationForm(const LLSD& sd) | ||
268 | { | ||
269 | if (sd.isArray()) | ||
270 | { | ||
271 | mFormData = sd; | ||
272 | } | ||
273 | else | ||
274 | { | ||
275 | llwarns << "Invalid form data " << sd << llendl; | ||
276 | mFormData = LLSD::emptyArray(); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | LLSD LLNotificationForm::asLLSD() const | ||
281 | { | ||
282 | return mFormData; | ||
283 | } | ||
284 | |||
285 | LLSD LLNotificationForm::getElement(const std::string& element_name) | ||
286 | { | ||
287 | for (LLSD::array_const_iterator it = mFormData.beginArray(); | ||
288 | it != mFormData.endArray(); | ||
289 | ++it) | ||
290 | { | ||
291 | if ((*it)["name"].asString() == element_name) return (*it); | ||
292 | } | ||
293 | return LLSD(); | ||
294 | } | ||
295 | |||
296 | |||
297 | bool LLNotificationForm::hasElement(const std::string& element_name) | ||
298 | { | ||
299 | for (LLSD::array_const_iterator it = mFormData.beginArray(); | ||
300 | it != mFormData.endArray(); | ||
301 | ++it) | ||
302 | { | ||
303 | if ((*it)["name"].asString() == element_name) return true; | ||
304 | } | ||
305 | return false; | ||
306 | } | ||
307 | |||
308 | void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value) | ||
309 | { | ||
310 | LLSD element; | ||
311 | element["type"] = type; | ||
312 | element["name"] = name; | ||
313 | element["label"] = name; | ||
314 | element["value"] = value; | ||
315 | element["index"] = mFormData.size(); | ||
316 | mFormData.append(element); | ||
317 | } | ||
318 | |||
319 | void LLNotificationForm::append(const LLSD& sub_form) | ||
320 | { | ||
321 | if (sub_form.isArray()) | ||
322 | { | ||
323 | for (LLSD::array_const_iterator it = sub_form.beginArray(); | ||
324 | it != sub_form.endArray(); | ||
325 | ++it) | ||
326 | { | ||
327 | mFormData.append(*it); | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | |||
332 | void LLNotificationForm::formatElements(const LLSD& substitutions) | ||
333 | { | ||
334 | for (LLSD::array_iterator it = mFormData.beginArray(); | ||
335 | it != mFormData.endArray(); | ||
336 | ++it) | ||
337 | { | ||
338 | // format "text" component of each form element | ||
339 | if ((*it).has("text")) | ||
340 | { | ||
341 | std::string text = (*it)["text"].asString(); | ||
342 | text = LLNotification::format(text, substitutions); | ||
343 | (*it)["text"] = text; | ||
344 | } | ||
345 | if ((*it)["type"].asString() == "text" && (*it).has("value")) | ||
346 | { | ||
347 | std::string value = (*it)["value"].asString(); | ||
348 | value = LLNotification::format(value, substitutions); | ||
349 | (*it)["value"] = value; | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
354 | std::string LLNotificationForm::getDefaultOption() | ||
355 | { | ||
356 | for (LLSD::array_const_iterator it = mFormData.beginArray(); | ||
357 | it != mFormData.endArray(); | ||
358 | ++it) | ||
359 | { | ||
360 | if ((*it)["default"]) return (*it)["name"].asString(); | ||
361 | } | ||
362 | return ""; | ||
363 | } | ||
364 | |||
365 | LLNotificationTemplate::LLNotificationTemplate() : | ||
366 | mExpireSeconds(0), | ||
367 | mExpireOption(-1), | ||
368 | mURLOption(-1), | ||
369 | mUnique(false), | ||
370 | mPriority(NOTIFICATION_PRIORITY_NORMAL) | ||
371 | { | ||
372 | mForm = LLNotificationFormPtr(new LLNotificationForm()); | ||
373 | } | ||
374 | |||
375 | LLNotification::LLNotification(const LLNotification::Params& p) : | ||
376 | mTimestamp(p.timestamp), | ||
377 | mSubstitutions(p.substitutions), | ||
378 | mPayload(p.payload), | ||
379 | mExpiresAt(0), | ||
380 | mResponseFunctorName(p.functor_name), | ||
381 | mTemporaryResponder(p.mTemporaryResponder), | ||
382 | mRespondedTo(false), | ||
383 | mPriority(p.priority), | ||
384 | mCancelled(false), | ||
385 | mIgnored(false) | ||
386 | { | ||
387 | mId.generate(); | ||
388 | init(p.name, p.form_elements); | ||
389 | } | ||
390 | |||
391 | |||
392 | LLNotification::LLNotification(const LLSD& sd) : | ||
393 | mTemporaryResponder(false), | ||
394 | mRespondedTo(false), | ||
395 | mCancelled(false), | ||
396 | mIgnored(false) | ||
397 | { | ||
398 | mId.generate(); | ||
399 | mSubstitutions = sd["substitutions"]; | ||
400 | mPayload = sd["payload"]; | ||
401 | mTimestamp = sd["time"]; | ||
402 | mExpiresAt = sd["expiry"]; | ||
403 | mPriority = (ENotificationPriority)sd["priority"].asInteger(); | ||
404 | mResponseFunctorName = sd["responseFunctor"].asString(); | ||
405 | std::string templatename = sd["name"].asString(); | ||
406 | init(templatename, LLSD()); | ||
407 | // replace form with serialized version | ||
408 | mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"])); | ||
409 | } | ||
410 | |||
411 | |||
412 | LLSD LLNotification::asLLSD() | ||
413 | { | ||
414 | LLSD output; | ||
415 | output["name"] = mTemplatep->mName; | ||
416 | output["form"] = getForm()->asLLSD(); | ||
417 | output["substitutions"] = mSubstitutions; | ||
418 | output["payload"] = mPayload; | ||
419 | output["time"] = mTimestamp; | ||
420 | output["expiry"] = mExpiresAt; | ||
421 | output["priority"] = (S32)mPriority; | ||
422 | output["responseFunctor"] = mResponseFunctorName; | ||
423 | return output; | ||
424 | } | ||
425 | |||
426 | void LLNotification::update() | ||
427 | { | ||
428 | LLNotifications::instance().update(shared_from_this()); | ||
429 | } | ||
430 | |||
431 | void LLNotification::updateFrom(LLNotificationPtr other) | ||
432 | { | ||
433 | // can only update from the same notification type | ||
434 | if (mTemplatep != other->mTemplatep) return; | ||
435 | |||
436 | // NOTE: do NOT change the ID, since it is the key to | ||
437 | // this given instance, just update all the metadata | ||
438 | //mId = other->mId; | ||
439 | |||
440 | mPayload = other->mPayload; | ||
441 | mSubstitutions = other->mSubstitutions; | ||
442 | mTimestamp = other->mTimestamp; | ||
443 | mExpiresAt = other->mExpiresAt; | ||
444 | mCancelled = other->mCancelled; | ||
445 | mIgnored = other->mIgnored; | ||
446 | mPriority = other->mPriority; | ||
447 | mForm = other->mForm; | ||
448 | mResponseFunctorName = other->mResponseFunctorName; | ||
449 | mRespondedTo = other->mRespondedTo; | ||
450 | mTemporaryResponder = other->mTemporaryResponder; | ||
451 | |||
452 | update(); | ||
453 | } | ||
454 | |||
455 | const LLNotificationFormPtr LLNotification::getForm() | ||
456 | { | ||
457 | return mForm; | ||
458 | } | ||
459 | |||
460 | void LLNotification::cancel() | ||
461 | { | ||
462 | mCancelled = true; | ||
463 | } | ||
464 | |||
465 | LLSD LLNotification::getResponseTemplate(EResponseTemplateType type) | ||
466 | { | ||
467 | LLSD response = LLSD::emptyMap(); | ||
468 | for (S32 element_idx = 0; | ||
469 | element_idx < mForm->getNumElements(); | ||
470 | ++element_idx) | ||
471 | { | ||
472 | LLSD element = mForm->getElement(element_idx); | ||
473 | if (element.has("name")) | ||
474 | { | ||
475 | response[element["name"].asString()] = element["value"]; | ||
476 | } | ||
477 | |||
478 | if ((type == WITH_DEFAULT_BUTTON) | ||
479 | && element["default"].asBoolean()) | ||
480 | { | ||
481 | response[element["name"].asString()] = true; | ||
482 | } | ||
483 | } | ||
484 | return response; | ||
485 | } | ||
486 | |||
487 | //static | ||
488 | S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response) | ||
489 | { | ||
490 | LLNotificationForm form(notification["form"]); | ||
491 | |||
492 | for (S32 element_idx = 0; | ||
493 | element_idx < form.getNumElements(); | ||
494 | ++element_idx) | ||
495 | { | ||
496 | LLSD element = form.getElement(element_idx); | ||
497 | |||
498 | // only look at buttons | ||
499 | if (element["type"].asString() == "button" | ||
500 | && response[element["name"].asString()].asBoolean()) | ||
501 | { | ||
502 | return element["index"].asInteger(); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | return -1; | ||
507 | } | ||
508 | |||
509 | //static | ||
510 | std::string LLNotification::getSelectedOptionName(const LLSD& response) | ||
511 | { | ||
512 | for (LLSD::map_const_iterator response_it = response.beginMap(); | ||
513 | response_it != response.endMap(); | ||
514 | ++response_it) | ||
515 | { | ||
516 | if (response_it->second.isBoolean() && response_it->second.asBoolean()) | ||
517 | { | ||
518 | return response_it->first; | ||
519 | } | ||
520 | } | ||
521 | return ""; | ||
522 | } | ||
523 | |||
524 | |||
525 | void LLNotification::respond(const LLSD& response) | ||
526 | { | ||
527 | mRespondedTo = true; | ||
528 | LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName)(asLLSD(), response); | ||
529 | if (mTemporaryResponder) | ||
530 | { | ||
531 | LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); | ||
532 | mResponseFunctorName = ""; | ||
533 | mTemporaryResponder = false; | ||
534 | } | ||
535 | |||
536 | if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) | ||
537 | { | ||
538 | LLUI::sIgnoresGroup->setWarning(getName(), !mIgnored); | ||
539 | if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) | ||
540 | { | ||
541 | LLUI::sIgnoresGroup->setLLSD("Default" + getName(), response); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | update(); | ||
546 | } | ||
547 | |||
548 | void LLNotification::setIgnored(bool ignore) | ||
549 | { | ||
550 | mIgnored = ignore; | ||
551 | } | ||
552 | |||
553 | void LLNotification::setResponseFunctor(std::string const &responseFunctorName) | ||
554 | { | ||
555 | if (mTemporaryResponder) | ||
556 | // get rid of the old one | ||
557 | LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); | ||
558 | mResponseFunctorName = responseFunctorName; | ||
559 | mTemporaryResponder = false; | ||
560 | } | ||
561 | |||
562 | bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const | ||
563 | { | ||
564 | for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin(); | ||
565 | required_fields_it != required_fields.end(); | ||
566 | required_fields_it++) | ||
567 | { | ||
568 | std::string required_field_name = *required_fields_it; | ||
569 | if( ! getPayload().has(required_field_name)) | ||
570 | { | ||
571 | return false; // a required field was not found | ||
572 | } | ||
573 | } | ||
574 | return true; // all required fields were found | ||
575 | } | ||
576 | |||
577 | bool LLNotification::isEquivalentTo(LLNotificationPtr that) const | ||
578 | { | ||
579 | if (this->mTemplatep->mName != that->mTemplatep->mName) | ||
580 | { | ||
581 | return false; // must have the same template name or forget it | ||
582 | } | ||
583 | if (this->mTemplatep->mUnique) | ||
584 | { | ||
585 | // highlander bit sez there can only be one of these | ||
586 | return | ||
587 | this->payloadContainsAll(that->mTemplatep->mUniqueContext) && | ||
588 | that->payloadContainsAll(this->mTemplatep->mUniqueContext); | ||
589 | } | ||
590 | return false; | ||
591 | } | ||
592 | |||
593 | void LLNotification::init(const std::string& template_name, const LLSD& form_elements) | ||
594 | { | ||
595 | mTemplatep = LLNotifications::instance().getTemplate(template_name); | ||
596 | if (!mTemplatep) return; | ||
597 | |||
598 | // add default substitutions | ||
599 | // TODO: change this to read from the translatable strings file! | ||
600 | mSubstitutions["SECOND_LIFE"] = "Second Life"; | ||
601 | mSubstitutions["_URL"] = getURL(); | ||
602 | mSubstitutions["_NAME"] = template_name; | ||
603 | // TODO: something like this so that a missing alert is sensible: | ||
604 | //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); | ||
605 | |||
606 | mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); | ||
607 | mForm->append(form_elements); | ||
608 | |||
609 | // apply substitution to form labels | ||
610 | mForm->formatElements(mSubstitutions); | ||
611 | |||
612 | LLDate rightnow = LLDate::now(); | ||
613 | if (mTemplatep->mExpireSeconds) | ||
614 | { | ||
615 | mExpiresAt = LLDate(rightnow.secondsSinceEpoch() + mTemplatep->mExpireSeconds); | ||
616 | } | ||
617 | |||
618 | if (mPriority == NOTIFICATION_PRIORITY_UNSPECIFIED) | ||
619 | { | ||
620 | mPriority = mTemplatep->mPriority; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | std::string LLNotification::summarize() const | ||
625 | { | ||
626 | std::string s = "Notification("; | ||
627 | s += getName(); | ||
628 | s += ") : "; | ||
629 | s += mTemplatep ? mTemplatep->mMessage : ""; | ||
630 | // should also include timestamp and expiration time (but probably not payload) | ||
631 | return s; | ||
632 | } | ||
633 | |||
634 | //static | ||
635 | std::string LLNotification::format(const std::string& s, const LLSD& substitutions) | ||
636 | { | ||
637 | if (!substitutions.isMap()) | ||
638 | { | ||
639 | return s; | ||
640 | } | ||
641 | |||
642 | std::ostringstream output; | ||
643 | // match strings like [NAME] | ||
644 | const boost::regex key("\\[([0-9_A-Z]+)]"); | ||
645 | |||
646 | std::string::const_iterator start = s.begin(); | ||
647 | std::string::const_iterator end = s.end(); | ||
648 | boost::smatch match; | ||
649 | |||
650 | while (boost::regex_search(start, end, match, key, boost::match_default)) | ||
651 | { | ||
652 | bool found_replacement = false; | ||
653 | std::string replacement; | ||
654 | |||
655 | // see if we have a replacement for the bracketed string (without the brackets) | ||
656 | // test first using has() because if we just look up with operator[] we get back an | ||
657 | // empty string even if the value is missing. We want to distinguish between | ||
658 | // missing replacements and deliberately empty replacement strings. | ||
659 | if (substitutions.has(std::string(match[1].first, match[1].second))) | ||
660 | { | ||
661 | replacement = substitutions[std::string(match[1].first, match[1].second)].asString(); | ||
662 | found_replacement = true; | ||
663 | } | ||
664 | // if not, see if there's one WITH brackets | ||
665 | else if (substitutions.has(std::string(match[0].first, match[0].second))) | ||
666 | { | ||
667 | replacement = substitutions[std::string(match[0].first, match[0].second)].asString(); | ||
668 | found_replacement = true; | ||
669 | } | ||
670 | |||
671 | if (found_replacement) | ||
672 | { | ||
673 | // found a replacement | ||
674 | // "hello world" is output | ||
675 | output << std::string(start, match[0].first) << replacement; | ||
676 | } | ||
677 | else | ||
678 | { | ||
679 | // we had no replacement, so leave the string we searched for so that it gets noticed by QA | ||
680 | // "hello [NAME_NOT_FOUND]" is output | ||
681 | output << std::string(start, match[0].second); | ||
682 | } | ||
683 | |||
684 | // update search position | ||
685 | start = match[0].second; | ||
686 | } | ||
687 | // send the remainder of the string (with no further matches for bracketed names) | ||
688 | output << std::string(start, end); | ||
689 | return output.str(); | ||
690 | } | ||
691 | |||
692 | std::string LLNotification::getMessage() const | ||
693 | { | ||
694 | // all our callers cache this result, so it gives us more flexibility | ||
695 | // to do the substitution at call time rather than attempting to | ||
696 | // cache it in the notification | ||
697 | if (!mTemplatep) | ||
698 | return std::string(); | ||
699 | return format(mTemplatep->mMessage, mSubstitutions); | ||
700 | } | ||
701 | |||
702 | std::string LLNotification::getLabel() const | ||
703 | { | ||
704 | return (mTemplatep ? format(mTemplatep->mLabel, mSubstitutions) : ""); | ||
705 | } | ||
706 | |||
707 | |||
708 | |||
709 | // ========================================================= | ||
710 | // LLNotificationChannel implementation | ||
711 | // --- | ||
712 | void LLNotificationChannelBase::connectChanged(const LLStandardSignal::slot_type& slot) | ||
713 | { | ||
714 | // when someone wants to connect to a channel, we first throw them | ||
715 | // all of the notifications that are already in the channel | ||
716 | // we use a special signal called "load" in case the channel wants to care | ||
717 | // only about new notifications | ||
718 | for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) | ||
719 | { | ||
720 | slot.get_slot_function()(LLSD().insert("sigtype", "load").insert("id", (*it)->id())); | ||
721 | } | ||
722 | // and then connect the signal so that all future notifications will also be | ||
723 | // forwarded. | ||
724 | mChanged.connect(slot); | ||
725 | } | ||
726 | |||
727 | void LLNotificationChannelBase::connectPassedFilter(const LLStandardSignal::slot_type& slot) | ||
728 | { | ||
729 | // these two filters only fire for notifications added after the current one, because | ||
730 | // they don't participate in the hierarchy. | ||
731 | mPassedFilter.connect(slot); | ||
732 | } | ||
733 | |||
734 | void LLNotificationChannelBase::connectFailedFilter(const LLStandardSignal::slot_type& slot) | ||
735 | { | ||
736 | mFailedFilter.connect(slot); | ||
737 | } | ||
738 | |||
739 | // external call, conforms to our standard signature | ||
740 | bool LLNotificationChannelBase::updateItem(const LLSD& payload) | ||
741 | { | ||
742 | // first check to see if it's in the master list | ||
743 | LLNotificationPtr pNotification = LLNotifications::instance().find(payload["id"]); | ||
744 | if (!pNotification) | ||
745 | return false; // not found | ||
746 | |||
747 | return updateItem(payload, pNotification); | ||
748 | } | ||
749 | |||
750 | |||
751 | //FIX QUIT NOT WORKING | ||
752 | |||
753 | |||
754 | // internal call, for use in avoiding lookup | ||
755 | bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPtr pNotification) | ||
756 | { | ||
757 | std::string cmd = payload["sigtype"]; | ||
758 | LLNotificationSet::iterator foundItem = mItems.find(pNotification); | ||
759 | bool wasFound = (foundItem != mItems.end()); | ||
760 | bool passesFilter = mFilter(pNotification); | ||
761 | |||
762 | // first, we offer the result of the filter test to the simple | ||
763 | // signals for pass/fail. One of these is guaranteed to be called. | ||
764 | // If either signal returns true, the change processing is NOT performed | ||
765 | // (so don't return true unless you know what you're doing!) | ||
766 | bool abortProcessing = false; | ||
767 | if (passesFilter) | ||
768 | { | ||
769 | abortProcessing = mPassedFilter(payload); | ||
770 | } | ||
771 | else | ||
772 | { | ||
773 | abortProcessing = mFailedFilter(payload); | ||
774 | } | ||
775 | |||
776 | if (abortProcessing) | ||
777 | { | ||
778 | return true; | ||
779 | } | ||
780 | |||
781 | if (cmd == "load") | ||
782 | { | ||
783 | // should be no reason we'd ever get a load if we already have it | ||
784 | // if passes filter send a load message, else do nothing | ||
785 | assert(!wasFound); | ||
786 | if (passesFilter) | ||
787 | { | ||
788 | // not in our list, add it and say so | ||
789 | mItems.insert(pNotification); | ||
790 | abortProcessing = mChanged(payload); | ||
791 | onLoad(pNotification); | ||
792 | } | ||
793 | } | ||
794 | else if (cmd == "change") | ||
795 | { | ||
796 | // if it passes filter now and was found, we just send a change message | ||
797 | // if it passes filter now and wasn't found, we have to add it | ||
798 | // if it doesn't pass filter and wasn't found, we do nothing | ||
799 | // if it doesn't pass filter and was found, we need to delete it | ||
800 | if (passesFilter) | ||
801 | { | ||
802 | if (wasFound) | ||
803 | { | ||
804 | // it already existed, so this is a change | ||
805 | // since it changed in place, all we have to do is resend the signal | ||
806 | abortProcessing = mChanged(payload); | ||
807 | onChange(pNotification); | ||
808 | } | ||
809 | else | ||
810 | { | ||
811 | // not in our list, add it and say so | ||
812 | mItems.insert(pNotification); | ||
813 | // our payload is const, so make a copy before changing it | ||
814 | LLSD newpayload = payload; | ||
815 | newpayload["sigtype"] = "add"; | ||
816 | abortProcessing = mChanged(newpayload); | ||
817 | onChange(pNotification); | ||
818 | } | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | if (wasFound) | ||
823 | { | ||
824 | // it already existed, so this is a delete | ||
825 | mItems.erase(pNotification); | ||
826 | // our payload is const, so make a copy before changing it | ||
827 | LLSD newpayload = payload; | ||
828 | newpayload["sigtype"] = "delete"; | ||
829 | abortProcessing = mChanged(newpayload); | ||
830 | onChange(pNotification); | ||
831 | } | ||
832 | // didn't pass, not on our list, do nothing | ||
833 | } | ||
834 | } | ||
835 | else if (cmd == "add") | ||
836 | { | ||
837 | // should be no reason we'd ever get an add if we already have it | ||
838 | // if passes filter send an add message, else do nothing | ||
839 | assert(!wasFound); | ||
840 | if (passesFilter) | ||
841 | { | ||
842 | // not in our list, add it and say so | ||
843 | mItems.insert(pNotification); | ||
844 | abortProcessing = mChanged(payload); | ||
845 | onAdd(pNotification); | ||
846 | } | ||
847 | } | ||
848 | else if (cmd == "delete") | ||
849 | { | ||
850 | // if we have it in our list, pass on the delete, then delete it, else do nothing | ||
851 | if (wasFound) | ||
852 | { | ||
853 | abortProcessing = mChanged(payload); | ||
854 | mItems.erase(pNotification); | ||
855 | onDelete(pNotification); | ||
856 | } | ||
857 | } | ||
858 | return abortProcessing; | ||
859 | } | ||
860 | |||
861 | /* static */ | ||
862 | LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name, | ||
863 | const std::string& parent, | ||
864 | LLNotificationFilter filter, | ||
865 | LLNotificationComparator comparator) | ||
866 | { | ||
867 | // note: this is not a leak; notifications are self-registering. | ||
868 | // This factory helps to prevent excess deletions by making sure all smart | ||
869 | // pointers to notification channels come from the same source | ||
870 | new LLNotificationChannel(name, parent, filter, comparator); | ||
871 | return LLNotifications::instance().getChannel(name); | ||
872 | } | ||
873 | |||
874 | |||
875 | LLNotificationChannel::LLNotificationChannel(const std::string& name, | ||
876 | const std::string& parent, | ||
877 | LLNotificationFilter filter, | ||
878 | LLNotificationComparator comparator) : | ||
879 | LLNotificationChannelBase(filter, comparator), | ||
880 | mName(name), | ||
881 | mParent(parent) | ||
882 | { | ||
883 | // store myself in the channel map | ||
884 | LLNotifications::instance().addChannel(LLNotificationChannelPtr(this)); | ||
885 | // bind to notification broadcast | ||
886 | if (parent.empty()) | ||
887 | { | ||
888 | LLNotifications::instance().connectChanged( | ||
889 | boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); | ||
890 | } | ||
891 | else | ||
892 | { | ||
893 | LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); | ||
894 | LLStandardSignal::slot_type f = boost::bind(&LLNotificationChannelBase::updateItem, this, _1); | ||
895 | p->connectChanged(f); | ||
896 | } | ||
897 | } | ||
898 | |||
899 | |||
900 | void LLNotificationChannel::setComparator(LLNotificationComparator comparator) | ||
901 | { | ||
902 | mComparator = comparator; | ||
903 | LLNotificationSet s2(mComparator); | ||
904 | s2.insert(mItems.begin(), mItems.end()); | ||
905 | mItems.swap(s2); | ||
906 | |||
907 | // notify clients that we've been resorted | ||
908 | mChanged(LLSD().insert("sigtype", "sort")); | ||
909 | } | ||
910 | |||
911 | bool LLNotificationChannel::isEmpty() const | ||
912 | { | ||
913 | return mItems.empty(); | ||
914 | } | ||
915 | |||
916 | LLNotificationChannel::Iterator LLNotificationChannel::begin() | ||
917 | { | ||
918 | return mItems.begin(); | ||
919 | } | ||
920 | |||
921 | LLNotificationChannel::Iterator LLNotificationChannel::end() | ||
922 | { | ||
923 | return mItems.end(); | ||
924 | } | ||
925 | |||
926 | std::string LLNotificationChannel::summarize() | ||
927 | { | ||
928 | std::string s("Channel '"); | ||
929 | s += mName; | ||
930 | s += "'\n "; | ||
931 | for (LLNotificationChannel::Iterator it = begin(); it != end(); ++it) | ||
932 | { | ||
933 | s += (*it)->summarize(); | ||
934 | s += "\n "; | ||
935 | } | ||
936 | return s; | ||
937 | } | ||
938 | |||
939 | |||
940 | // --- | ||
941 | // END OF LLNotificationChannel implementation | ||
942 | // ========================================================= | ||
943 | |||
944 | |||
945 | // ========================================================= | ||
946 | // LLNotifications implementation | ||
947 | // --- | ||
948 | LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything, | ||
949 | LLNotificationComparators::orderByUUID()) | ||
950 | { | ||
951 | } | ||
952 | |||
953 | |||
954 | // The expiration channel gets all notifications that are cancelled | ||
955 | bool LLNotifications::expirationFilter(LLNotificationPtr pNotification) | ||
956 | { | ||
957 | return pNotification->isCancelled() || pNotification->isRespondedTo(); | ||
958 | } | ||
959 | |||
960 | bool LLNotifications::expirationHandler(const LLSD& payload) | ||
961 | { | ||
962 | if (payload["sigtype"].asString() != "delete") | ||
963 | { | ||
964 | // anything added to this channel actually should be deleted from the master | ||
965 | cancel(find(payload["id"])); | ||
966 | return true; // don't process this item any further | ||
967 | } | ||
968 | return false; | ||
969 | } | ||
970 | |||
971 | bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) | ||
972 | { | ||
973 | if (!pNotif->hasUniquenessConstraints()) | ||
974 | { | ||
975 | return true; | ||
976 | } | ||
977 | |||
978 | // checks against existing unique notifications | ||
979 | for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); | ||
980 | existing_it != mUniqueNotifications.end(); | ||
981 | ++existing_it) | ||
982 | { | ||
983 | LLNotificationPtr existing_notification = existing_it->second; | ||
984 | if (pNotif != existing_notification | ||
985 | && pNotif->isEquivalentTo(existing_notification)) | ||
986 | { | ||
987 | return false; | ||
988 | } | ||
989 | } | ||
990 | |||
991 | return true; | ||
992 | } | ||
993 | |||
994 | bool LLNotifications::uniqueHandler(const LLSD& payload) | ||
995 | { | ||
996 | LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); | ||
997 | if (pNotif && pNotif->hasUniquenessConstraints()) | ||
998 | { | ||
999 | if (payload["sigtype"].asString() == "add") | ||
1000 | { | ||
1001 | // not a duplicate according to uniqueness criteria, so we keep it | ||
1002 | // and store it for future uniqueness checks | ||
1003 | mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); | ||
1004 | } | ||
1005 | else if (payload["sigtype"].asString() == "delete") | ||
1006 | { | ||
1007 | mUniqueNotifications.erase(pNotif->getName()); | ||
1008 | } | ||
1009 | } | ||
1010 | |||
1011 | return false; | ||
1012 | } | ||
1013 | |||
1014 | bool LLNotifications::failedUniquenessTest(const LLSD& payload) | ||
1015 | { | ||
1016 | LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); | ||
1017 | |||
1018 | if (!pNotif || !pNotif->hasUniquenessConstraints()) | ||
1019 | { | ||
1020 | return false; | ||
1021 | } | ||
1022 | |||
1023 | // checks against existing unique notifications | ||
1024 | for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); | ||
1025 | existing_it != mUniqueNotifications.end(); | ||
1026 | ++existing_it) | ||
1027 | { | ||
1028 | LLNotificationPtr existing_notification = existing_it->second; | ||
1029 | if (pNotif != existing_notification | ||
1030 | && pNotif->isEquivalentTo(existing_notification)) | ||
1031 | { | ||
1032 | // copy notification instance data over to oldest instance | ||
1033 | // of this unique notification and update it | ||
1034 | existing_notification->updateFrom(pNotif); | ||
1035 | // then delete the new one | ||
1036 | pNotif->cancel(); | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | return false; | ||
1041 | } | ||
1042 | |||
1043 | |||
1044 | void LLNotifications::addChannel(LLNotificationChannelPtr pChan) | ||
1045 | { | ||
1046 | mChannels[pChan->getName()] = pChan; | ||
1047 | } | ||
1048 | |||
1049 | LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName) | ||
1050 | { | ||
1051 | ChannelMap::iterator p = mChannels.find(channelName); | ||
1052 | if(p == mChannels.end()) | ||
1053 | { | ||
1054 | llerrs << "Did not find channel named " << channelName << llendl; | ||
1055 | } | ||
1056 | return p->second; | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | // this function is called once at construction time, after the object is constructed. | ||
1061 | void LLNotifications::initSingleton() | ||
1062 | { | ||
1063 | loadTemplates(); | ||
1064 | createDefaultChannels(); | ||
1065 | } | ||
1066 | |||
1067 | void LLNotifications::createDefaultChannels() | ||
1068 | { | ||
1069 | // now construct the various channels AFTER loading the notifications, | ||
1070 | // because the history channel is going to rewrite the stored notifications file | ||
1071 | LLNotificationChannel::buildChannel("Expiration", "", | ||
1072 | boost::bind(&LLNotifications::expirationFilter, this, _1)); | ||
1073 | LLNotificationChannel::buildChannel("Unexpired", "", | ||
1074 | !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind | ||
1075 | LLNotificationChannel::buildChannel("Unique", "Unexpired", | ||
1076 | boost::bind(&LLNotifications::uniqueFilter, this, _1)); | ||
1077 | LLNotificationChannel::buildChannel("Ignore", "Unique", | ||
1078 | filterIgnoredNotifications); | ||
1079 | LLNotificationChannel::buildChannel("Visible", "Ignore", | ||
1080 | &LLNotificationFilters::includeEverything); | ||
1081 | |||
1082 | // create special history channel | ||
1083 | //std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" ); | ||
1084 | // use ^^^ when done debugging notifications serialization | ||
1085 | std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_USER_SETTINGS, "open_notifications.xml" ); | ||
1086 | // this isn't a leak, don't worry about the empty "new" | ||
1087 | new LLNotificationHistoryChannel(notifications_log_file); | ||
1088 | |||
1089 | // connect action methods to these channels | ||
1090 | LLNotifications::instance().getChannel("Expiration")-> | ||
1091 | connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); | ||
1092 | LLNotifications::instance().getChannel("Unique")-> | ||
1093 | connectChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); | ||
1094 | LLNotifications::instance().getChannel("Unique")-> | ||
1095 | connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); | ||
1096 | LLNotifications::instance().getChannel("Ignore")-> | ||
1097 | connectFailedFilter(&handleIgnoredNotification); | ||
1098 | } | ||
1099 | |||
1100 | static std::string sStringSkipNextTime("Skip this dialog next time"); | ||
1101 | static std::string sStringAlwaysChoose("Always choose this option"); | ||
1102 | |||
1103 | bool LLNotifications::addTemplate(const std::string &name, | ||
1104 | LLNotificationTemplatePtr theTemplate) | ||
1105 | { | ||
1106 | if (mTemplates.count(name)) | ||
1107 | { | ||
1108 | llwarns << "LLNotifications -- attempted to add template '" << name << "' twice." << llendl; | ||
1109 | return false; | ||
1110 | } | ||
1111 | mTemplates[name] = theTemplate; | ||
1112 | return true; | ||
1113 | } | ||
1114 | |||
1115 | LLNotificationTemplatePtr LLNotifications::getTemplate(const std::string& name) | ||
1116 | { | ||
1117 | if (mTemplates.count(name)) | ||
1118 | { | ||
1119 | return mTemplates[name]; | ||
1120 | } | ||
1121 | else | ||
1122 | { | ||
1123 | return mTemplates["MissingAlert"]; | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | bool LLNotifications::templateExists(const std::string& name) | ||
1128 | { | ||
1129 | return (mTemplates.count(name) != 0); | ||
1130 | } | ||
1131 | |||
1132 | void LLNotifications::clearTemplates() | ||
1133 | { | ||
1134 | mTemplates.clear(); | ||
1135 | } | ||
1136 | |||
1137 | void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option) | ||
1138 | { | ||
1139 | LLNotificationPtr temp_notify(new LLNotification(params)); | ||
1140 | LLSD response = temp_notify->getResponseTemplate(); | ||
1141 | LLSD selected_item = temp_notify->getForm()->getElement(option); | ||
1142 | |||
1143 | if (selected_item.isUndefined()) | ||
1144 | { | ||
1145 | llwarns << "Invalid option" << option << " for notification " << (std::string)params.name << llendl; | ||
1146 | return; | ||
1147 | } | ||
1148 | response[selected_item["name"].asString()] = true; | ||
1149 | |||
1150 | temp_notify->respond(response); | ||
1151 | } | ||
1152 | |||
1153 | LLNotifications::TemplateNames LLNotifications::getTemplateNames() const | ||
1154 | { | ||
1155 | TemplateNames names; | ||
1156 | for (TemplateMap::const_iterator it = mTemplates.begin(); it != mTemplates.end(); ++it) | ||
1157 | { | ||
1158 | names.push_back(it->first); | ||
1159 | } | ||
1160 | return names; | ||
1161 | } | ||
1162 | |||
1163 | typedef std::map<std::string, std::string> StringMap; | ||
1164 | void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements) | ||
1165 | { | ||
1166 | //llwarns << "replaceSubstitutionStrings" << llendl; | ||
1167 | // walk the list of attributes looking for replacements | ||
1168 | for (LLXMLAttribList::iterator it=node->mAttributes.begin(); | ||
1169 | it != node->mAttributes.end(); ++it) | ||
1170 | { | ||
1171 | std::string value = it->second->getValue(); | ||
1172 | if (value[0] == '$') | ||
1173 | { | ||
1174 | value.erase(0, 1); // trim off the $ | ||
1175 | std::string replacement; | ||
1176 | StringMap::const_iterator found = replacements.find(value); | ||
1177 | if (found != replacements.end()) | ||
1178 | { | ||
1179 | replacement = found->second; | ||
1180 | //llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl; | ||
1181 | |||
1182 | it->second->setValue(replacement); | ||
1183 | } | ||
1184 | else | ||
1185 | { | ||
1186 | llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl; | ||
1187 | } | ||
1188 | } | ||
1189 | } | ||
1190 | |||
1191 | // now walk the list of children and call this recursively. | ||
1192 | for (LLXMLNodePtr child = node->getFirstChild(); | ||
1193 | child.notNull(); child = child->getNextSibling()) | ||
1194 | { | ||
1195 | replaceSubstitutionStrings(child, replacements); | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | // private to this file | ||
1200 | // returns true if the template request was invalid and there's nothing else we | ||
1201 | // can do with this node, false if you should keep processing (it may have | ||
1202 | // replaced the contents of the node referred to) | ||
1203 | LLXMLNodePtr LLNotifications::checkForXMLTemplate(LLXMLNodePtr item) | ||
1204 | { | ||
1205 | if (item->hasName("usetemplate")) | ||
1206 | { | ||
1207 | std::string replacementName; | ||
1208 | if (item->getAttributeString("name", replacementName)) | ||
1209 | { | ||
1210 | StringMap replacements; | ||
1211 | for (LLXMLAttribList::const_iterator it=item->mAttributes.begin(); | ||
1212 | it != item->mAttributes.end(); ++it) | ||
1213 | { | ||
1214 | replacements[it->second->getName()->mString] = it->second->getValue(); | ||
1215 | } | ||
1216 | if (mXmlTemplates.count(replacementName)) | ||
1217 | { | ||
1218 | item=LLXMLNode::replaceNode(item, mXmlTemplates[replacementName]); | ||
1219 | |||
1220 | // walk the nodes looking for $(substitution) here and replace | ||
1221 | replaceSubstitutionStrings(item, replacements); | ||
1222 | } | ||
1223 | else | ||
1224 | { | ||
1225 | llwarns << "XML template lookup failure on '" << replacementName << "' " << llendl; | ||
1226 | } | ||
1227 | } | ||
1228 | } | ||
1229 | return item; | ||
1230 | } | ||
1231 | |||
1232 | bool LLNotifications::loadTemplates() | ||
1233 | { | ||
1234 | const std::string xml_filename = "notifications.xml"; | ||
1235 | LLXMLNodePtr root; | ||
1236 | |||
1237 | BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); | ||
1238 | |||
1239 | if (!success || root.isNull() || !root->hasName( "notifications" )) | ||
1240 | { | ||
1241 | llerrs << "Problem reading UI Notifications file: " << xml_filename << llendl; | ||
1242 | return false; | ||
1243 | } | ||
1244 | |||
1245 | clearTemplates(); | ||
1246 | |||
1247 | for (LLXMLNodePtr item = root->getFirstChild(); | ||
1248 | item.notNull(); item = item->getNextSibling()) | ||
1249 | { | ||
1250 | // we do this FIRST so that item can be changed if we | ||
1251 | // encounter a usetemplate -- we just replace the | ||
1252 | // current xml node and keep processing | ||
1253 | item = checkForXMLTemplate(item); | ||
1254 | |||
1255 | if (item->hasName("global")) | ||
1256 | { | ||
1257 | std::string global_name; | ||
1258 | if (item->getAttributeString("name", global_name)) | ||
1259 | { | ||
1260 | mGlobalStrings[global_name] = item->getTextContents(); | ||
1261 | } | ||
1262 | continue; | ||
1263 | } | ||
1264 | |||
1265 | if (item->hasName("template")) | ||
1266 | { | ||
1267 | // store an xml template; templates must have a single node (can contain | ||
1268 | // other nodes) | ||
1269 | std::string name; | ||
1270 | item->getAttributeString("name", name); | ||
1271 | LLXMLNodePtr ptr = item->getFirstChild(); | ||
1272 | mXmlTemplates[name] = ptr; | ||
1273 | continue; | ||
1274 | } | ||
1275 | |||
1276 | if (!item->hasName("notification")) | ||
1277 | { | ||
1278 | llwarns << "Unexpected entity " << item->getName()->mString << | ||
1279 | " found in " << xml_filename << llendl; | ||
1280 | continue; | ||
1281 | } | ||
1282 | |||
1283 | // now we know we have a notification entry, so let's build it | ||
1284 | LLNotificationTemplatePtr pTemplate(new LLNotificationTemplate()); | ||
1285 | |||
1286 | if (!item->getAttributeString("name", pTemplate->mName)) | ||
1287 | { | ||
1288 | llwarns << "Unable to parse notification with no name" << llendl; | ||
1289 | continue; | ||
1290 | } | ||
1291 | |||
1292 | //llinfos << "Parsing " << pTemplate->mName << llendl; | ||
1293 | |||
1294 | pTemplate->mMessage = item->getTextContents(); | ||
1295 | pTemplate->mDefaultFunctor = pTemplate->mName; | ||
1296 | item->getAttributeString("type", pTemplate->mType); | ||
1297 | item->getAttributeString("icon", pTemplate->mIcon); | ||
1298 | item->getAttributeString("label", pTemplate->mLabel); | ||
1299 | item->getAttributeU32("duration", pTemplate->mExpireSeconds); | ||
1300 | item->getAttributeU32("expireOption", pTemplate->mExpireOption); | ||
1301 | |||
1302 | std::string priority; | ||
1303 | item->getAttributeString("priority", priority); | ||
1304 | pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL; | ||
1305 | if (!priority.empty()) | ||
1306 | { | ||
1307 | if (priority == "low") pTemplate->mPriority = NOTIFICATION_PRIORITY_LOW; | ||
1308 | if (priority == "normal") pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL; | ||
1309 | if (priority == "high") pTemplate->mPriority = NOTIFICATION_PRIORITY_HIGH; | ||
1310 | if (priority == "critical") pTemplate->mPriority = NOTIFICATION_PRIORITY_CRITICAL; | ||
1311 | } | ||
1312 | |||
1313 | item->getAttributeString("functor", pTemplate->mDefaultFunctor); | ||
1314 | |||
1315 | BOOL persist = false; | ||
1316 | item->getAttributeBOOL("persist", persist); | ||
1317 | pTemplate->mPersist = persist; | ||
1318 | |||
1319 | std::string sound; | ||
1320 | item->getAttributeString("sound", sound); | ||
1321 | if (!sound.empty()) | ||
1322 | { | ||
1323 | // TODO: test for bad sound effect name / missing effect | ||
1324 | pTemplate->mSoundEffect = LLUUID(LLUI::sConfigGroup->getString(sound.c_str())); | ||
1325 | } | ||
1326 | |||
1327 | for (LLXMLNodePtr child = item->getFirstChild(); | ||
1328 | !child.isNull(); child = child->getNextSibling()) | ||
1329 | { | ||
1330 | child = checkForXMLTemplate(child); | ||
1331 | |||
1332 | // <url> | ||
1333 | if (child->hasName("url")) | ||
1334 | { | ||
1335 | pTemplate->mURL = child->getTextContents(); | ||
1336 | child->getAttributeU32("option", pTemplate->mURLOption); | ||
1337 | } | ||
1338 | |||
1339 | if (child->hasName("unique")) | ||
1340 | { | ||
1341 | pTemplate->mUnique = true; | ||
1342 | for (LLXMLNodePtr formitem = child->getFirstChild(); | ||
1343 | !formitem.isNull(); formitem = formitem->getNextSibling()) | ||
1344 | { | ||
1345 | if (formitem->hasName("context")) | ||
1346 | { | ||
1347 | std::string key; | ||
1348 | formitem->getAttributeString("key", key); | ||
1349 | pTemplate->mUniqueContext.push_back(key); | ||
1350 | //llwarns << "adding " << key << " to unique context" << llendl; | ||
1351 | } | ||
1352 | else | ||
1353 | { | ||
1354 | llwarns << "'unique' has unrecognized subelement " | ||
1355 | << formitem->getName()->mString << llendl; | ||
1356 | } | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | // <form> | ||
1361 | if (child->hasName("form")) | ||
1362 | { | ||
1363 | pTemplate->mForm = LLNotificationFormPtr(new LLNotificationForm(pTemplate->mName, child)); | ||
1364 | } | ||
1365 | } | ||
1366 | addTemplate(pTemplate->mName, pTemplate); | ||
1367 | } | ||
1368 | |||
1369 | //std::ostringstream ostream; | ||
1370 | //root->writeToOstream(ostream, "\n "); | ||
1371 | //llwarns << ostream.str() << llendl; | ||
1372 | |||
1373 | return true; | ||
1374 | } | ||
1375 | |||
1376 | // we provide a couple of simple add notification functions so that it's reasonable to create notifications in one line | ||
1377 | LLNotificationPtr LLNotifications::add(const std::string& name, | ||
1378 | const LLSD& substitutions, | ||
1379 | const LLSD& payload) | ||
1380 | { | ||
1381 | return add(LLNotification::Params(name).substitutions(substitutions).payload(payload)); | ||
1382 | } | ||
1383 | |||
1384 | LLNotificationPtr LLNotifications::add(const std::string& name, | ||
1385 | const LLSD& substitutions, | ||
1386 | const LLSD& payload, | ||
1387 | const std::string& functor_name) | ||
1388 | { | ||
1389 | return add(LLNotification::Params(name).substitutions(substitutions).payload(payload).functor_name(functor_name)); | ||
1390 | } | ||
1391 | |||
1392 | LLNotificationPtr LLNotifications::add(const std::string& name, | ||
1393 | const LLSD& substitutions, | ||
1394 | const LLSD& payload, | ||
1395 | LLNotificationFunctorRegistry::ResponseFunctor functor) | ||
1396 | { | ||
1397 | return add(LLNotification::Params(name).substitutions(substitutions).payload(payload).functor(functor)); | ||
1398 | } | ||
1399 | |||
1400 | // generalized add function that takes a parameter block object for more complex instantiations | ||
1401 | LLNotificationPtr LLNotifications::add(const LLNotification::Params& p) | ||
1402 | { | ||
1403 | LLNotificationPtr pNotif(new LLNotification(p)); | ||
1404 | add(pNotif); | ||
1405 | return pNotif; | ||
1406 | } | ||
1407 | |||
1408 | |||
1409 | void LLNotifications::add(const LLNotificationPtr pNotif) | ||
1410 | { | ||
1411 | // first see if we already have it -- if so, that's a problem | ||
1412 | LLNotificationSet::iterator it=mItems.find(pNotif); | ||
1413 | if (it != mItems.end()) | ||
1414 | { | ||
1415 | llerrs << "Notification added a second time to the master notification channel." << llendl; | ||
1416 | } | ||
1417 | |||
1418 | updateItem(LLSD().insert("sigtype", "add").insert("id", pNotif->id()), pNotif); | ||
1419 | } | ||
1420 | |||
1421 | void LLNotifications::cancel(LLNotificationPtr pNotif) | ||
1422 | { | ||
1423 | LLNotificationSet::iterator it=mItems.find(pNotif); | ||
1424 | if (it == mItems.end()) | ||
1425 | { | ||
1426 | llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl; | ||
1427 | } | ||
1428 | updateItem(LLSD().insert("sigtype", "delete").insert("id", pNotif->id()), pNotif); | ||
1429 | pNotif->cancel(); | ||
1430 | } | ||
1431 | |||
1432 | void LLNotifications::update(const LLNotificationPtr pNotif) | ||
1433 | { | ||
1434 | LLNotificationSet::iterator it=mItems.find(pNotif); | ||
1435 | if (it != mItems.end()) | ||
1436 | { | ||
1437 | updateItem(LLSD().insert("sigtype", "change").insert("id", pNotif->id()), pNotif); | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | |||
1442 | LLNotificationPtr LLNotifications::find(LLUUID uuid) | ||
1443 | { | ||
1444 | LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid)); | ||
1445 | LLNotificationSet::iterator it=mItems.find(target); | ||
1446 | if (it == mItems.end()) | ||
1447 | { | ||
1448 | llwarns << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << llendl; | ||
1449 | return LLNotificationPtr((LLNotification*)NULL); | ||
1450 | } | ||
1451 | else | ||
1452 | { | ||
1453 | return *it; | ||
1454 | } | ||
1455 | } | ||
1456 | |||
1457 | void LLNotifications::forEachNotification(NotificationProcess process) | ||
1458 | { | ||
1459 | std::for_each(mItems.begin(), mItems.end(), process); | ||
1460 | } | ||
1461 | |||
1462 | std::string LLNotifications::getGlobalString(const std::string& key) const | ||
1463 | { | ||
1464 | GlobalStringMap::const_iterator it = mGlobalStrings.find(key); | ||
1465 | if (it != mGlobalStrings.end()) | ||
1466 | { | ||
1467 | return it->second; | ||
1468 | } | ||
1469 | else | ||
1470 | { | ||
1471 | // if we don't have the key as a global, return the key itself so that the error | ||
1472 | // is self-diagnosing. | ||
1473 | return key; | ||
1474 | } | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | // --- | ||
1479 | // END OF LLNotifications implementation | ||
1480 | // ========================================================= | ||
1481 | |||
1482 | std::ostream& operator<<(std::ostream& s, const LLNotification& notification) | ||
1483 | { | ||
1484 | s << notification.summarize(); | ||
1485 | return s; | ||
1486 | } | ||
1487 | |||
diff --git a/linden/indra/llui/llnotifications.h b/linden/indra/llui/llnotifications.h new file mode 100644 index 0000000..bb37912 --- /dev/null +++ b/linden/indra/llui/llnotifications.h | |||
@@ -0,0 +1,903 @@ | |||
1 | /** | ||
2 | * @file llnotifications.h | ||
3 | * @brief Non-UI manager and support for keeping a prioritized list of notifications | ||
4 | * @author Q (with assistance from Richard and Coco) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
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 | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LLNOTIFICATIONS_H | ||
35 | #define LL_LLNOTIFICATIONS_H | ||
36 | |||
37 | /** | ||
38 | * This system is intended to provide a singleton mechanism for adding | ||
39 | * notifications to one of an arbitrary set of event channels. | ||
40 | * | ||
41 | * Controlling JIRA: DEV-9061 | ||
42 | * | ||
43 | * Every notification has (see code for full list): | ||
44 | * - a textual name, which is used to look up its template in the XML files | ||
45 | * - a payload, which is a block of LLSD | ||
46 | * - a channel, which is normally extracted from the XML files but | ||
47 | * can be overridden. | ||
48 | * - a timestamp, used to order the notifications | ||
49 | * - expiration time -- if nonzero, specifies a time after which the | ||
50 | * notification will no longer be valid. | ||
51 | * - a callback name and a couple of status bits related to callbacks (see below) | ||
52 | * | ||
53 | * There is a management class called LLNotifications, which is an LLSingleton. | ||
54 | * The class maintains a collection of all of the notifications received | ||
55 | * or processed during this session, and also manages the persistence | ||
56 | * of those notifications that must be persisted. | ||
57 | * | ||
58 | * We also have Channels. A channel is a view on a collection of notifications; | ||
59 | * The collection is defined by a filter function that controls which | ||
60 | * notifications are in the channel, and its ordering is controlled by | ||
61 | * a comparator. | ||
62 | * | ||
63 | * There is a hierarchy of channels; notifications flow down from | ||
64 | * the management class (LLNotifications, which itself inherits from | ||
65 | * The channel base class) to the individual channels. | ||
66 | * Any change to notifications (add, delete, modify) is | ||
67 | * automatically propagated through the channel hierarchy. | ||
68 | * | ||
69 | * We provide methods for adding a new notification, for removing | ||
70 | * one, and for managing channels. Channels are relatively cheap to construct | ||
71 | * and maintain, so in general, human interfaces should use channels to | ||
72 | * select and manage their lists of notifications. | ||
73 | * | ||
74 | * We also maintain a collection of templates that are loaded from the | ||
75 | * XML file of template translations. The system supports substitution | ||
76 | * of named variables from the payload into the XML file. | ||
77 | * | ||
78 | * By default, only the "unknown message" template is built into the system. | ||
79 | * It is not an error to add a notification that's not found in the | ||
80 | * template system, but it is logged. | ||
81 | * | ||
82 | */ | ||
83 | |||
84 | #include <string> | ||
85 | #include <list> | ||
86 | #include <vector> | ||
87 | #include <map> | ||
88 | #include <set> | ||
89 | #include <iomanip> | ||
90 | #include <sstream> | ||
91 | |||
92 | #include <boost/utility.hpp> | ||
93 | #include <boost/shared_ptr.hpp> | ||
94 | #include <boost/signal.hpp> | ||
95 | #include <boost/type_traits.hpp> | ||
96 | |||
97 | // we want to minimize external dependencies, but this one is important | ||
98 | #include "llsd.h" | ||
99 | |||
100 | // and we need this to manage the notification callbacks | ||
101 | #include "llfunctorregistry.h" | ||
102 | #include "llui.h" | ||
103 | |||
104 | class LLNotification; | ||
105 | typedef boost::shared_ptr<LLNotification> LLNotificationPtr; | ||
106 | |||
107 | /***************************************************************************** | ||
108 | * Signal and handler declarations | ||
109 | * Using a single handler signature means that we can have a common handler | ||
110 | * type, rather than needing a distinct one for each different handler. | ||
111 | *****************************************************************************/ | ||
112 | |||
113 | /** | ||
114 | * A boost::signals Combiner that stops the first time a handler returns true | ||
115 | * We need this because we want to have our handlers return bool, so that | ||
116 | * we have the option to cause a handler to stop further processing. The | ||
117 | * default handler fails when the signal returns a value but has no slots. | ||
118 | */ | ||
119 | struct LLStopWhenHandled | ||
120 | { | ||
121 | typedef bool result_type; | ||
122 | |||
123 | template<typename InputIterator> | ||
124 | result_type operator()(InputIterator first, InputIterator last) const | ||
125 | { | ||
126 | for (InputIterator si = first; si != last; ++si) | ||
127 | { | ||
128 | if (*si) | ||
129 | { | ||
130 | return true; | ||
131 | } | ||
132 | } | ||
133 | return false; | ||
134 | } | ||
135 | }; | ||
136 | |||
137 | |||
138 | typedef enum e_notification_priority | ||
139 | { | ||
140 | NOTIFICATION_PRIORITY_UNSPECIFIED, | ||
141 | NOTIFICATION_PRIORITY_LOW, | ||
142 | NOTIFICATION_PRIORITY_NORMAL, | ||
143 | NOTIFICATION_PRIORITY_HIGH, | ||
144 | NOTIFICATION_PRIORITY_CRITICAL | ||
145 | } ENotificationPriority; | ||
146 | |||
147 | /** | ||
148 | * We want to have a standard signature for all signals; this way, | ||
149 | * we can easily document a protocol for communicating across | ||
150 | * dlls and into scripting languages someday. | ||
151 | * we want to return a bool to indicate whether the signal has been | ||
152 | * handled and should NOT be passed on to other listeners. | ||
153 | * Return true to stop further handling of the signal, and false | ||
154 | * to continue. | ||
155 | * We take an LLSD because this way the contents of the signal | ||
156 | * are independent of the API used to communicate it. | ||
157 | * It is const ref because then there's low cost to pass it; | ||
158 | * if you only need to inspect it, it's very cheap. | ||
159 | */ | ||
160 | |||
161 | typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder; | ||
162 | |||
163 | typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry; | ||
164 | typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration; | ||
165 | |||
166 | typedef boost::signal<bool(const LLSD&), LLStopWhenHandled> LLStandardSignal; | ||
167 | |||
168 | // context data that can be looked up via a notification's payload by the display logic | ||
169 | // derive from this class to implement specific contexts | ||
170 | class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID> | ||
171 | { | ||
172 | public: | ||
173 | LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID()) | ||
174 | { | ||
175 | } | ||
176 | |||
177 | virtual ~LLNotificationContext() {} | ||
178 | |||
179 | LLSD asLLSD() const | ||
180 | { | ||
181 | return getKey(); | ||
182 | } | ||
183 | |||
184 | private: | ||
185 | |||
186 | }; | ||
187 | |||
188 | // Contains notification form data, such as buttons and text fields along with | ||
189 | // manipulator functions | ||
190 | class LLNotificationForm | ||
191 | { | ||
192 | LOG_CLASS(LLNotificationForm); | ||
193 | |||
194 | public: | ||
195 | typedef enum e_ignore_type | ||
196 | { | ||
197 | IGNORE_NO, | ||
198 | IGNORE_WITH_DEFAULT_RESPONSE, | ||
199 | IGNORE_WITH_LAST_RESPONSE, | ||
200 | IGNORE_SHOW_AGAIN | ||
201 | } EIgnoreType; | ||
202 | |||
203 | LLNotificationForm(); | ||
204 | LLNotificationForm(const LLSD& sd); | ||
205 | LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node); | ||
206 | |||
207 | LLSD asLLSD() const; | ||
208 | |||
209 | S32 getNumElements() { return mFormData.size(); } | ||
210 | LLSD getElement(S32 index) { return mFormData.get(index); } | ||
211 | LLSD getElement(const std::string& element_name); | ||
212 | bool hasElement(const std::string& element_name); | ||
213 | void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD()); | ||
214 | void formatElements(const LLSD& substitutions); | ||
215 | // appends form elements from another form serialized as LLSD | ||
216 | void append(const LLSD& sub_form); | ||
217 | std::string getDefaultOption(); | ||
218 | |||
219 | EIgnoreType getIgnoreType() { return mIgnore; } | ||
220 | std::string getIgnoreMessage() { return mIgnoreMsg; } | ||
221 | |||
222 | private: | ||
223 | LLSD mFormData; | ||
224 | EIgnoreType mIgnore; | ||
225 | std::string mIgnoreMsg; | ||
226 | }; | ||
227 | |||
228 | typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr; | ||
229 | |||
230 | // This is the class of object read from the XML file (notifications.xml, | ||
231 | // from the appropriate local language directory). | ||
232 | struct LLNotificationTemplate | ||
233 | { | ||
234 | LLNotificationTemplate(); | ||
235 | // the name of the notification -- the key used to identify it | ||
236 | // Ideally, the key should follow variable naming rules | ||
237 | // (no spaces or punctuation). | ||
238 | std::string mName; | ||
239 | // The type of the notification | ||
240 | // used to control which queue it's stored in | ||
241 | std::string mType; | ||
242 | // The text used to display the notification. Replaceable parameters | ||
243 | // are enclosed in square brackets like this []. | ||
244 | std::string mMessage; | ||
245 | // The label for the notification; used for | ||
246 | // certain classes of notification (those with a window and a window title). | ||
247 | // Also used when a notification pops up underneath the current one. | ||
248 | // Replaceable parameters can be used in the label. | ||
249 | std::string mLabel; | ||
250 | // The name of the icon image. This should include an extension. | ||
251 | std::string mIcon; | ||
252 | // This is the Highlander bit -- "There Can Be Only One" | ||
253 | // An outstanding notification with this bit set | ||
254 | // is updated by an incoming notification with the same name, | ||
255 | // rather than creating a new entry in the queue. | ||
256 | // (used for things like progress indications, or repeating warnings | ||
257 | // like "the grid is going down in N minutes") | ||
258 | bool mUnique; | ||
259 | // if we want to be unique only if a certain part of the payload is constant | ||
260 | // specify the field names for the payload. The notification will only be | ||
261 | // combined if all of the fields named in the context are identical in the | ||
262 | // new and the old notification; otherwise, the notification will be | ||
263 | // duplicated. This is to support suppressing duplicate offers from the same | ||
264 | // sender but still differentiating different offers. Example: Invitation to | ||
265 | // conference chat. | ||
266 | std::vector<std::string> mUniqueContext; | ||
267 | // If this notification expires automatically, this value will be | ||
268 | // nonzero, and indicates the number of seconds for which the notification | ||
269 | // will be valid (a teleport offer, for example, might be valid for | ||
270 | // 300 seconds). | ||
271 | U32 mExpireSeconds; | ||
272 | // if the offer expires, one of the options is chosen automatically | ||
273 | // based on its "value" parameter. This controls which one. | ||
274 | // If expireSeconds is specified, expireOption should also be specified. | ||
275 | U32 mExpireOption; | ||
276 | // if the notification contains a url, it's stored here (and replaced | ||
277 | // into the message where [_URL] is found) | ||
278 | std::string mURL; | ||
279 | // if there's a URL in the message, this controls which option visits | ||
280 | // that URL. Obsolete this and eliminate the buttons for affected | ||
281 | // messages when we allow clickable URLs in the UI | ||
282 | U32 mURLOption; | ||
283 | // does this notification persist across sessions? if so, it will be | ||
284 | // serialized to disk on first receipt and read on startup | ||
285 | bool mPersist; | ||
286 | // This is the name of the default functor, if present, to be | ||
287 | // used for the notification's callback. It is optional, and used only if | ||
288 | // the notification is constructed without an identified functor. | ||
289 | std::string mDefaultFunctor; | ||
290 | // The form data associated with a given notification (buttons, text boxes, etc) | ||
291 | LLNotificationFormPtr mForm; | ||
292 | // default priority for notifications of this type | ||
293 | ENotificationPriority mPriority; | ||
294 | // UUID of the audio file to be played when this notification arrives | ||
295 | // this is loaded as a name, but looked up to get the UUID upon template load. | ||
296 | // If null, it wasn't specified. | ||
297 | LLUUID mSoundEffect; | ||
298 | }; | ||
299 | |||
300 | // we want to keep a map of these by name, and it's best to manage them | ||
301 | // with smart pointers | ||
302 | typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr; | ||
303 | |||
304 | /** | ||
305 | * @class LLNotification | ||
306 | * @brief The object that expresses the details of a notification | ||
307 | * | ||
308 | * We make this noncopyable because | ||
309 | * we want to manage these through LLNotificationPtr, and only | ||
310 | * ever create one instance of any given notification. | ||
311 | * | ||
312 | * The enable_shared_from_this flag ensures that if we construct | ||
313 | * a smart pointer from a notification, we'll always get the same | ||
314 | * shared pointer. | ||
315 | */ | ||
316 | class LLNotification : | ||
317 | boost::noncopyable, | ||
318 | public boost::enable_shared_from_this<LLNotification> | ||
319 | { | ||
320 | LOG_CLASS(LLNotification); | ||
321 | friend class LLNotifications; | ||
322 | |||
323 | public: | ||
324 | // parameter object used to instantiate a new notification | ||
325 | class Params : public LLParamBlock<Params> | ||
326 | { | ||
327 | friend class LLNotification; | ||
328 | public: | ||
329 | Params(const std::string& _name) | ||
330 | : name(_name), | ||
331 | mTemporaryResponder(false), | ||
332 | functor_name(_name), | ||
333 | priority(NOTIFICATION_PRIORITY_UNSPECIFIED), | ||
334 | timestamp(LLDate::now()) | ||
335 | { | ||
336 | } | ||
337 | |||
338 | // pseudo-param | ||
339 | Params& functor(LLNotificationFunctorRegistry::ResponseFunctor f) | ||
340 | { | ||
341 | functor_name = LLUUID::generateNewID().asString(); | ||
342 | LLNotificationFunctorRegistry::instance().registerFunctor(functor_name, f); | ||
343 | |||
344 | mTemporaryResponder = true; | ||
345 | return *this; | ||
346 | } | ||
347 | |||
348 | LLMandatoryParam<std::string> name; | ||
349 | |||
350 | // optional | ||
351 | LLOptionalParam<LLSD> substitutions; | ||
352 | LLOptionalParam<LLSD> payload; | ||
353 | LLOptionalParam<ENotificationPriority> priority; | ||
354 | LLOptionalParam<LLSD> form_elements; | ||
355 | LLOptionalParam<LLDate> timestamp; | ||
356 | LLOptionalParam<LLNotificationContext*> context; | ||
357 | LLOptionalParam<std::string> functor_name; | ||
358 | |||
359 | private: | ||
360 | bool mTemporaryResponder; | ||
361 | }; | ||
362 | |||
363 | private: | ||
364 | |||
365 | LLUUID mId; | ||
366 | LLSD mPayload; | ||
367 | LLSD mSubstitutions; | ||
368 | LLDate mTimestamp; | ||
369 | LLDate mExpiresAt; | ||
370 | bool mCancelled; | ||
371 | bool mRespondedTo; // once the notification has been responded to, this becomes true | ||
372 | bool mIgnored; | ||
373 | ENotificationPriority mPriority; | ||
374 | LLNotificationFormPtr mForm; | ||
375 | |||
376 | // a reference to the template | ||
377 | LLNotificationTemplatePtr mTemplatep; | ||
378 | |||
379 | /* | ||
380 | We want to be able to store and reload notifications so that they can survive | ||
381 | a shutdown/restart of the client. So we can't simply pass in callbacks; | ||
382 | we have to specify a callback mechanism that can be used by name rather than | ||
383 | by some arbitrary pointer -- and then people have to initialize callbacks | ||
384 | in some useful location. So we use LLNotificationFunctorRegistry to manage them. | ||
385 | */ | ||
386 | std::string mResponseFunctorName; | ||
387 | |||
388 | /* | ||
389 | In cases where we want to specify an explict, non-persisted callback, | ||
390 | we store that in the callback registry under a dynamically generated | ||
391 | key, and store the key in the notification, so we can still look it up | ||
392 | using the same mechanism. | ||
393 | */ | ||
394 | bool mTemporaryResponder; | ||
395 | |||
396 | void init(const std::string& template_name, const LLSD& form_elements); | ||
397 | |||
398 | LLNotification(const Params& p); | ||
399 | |||
400 | // this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT | ||
401 | // for anything real! | ||
402 | LLNotification(LLUUID uuid) : mId(uuid) {} | ||
403 | |||
404 | void cancel(); | ||
405 | |||
406 | bool payloadContainsAll(const std::vector<std::string>& required_fields) const; | ||
407 | |||
408 | public: | ||
409 | |||
410 | // constructor from a saved notification | ||
411 | LLNotification(const LLSD& sd); | ||
412 | |||
413 | // This is a string formatter for substituting into the message directly | ||
414 | // from LLSD without going through the hopefully-to-be-obsoleted LLString | ||
415 | static std::string format(const std::string& text, const LLSD& substitutions); | ||
416 | |||
417 | void setResponseFunctor(std::string const &responseFunctorName); | ||
418 | |||
419 | typedef enum e_response_template_type | ||
420 | { | ||
421 | WITHOUT_DEFAULT_BUTTON, | ||
422 | WITH_DEFAULT_BUTTON | ||
423 | } EResponseTemplateType; | ||
424 | |||
425 | // return response LLSD filled in with default form contents and (optionally) the default button selected | ||
426 | LLSD getResponseTemplate(EResponseTemplateType type = WITHOUT_DEFAULT_BUTTON); | ||
427 | |||
428 | // returns index of first button with value==TRUE | ||
429 | // usually this the button the user clicked on | ||
430 | // returns -1 if no button clicked (e.g. form has not been displayed) | ||
431 | static S32 getSelectedOption(const LLSD& notification, const LLSD& response); | ||
432 | // returns name of first button with value==TRUE | ||
433 | static std::string getSelectedOptionName(const LLSD& notification); | ||
434 | |||
435 | // after someone responds to a notification (usually by clicking a button, | ||
436 | // but sometimes by filling out a little form and THEN clicking a button), | ||
437 | // the result of the response (the name and value of the button clicked, | ||
438 | // plus any other data) should be packaged up as LLSD, then passed as a | ||
439 | // parameter to the notification's respond() method here. This will look up | ||
440 | // and call the appropriate responder. | ||
441 | // | ||
442 | // response is notification serialized as LLSD: | ||
443 | // ["name"] = notification name | ||
444 | // ["form"] = LLSD tree that includes form description and any prefilled form data | ||
445 | // ["response"] = form data filled in by user | ||
446 | // (including, but not limited to which button they clicked on) | ||
447 | // ["payload"] = transaction specific data, such as ["source_id"] (originator of notification), | ||
448 | // ["item_id"] (attached inventory item), etc. | ||
449 | // ["substitutions"] = string substitutions used to generate notification message | ||
450 | // from the template | ||
451 | // ["time"] = time at which notification was generated; | ||
452 | // ["expiry"] = time at which notification expires; | ||
453 | // ["responseFunctor"] = name of registered functor that handles responses to notification; | ||
454 | LLSD asLLSD(); | ||
455 | |||
456 | void respond(const LLSD& sd); | ||
457 | |||
458 | void setIgnored(bool ignore); | ||
459 | |||
460 | bool isCancelled() const | ||
461 | { | ||
462 | return mCancelled; | ||
463 | } | ||
464 | |||
465 | bool isRespondedTo() const | ||
466 | { | ||
467 | return mRespondedTo; | ||
468 | } | ||
469 | |||
470 | bool isIgnored() const | ||
471 | { | ||
472 | return mIgnored; | ||
473 | } | ||
474 | |||
475 | const std::string& getName() const | ||
476 | { | ||
477 | return mTemplatep->mName; | ||
478 | } | ||
479 | |||
480 | const LLUUID& id() const | ||
481 | { | ||
482 | return mId; | ||
483 | } | ||
484 | |||
485 | const LLSD& getPayload() const | ||
486 | { | ||
487 | return mPayload; | ||
488 | } | ||
489 | |||
490 | const LLSD& getSubstitutions() const | ||
491 | { | ||
492 | return mSubstitutions; | ||
493 | } | ||
494 | |||
495 | const LLDate& getDate() const | ||
496 | { | ||
497 | return mTimestamp; | ||
498 | } | ||
499 | |||
500 | std::string getType() const | ||
501 | { | ||
502 | return (mTemplatep ? mTemplatep->mType : ""); | ||
503 | } | ||
504 | |||
505 | std::string getMessage() const; | ||
506 | std::string getLabel() const; | ||
507 | |||
508 | std::string getURL() const | ||
509 | { | ||
510 | return (mTemplatep ? mTemplatep->mURL : ""); | ||
511 | } | ||
512 | |||
513 | S32 getURLOption() const | ||
514 | { | ||
515 | return (mTemplatep ? mTemplatep->mURLOption : -1); | ||
516 | } | ||
517 | |||
518 | const LLNotificationFormPtr getForm(); | ||
519 | |||
520 | const LLDate getExpiration() const | ||
521 | { | ||
522 | return mExpiresAt; | ||
523 | } | ||
524 | |||
525 | ENotificationPriority getPriority() const | ||
526 | { | ||
527 | return mPriority; | ||
528 | } | ||
529 | |||
530 | const LLUUID getID() const | ||
531 | { | ||
532 | return mId; | ||
533 | } | ||
534 | |||
535 | // comparing two notifications normally means comparing them by UUID (so we can look them | ||
536 | // up quickly this way) | ||
537 | bool operator<(const LLNotification& rhs) const | ||
538 | { | ||
539 | return mId < rhs.mId; | ||
540 | } | ||
541 | |||
542 | bool operator==(const LLNotification& rhs) const | ||
543 | { | ||
544 | return mId == rhs.mId; | ||
545 | } | ||
546 | |||
547 | bool operator!=(const LLNotification& rhs) const | ||
548 | { | ||
549 | return !operator==(rhs); | ||
550 | } | ||
551 | |||
552 | bool isSameObjectAs(const LLNotification* rhs) const | ||
553 | { | ||
554 | return this == rhs; | ||
555 | } | ||
556 | |||
557 | // this object has been updated, so tell all our clients | ||
558 | void update(); | ||
559 | |||
560 | void updateFrom(LLNotificationPtr other); | ||
561 | |||
562 | // A fuzzy equals comparator. | ||
563 | // true only if both notifications have the same template and | ||
564 | // 1) flagged as unique (there can be only one of these) OR | ||
565 | // 2) all required payload fields of each also exist in the other. | ||
566 | bool isEquivalentTo(LLNotificationPtr that) const; | ||
567 | |||
568 | // if the current time is greater than the expiration, the notification is expired | ||
569 | bool isExpired() const | ||
570 | { | ||
571 | if (mExpiresAt.secondsSinceEpoch() == 0) | ||
572 | { | ||
573 | return false; | ||
574 | } | ||
575 | |||
576 | LLDate rightnow = LLDate::now(); | ||
577 | return rightnow > mExpiresAt; | ||
578 | } | ||
579 | |||
580 | std::string summarize() const; | ||
581 | |||
582 | bool hasUniquenessConstraints() const { return (mTemplatep ? mTemplatep->mUnique : false);} | ||
583 | |||
584 | virtual ~LLNotification() {} | ||
585 | }; | ||
586 | |||
587 | std::ostream& operator<<(std::ostream& s, const LLNotification& notification); | ||
588 | |||
589 | namespace LLNotificationFilters | ||
590 | { | ||
591 | // a sample filter | ||
592 | bool includeEverything(LLNotificationPtr p); | ||
593 | |||
594 | typedef enum e_comparison | ||
595 | { | ||
596 | EQUAL, | ||
597 | LESS, | ||
598 | GREATER, | ||
599 | LESS_EQUAL, | ||
600 | GREATER_EQUAL | ||
601 | } EComparison; | ||
602 | |||
603 | // generic filter functor that takes method or member variable reference | ||
604 | template<typename T> | ||
605 | struct filterBy | ||
606 | { | ||
607 | typedef boost::function<T (LLNotificationPtr)> field_t; | ||
608 | typedef typename boost::remove_reference<T>::type value_t; | ||
609 | |||
610 | filterBy(field_t field, value_t value, EComparison comparison = EQUAL) | ||
611 | : mField(field), | ||
612 | mFilterValue(value), | ||
613 | mComparison(comparison) | ||
614 | { | ||
615 | } | ||
616 | |||
617 | bool operator()(LLNotificationPtr p) | ||
618 | { | ||
619 | switch(mComparison) | ||
620 | { | ||
621 | case EQUAL: | ||
622 | return mField(p) == mFilterValue; | ||
623 | case LESS: | ||
624 | return mField(p) < mFilterValue; | ||
625 | case GREATER: | ||
626 | return mField(p) > mFilterValue; | ||
627 | case LESS_EQUAL: | ||
628 | return mField(p) <= mFilterValue; | ||
629 | case GREATER_EQUAL: | ||
630 | return mField(p) >= mFilterValue; | ||
631 | default: | ||
632 | return false; | ||
633 | } | ||
634 | } | ||
635 | |||
636 | field_t mField; | ||
637 | value_t mFilterValue; | ||
638 | EComparison mComparison; | ||
639 | }; | ||
640 | }; | ||
641 | |||
642 | namespace LLNotificationComparators | ||
643 | { | ||
644 | typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection; | ||
645 | |||
646 | // generic order functor that takes method or member variable reference | ||
647 | template<typename T> | ||
648 | struct orderBy | ||
649 | { | ||
650 | typedef boost::function<T (LLNotificationPtr)> field_t; | ||
651 | orderBy(field_t field, EDirection = ORDER_INCREASING) : mField(field) {} | ||
652 | bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs) | ||
653 | { | ||
654 | if (mDirection == ORDER_DECREASING) | ||
655 | { | ||
656 | return mField(lhs) > mField(rhs); | ||
657 | } | ||
658 | else | ||
659 | { | ||
660 | return mField(lhs) < mField(rhs); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | field_t mField; | ||
665 | EDirection mDirection; | ||
666 | }; | ||
667 | |||
668 | struct orderByUUID : public orderBy<const LLUUID&> | ||
669 | { | ||
670 | orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {} | ||
671 | }; | ||
672 | |||
673 | struct orderByDate : public orderBy<const LLDate&> | ||
674 | { | ||
675 | orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {} | ||
676 | }; | ||
677 | }; | ||
678 | |||
679 | typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter; | ||
680 | typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator; | ||
681 | typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet; | ||
682 | typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; | ||
683 | |||
684 | // ======================================================== | ||
685 | // Abstract base class (interface) for a channel; also used for the master container. | ||
686 | // This lets us arrange channels into a call hierarchy. | ||
687 | |||
688 | // We maintain a heirarchy of notification channels; events are always started at the top | ||
689 | // and propagated through the hierarchy only if they pass a filter. | ||
690 | // Any channel can be created with a parent. A null parent (empty string) means it's | ||
691 | // tied to the root of the tree (the LLNotifications class itself). | ||
692 | // The default hierarchy looks like this: | ||
693 | // | ||
694 | // LLNotifications --+-- Expiration --+-- Mute --+-- Ignore --+-- Visible --+-- History | ||
695 | // +-- Alerts | ||
696 | // +-- Notifications | ||
697 | // | ||
698 | // In general, new channels that want to only see notifications that pass through | ||
699 | // all of the built-in tests should attach to the "Visible" channel | ||
700 | // | ||
701 | class LLNotificationChannelBase : | ||
702 | public boost::signals::trackable | ||
703 | { | ||
704 | LOG_CLASS(LLNotificationChannelBase); | ||
705 | public: | ||
706 | LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) : | ||
707 | mFilter(filter), mItems(comp) | ||
708 | {} | ||
709 | virtual ~LLNotificationChannelBase() {} | ||
710 | // you can also connect to a Channel, so you can be notified of | ||
711 | // changes to this channel | ||
712 | virtual void connectChanged(const LLStandardSignal::slot_type& slot); | ||
713 | virtual void connectPassedFilter(const LLStandardSignal::slot_type& slot); | ||
714 | virtual void connectFailedFilter(const LLStandardSignal::slot_type& slot); | ||
715 | |||
716 | // use this when items change or to add a new one | ||
717 | bool updateItem(const LLSD& payload); | ||
718 | const LLNotificationFilter& getFilter() { return mFilter; } | ||
719 | |||
720 | protected: | ||
721 | LLNotificationSet mItems; | ||
722 | LLStandardSignal mChanged; | ||
723 | LLStandardSignal mPassedFilter; | ||
724 | LLStandardSignal mFailedFilter; | ||
725 | |||
726 | // these are action methods that subclasses can override to take action | ||
727 | // on specific types of changes; the management of the mItems list is | ||
728 | // still handled by the generic handler. | ||
729 | virtual void onLoad(LLNotificationPtr p) {} | ||
730 | virtual void onAdd(LLNotificationPtr p) {} | ||
731 | virtual void onDelete(LLNotificationPtr p) {} | ||
732 | virtual void onChange(LLNotificationPtr p) {} | ||
733 | |||
734 | bool updateItem(const LLSD& payload, LLNotificationPtr pNotification); | ||
735 | LLNotificationFilter mFilter; | ||
736 | }; | ||
737 | |||
738 | // The type of the pointers that we're going to manage in the NotificationQueue system | ||
739 | // Because LLNotifications is a singleton, we don't actually expect to ever | ||
740 | // destroy it, but if it becomes necessary to do so, the shared_ptr model | ||
741 | // will ensure that we don't leak resources. | ||
742 | class LLNotificationChannel; | ||
743 | typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr; | ||
744 | |||
745 | // manages a list of notifications | ||
746 | // Note that if this is ever copied around, we might find ourselves with multiple copies | ||
747 | // of a queue with notifications being added to different nonequivalent copies. So we | ||
748 | // make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. | ||
749 | // | ||
750 | // NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to | ||
751 | // do something like: | ||
752 | // LLNotificationChannel::buildChannel("name", "parent"...); | ||
753 | // This returns an LLNotificationChannelPtr, which you can store, or | ||
754 | // you can then retrieve the channel by using the registry: | ||
755 | // LLNotifications::instance().getChannel("name")... | ||
756 | // | ||
757 | class LLNotificationChannel : | ||
758 | boost::noncopyable, | ||
759 | public LLNotificationChannelBase | ||
760 | { | ||
761 | LOG_CLASS(LLNotificationChannel); | ||
762 | |||
763 | public: | ||
764 | virtual ~LLNotificationChannel() {} | ||
765 | typedef LLNotificationSet::iterator Iterator; | ||
766 | |||
767 | std::string getName() const { return mName; } | ||
768 | std::string getParentChannelName() { return mParent; } | ||
769 | |||
770 | bool isEmpty() const; | ||
771 | |||
772 | Iterator begin(); | ||
773 | Iterator end(); | ||
774 | |||
775 | // Channels have a comparator to control sort order; | ||
776 | // the default sorts by arrival date | ||
777 | void setComparator(LLNotificationComparator comparator); | ||
778 | |||
779 | std::string summarize(); | ||
780 | |||
781 | // factory method for constructing these channels; since they're self-registering, | ||
782 | // we want to make sure that you can't use new to make them | ||
783 | static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent, | ||
784 | LLNotificationFilter filter=LLNotificationFilters::includeEverything, | ||
785 | LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); | ||
786 | |||
787 | protected: | ||
788 | // Notification Channels have a filter, which determines which notifications | ||
789 | // will be added to this channel. | ||
790 | // Channel filters cannot change. | ||
791 | // Channels have a protected constructor so you can't make smart pointers that don't | ||
792 | // come from our internal reference; call NotificationChannel::build(args) | ||
793 | LLNotificationChannel(const std::string& name, const std::string& parent, | ||
794 | LLNotificationFilter filter, LLNotificationComparator comparator); | ||
795 | |||
796 | private: | ||
797 | std::string mName; | ||
798 | std::string mParent; | ||
799 | LLNotificationComparator mComparator; | ||
800 | }; | ||
801 | |||
802 | |||
803 | |||
804 | class LLNotifications : | ||
805 | public LLSingleton<LLNotifications>, | ||
806 | public LLNotificationChannelBase | ||
807 | { | ||
808 | LOG_CLASS(LLNotifications); | ||
809 | |||
810 | friend class LLSingleton<LLNotifications>; | ||
811 | public: | ||
812 | // load notification descriptions from file; | ||
813 | // OK to call more than once because it will reload | ||
814 | bool loadTemplates(); | ||
815 | LLXMLNodePtr checkForXMLTemplate(LLXMLNodePtr item); | ||
816 | |||
817 | // we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line | ||
818 | LLNotificationPtr add(const std::string& name, | ||
819 | const LLSD& substitutions = LLSD(), | ||
820 | const LLSD& payload = LLSD()); | ||
821 | LLNotificationPtr add(const std::string& name, | ||
822 | const LLSD& substitutions, | ||
823 | const LLSD& payload, | ||
824 | const std::string& functor_name); | ||
825 | LLNotificationPtr add(const std::string& name, | ||
826 | const LLSD& substitutions, | ||
827 | const LLSD& payload, | ||
828 | LLNotificationFunctorRegistry::ResponseFunctor functor); | ||
829 | LLNotificationPtr add(const LLNotification::Params& p); | ||
830 | |||
831 | void add(const LLNotificationPtr pNotif); | ||
832 | void cancel(LLNotificationPtr pNotif); | ||
833 | void update(const LLNotificationPtr pNotif); | ||
834 | |||
835 | LLNotificationPtr find(LLUUID uuid); | ||
836 | |||
837 | typedef boost::function<void (LLNotificationPtr)> NotificationProcess; | ||
838 | |||
839 | void forEachNotification(NotificationProcess process); | ||
840 | |||
841 | // This is all stuff for managing the templates | ||
842 | // take your template out | ||
843 | LLNotificationTemplatePtr getTemplate(const std::string& name); | ||
844 | |||
845 | // get the whole collection | ||
846 | typedef std::vector<std::string> TemplateNames; | ||
847 | TemplateNames getTemplateNames() const; // returns a list of notification names | ||
848 | |||
849 | typedef std::map<std::string, LLNotificationTemplatePtr> TemplateMap; | ||
850 | |||
851 | TemplateMap::const_iterator templatesBegin() { return mTemplates.begin(); } | ||
852 | TemplateMap::const_iterator templatesEnd() { return mTemplates.end(); } | ||
853 | |||
854 | // test for existence | ||
855 | bool templateExists(const std::string& name); | ||
856 | // useful if you're reloading the file | ||
857 | void clearTemplates(); // erase all templates | ||
858 | |||
859 | void forceResponse(const LLNotification::Params& params, S32 option); | ||
860 | |||
861 | void createDefaultChannels(); | ||
862 | |||
863 | typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap; | ||
864 | ChannelMap mChannels; | ||
865 | |||
866 | void addChannel(LLNotificationChannelPtr pChan); | ||
867 | LLNotificationChannelPtr getChannel(const std::string& channelName); | ||
868 | |||
869 | std::string getGlobalString(const std::string& key) const; | ||
870 | |||
871 | private: | ||
872 | // we're a singleton, so we don't have a public constructor | ||
873 | LLNotifications(); | ||
874 | /*virtual*/ void initSingleton(); | ||
875 | |||
876 | void loadPersistentNotifications(); | ||
877 | |||
878 | bool expirationFilter(LLNotificationPtr pNotification); | ||
879 | bool expirationHandler(const LLSD& payload); | ||
880 | bool uniqueFilter(LLNotificationPtr pNotification); | ||
881 | bool uniqueHandler(const LLSD& payload); | ||
882 | bool failedUniquenessTest(const LLSD& payload); | ||
883 | LLNotificationChannelPtr pHistoryChannel; | ||
884 | LLNotificationChannelPtr pExpirationChannel; | ||
885 | |||
886 | // put your template in | ||
887 | bool addTemplate(const std::string& name, LLNotificationTemplatePtr theTemplate); | ||
888 | TemplateMap mTemplates; | ||
889 | |||
890 | std::string mFileName; | ||
891 | |||
892 | typedef std::map<std::string, LLXMLNodePtr> XMLTemplateMap; | ||
893 | XMLTemplateMap mXmlTemplates; | ||
894 | |||
895 | LLNotificationMap mUniqueNotifications; | ||
896 | |||
897 | typedef std::map<std::string, std::string> GlobalStringMap; | ||
898 | GlobalStringMap mGlobalStrings; | ||
899 | }; | ||
900 | |||
901 | |||
902 | #endif//LL_LLNOTIFICATIONS_H | ||
903 | |||
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp index d37517f..92d045d 100644 --- a/linden/indra/llui/llpanel.cpp +++ b/linden/indra/llui/llpanel.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -58,8 +59,6 @@ | |||
58 | #include "llresizebar.h" | 59 | #include "llresizebar.h" |
59 | #include "llcriticaldamp.h" | 60 | #include "llcriticaldamp.h" |
60 | 61 | ||
61 | LLPanel::alert_queue_t LLPanel::sAlertQueue; | ||
62 | |||
63 | const S32 RESIZE_BAR_OVERLAP = 1; | 62 | const S32 RESIZE_BAR_OVERLAP = 1; |
64 | const S32 RESIZE_BAR_HEIGHT = 3; | 63 | const S32 RESIZE_BAR_HEIGHT = 3; |
65 | 64 | ||
@@ -344,14 +343,14 @@ BOOL LLPanel::checkRequirements() | |||
344 | { | 343 | { |
345 | if (!mRequirementsError.empty()) | 344 | if (!mRequirementsError.empty()) |
346 | { | 345 | { |
347 | LLStringUtil::format_map_t args; | 346 | LLSD args; |
348 | args["[COMPONENTS]"] = mRequirementsError; | 347 | args["COMPONENTS"] = mRequirementsError; |
349 | args["[FLOATER]"] = getName(); | 348 | args["FLOATER"] = getName(); |
350 | 349 | ||
351 | llwarns << getName() << " failed requirements check on: \n" | 350 | llwarns << getName() << " failed requirements check on: \n" |
352 | << mRequirementsError << llendl; | 351 | << mRequirementsError << llendl; |
353 | 352 | ||
354 | alertXml(std::string("FailedRequirementsCheck"), args); | 353 | LLNotifications::instance().add(LLNotification::Params("FailedRequirementsCheck").payload(args)); |
355 | mRequirementsError.clear(); | 354 | mRequirementsError.clear(); |
356 | return FALSE; | 355 | return FALSE; |
357 | } | 356 | } |
@@ -359,25 +358,6 @@ BOOL LLPanel::checkRequirements() | |||
359 | return TRUE; | 358 | return TRUE; |
360 | } | 359 | } |
361 | 360 | ||
362 | //static | ||
363 | void LLPanel::alertXml(const std::string& label, LLStringUtil::format_map_t args) | ||
364 | { | ||
365 | sAlertQueue.push(LLAlertInfo(label,args)); | ||
366 | } | ||
367 | |||
368 | //static | ||
369 | BOOL LLPanel::nextAlert(LLAlertInfo &alert) | ||
370 | { | ||
371 | if (!sAlertQueue.empty()) | ||
372 | { | ||
373 | alert = sAlertQueue.front(); | ||
374 | sAlertQueue.pop(); | ||
375 | return TRUE; | ||
376 | } | ||
377 | |||
378 | return FALSE; | ||
379 | } | ||
380 | |||
381 | void LLPanel::setFocus(BOOL b) | 361 | void LLPanel::setFocus(BOOL b) |
382 | { | 362 | { |
383 | if( b ) | 363 | if( b ) |
@@ -927,7 +907,7 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const | |||
927 | return NULL; | 907 | return NULL; |
928 | } | 908 | } |
929 | 909 | ||
930 | void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata) | 910 | void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool)) |
931 | { | 911 | { |
932 | LLTabContainer* child = getChild<LLTabContainer>(id); | 912 | LLTabContainer* child = getChild<LLTabContainer>(id); |
933 | if (child) | 913 | if (child) |
@@ -937,6 +917,10 @@ void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string | |||
937 | { | 917 | { |
938 | child->setTabChangeCallback(panel, on_tab_clicked); | 918 | child->setTabChangeCallback(panel, on_tab_clicked); |
939 | child->setTabUserData(panel, userdata); | 919 | child->setTabUserData(panel, userdata); |
920 | if (on_precommit) | ||
921 | { | ||
922 | child->setTabPrecommitChangeCallback(panel, on_precommit); | ||
923 | } | ||
940 | } | 924 | } |
941 | } | 925 | } |
942 | } | 926 | } |
@@ -982,12 +966,12 @@ void LLPanel::childSetAction(const std::string& id, void(*function)(void*), void | |||
982 | } | 966 | } |
983 | } | 967 | } |
984 | 968 | ||
985 | void LLPanel::childSetActionTextbox(const std::string& id, void(*function)(void*)) | 969 | void LLPanel::childSetActionTextbox(const std::string& id, void(*function)(void*), void* value) |
986 | { | 970 | { |
987 | LLTextBox* textbox = getChild<LLTextBox>(id); | 971 | LLTextBox* textbox = getChild<LLTextBox>(id); |
988 | if (textbox) | 972 | if (textbox) |
989 | { | 973 | { |
990 | textbox->setClickedCallback(function); | 974 | textbox->setClickedCallback(function, value); |
991 | } | 975 | } |
992 | } | 976 | } |
993 | 977 | ||
@@ -1039,9 +1023,9 @@ void LLPanel::childDisplayNotFound() | |||
1039 | mExpectedMembers.insert(*itor); | 1023 | mExpectedMembers.insert(*itor); |
1040 | } | 1024 | } |
1041 | mNewExpectedMembers.clear(); | 1025 | mNewExpectedMembers.clear(); |
1042 | LLStringUtil::format_map_t args; | 1026 | LLSD args; |
1043 | args["[CONTROLS]"] = msg; | 1027 | args["CONTROLS"] = msg; |
1044 | LLAlertDialog::showXml("FloaterNotFound", args); | 1028 | LLNotifications::instance().add("FloaterNotFound", args); |
1045 | } | 1029 | } |
1046 | 1030 | ||
1047 | void LLPanel::storeRectControl() | 1031 | void LLPanel::storeRectControl() |
@@ -1065,6 +1049,8 @@ struct LLLayoutStack::LLEmbeddedPanel | |||
1065 | mAutoResize(auto_resize), | 1049 | mAutoResize(auto_resize), |
1066 | mUserResize(user_resize), | 1050 | mUserResize(user_resize), |
1067 | mOrientation(orientation), | 1051 | mOrientation(orientation), |
1052 | mCollapsed(FALSE), | ||
1053 | mCollapseAmt(0.f), | ||
1068 | mVisibleAmt(1.f) // default to fully visible | 1054 | mVisibleAmt(1.f) // default to fully visible |
1069 | { | 1055 | { |
1070 | LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; | 1056 | LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; |
@@ -1095,14 +1081,28 @@ struct LLLayoutStack::LLEmbeddedPanel | |||
1095 | mResizeBar = NULL; | 1081 | mResizeBar = NULL; |
1096 | } | 1082 | } |
1097 | 1083 | ||
1084 | F32 getCollapseFactor() | ||
1085 | { | ||
1086 | if (mOrientation == HORIZONTAL) | ||
1087 | { | ||
1088 | return mVisibleAmt * clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)mPanel->getRect().getWidth()); | ||
1089 | } | ||
1090 | else | ||
1091 | { | ||
1092 | return mVisibleAmt * clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinHeight / (F32)mPanel->getRect().getHeight()); | ||
1093 | } | ||
1094 | } | ||
1095 | |||
1098 | LLPanel* mPanel; | 1096 | LLPanel* mPanel; |
1099 | S32 mMinWidth; | 1097 | S32 mMinWidth; |
1100 | S32 mMinHeight; | 1098 | S32 mMinHeight; |
1101 | BOOL mAutoResize; | 1099 | BOOL mAutoResize; |
1102 | BOOL mUserResize; | 1100 | BOOL mUserResize; |
1101 | BOOL mCollapsed; | ||
1103 | LLResizeBar* mResizeBar; | 1102 | LLResizeBar* mResizeBar; |
1104 | eLayoutOrientation mOrientation; | 1103 | eLayoutOrientation mOrientation; |
1105 | F32 mVisibleAmt; | 1104 | F32 mVisibleAmt; |
1105 | F32 mCollapseAmt; | ||
1106 | }; | 1106 | }; |
1107 | 1107 | ||
1108 | static LLRegisterWidget<LLLayoutStack> r2("layout_stack"); | 1108 | static LLRegisterWidget<LLLayoutStack> r2("layout_stack"); |
@@ -1123,28 +1123,27 @@ LLLayoutStack::~LLLayoutStack() | |||
1123 | void LLLayoutStack::draw() | 1123 | void LLLayoutStack::draw() |
1124 | { | 1124 | { |
1125 | updateLayout(); | 1125 | updateLayout(); |
1126 | |||
1127 | e_panel_list_t::iterator panel_it; | ||
1128 | for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) | ||
1126 | { | 1129 | { |
1127 | e_panel_list_t::iterator panel_it; | 1130 | // clip to layout rectangle, not bounding rectangle |
1128 | for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) | 1131 | LLRect clip_rect = (*panel_it)->mPanel->getRect(); |
1132 | // scale clipping rectangle by visible amount | ||
1133 | if (mOrientation == HORIZONTAL) | ||
1129 | { | 1134 | { |
1130 | // clip to layout rectangle, not bounding rectangle | 1135 | clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor()); |
1131 | LLRect clip_rect = (*panel_it)->mPanel->getRect(); | 1136 | } |
1132 | // scale clipping rectangle by visible amount | 1137 | else |
1133 | if (mOrientation == HORIZONTAL) | 1138 | { |
1134 | { | 1139 | clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor()); |
1135 | clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->mVisibleAmt); | 1140 | } |
1136 | } | ||
1137 | else | ||
1138 | { | ||
1139 | clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->mVisibleAmt); | ||
1140 | } | ||
1141 | 1141 | ||
1142 | LLPanel* panelp = (*panel_it)->mPanel; | 1142 | LLPanel* panelp = (*panel_it)->mPanel; |
1143 | 1143 | ||
1144 | LLLocalClipRect clip(clip_rect); | 1144 | LLLocalClipRect clip(clip_rect); |
1145 | // only force drawing invisible children if visible amount is non-zero | 1145 | // only force drawing invisible children if visible amount is non-zero |
1146 | drawChild(panelp, 0, 0, !clip_rect.isNull()); | 1146 | drawChild(panelp, 0, 0, !clip_rect.isNull()); |
1147 | } | ||
1148 | } | 1147 | } |
1149 | } | 1148 | } |
1150 | 1149 | ||
@@ -1276,8 +1275,13 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width) | |||
1276 | return cur_width; | 1275 | return cur_width; |
1277 | } | 1276 | } |
1278 | 1277 | ||
1279 | void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index) | 1278 | void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index) |
1280 | { | 1279 | { |
1280 | // panel starts off invisible (collapsed) | ||
1281 | if (animate == ANIMATE) | ||
1282 | { | ||
1283 | panel->setVisible(FALSE); | ||
1284 | } | ||
1281 | LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize); | 1285 | LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize); |
1282 | 1286 | ||
1283 | mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel); | 1287 | mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel); |
@@ -1293,6 +1297,11 @@ void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL | |||
1293 | sendChildToFront(resize_barp); | 1297 | sendChildToFront(resize_barp); |
1294 | } | 1298 | } |
1295 | 1299 | ||
1300 | // start expanding panel animation | ||
1301 | if (animate == ANIMATE) | ||
1302 | { | ||
1303 | panel->setVisible(TRUE); | ||
1304 | } | ||
1296 | } | 1305 | } |
1297 | 1306 | ||
1298 | void LLLayoutStack::removePanel(LLPanel* panel) | 1307 | void LLLayoutStack::removePanel(LLPanel* panel) |
@@ -1300,6 +1309,14 @@ void LLLayoutStack::removePanel(LLPanel* panel) | |||
1300 | removeChild(panel); | 1309 | removeChild(panel); |
1301 | } | 1310 | } |
1302 | 1311 | ||
1312 | void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed) | ||
1313 | { | ||
1314 | LLEmbeddedPanel* panel_container = findEmbeddedPanel(panel); | ||
1315 | if (!panel_container) return; | ||
1316 | |||
1317 | panel_container->mCollapsed = collapsed; | ||
1318 | } | ||
1319 | |||
1303 | void LLLayoutStack::updateLayout(BOOL force_resize) | 1320 | void LLLayoutStack::updateLayout(BOOL force_resize) |
1304 | { | 1321 | { |
1305 | calcMinExtents(); | 1322 | calcMinExtents(); |
@@ -1332,6 +1349,15 @@ void LLLayoutStack::updateLayout(BOOL force_resize) | |||
1332 | } | 1349 | } |
1333 | } | 1350 | } |
1334 | 1351 | ||
1352 | if ((*panel_it)->mCollapsed) | ||
1353 | { | ||
1354 | (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME)); | ||
1355 | } | ||
1356 | else | ||
1357 | { | ||
1358 | (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME)); | ||
1359 | } | ||
1360 | |||
1335 | if (mOrientation == HORIZONTAL) | 1361 | if (mOrientation == HORIZONTAL) |
1336 | { | 1362 | { |
1337 | // enforce minimize size constraint by default | 1363 | // enforce minimize size constraint by default |
@@ -1339,7 +1365,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize) | |||
1339 | { | 1365 | { |
1340 | panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight()); | 1366 | panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight()); |
1341 | } | 1367 | } |
1342 | total_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt); | 1368 | total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor()); |
1343 | // want n-1 panel gaps for n panels | 1369 | // want n-1 panel gaps for n panels |
1344 | if (panel_it != mPanels.begin()) | 1370 | if (panel_it != mPanels.begin()) |
1345 | { | 1371 | { |
@@ -1353,7 +1379,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize) | |||
1353 | { | 1379 | { |
1354 | panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight); | 1380 | panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight); |
1355 | } | 1381 | } |
1356 | total_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt); | 1382 | total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor()); |
1357 | if (panel_it != mPanels.begin()) | 1383 | if (panel_it != mPanels.begin()) |
1358 | { | 1384 | { |
1359 | total_height += mPanelSpacing; | 1385 | total_height += mPanelSpacing; |
@@ -1367,7 +1393,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize) | |||
1367 | for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) | 1393 | for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) |
1368 | { | 1394 | { |
1369 | // panels that are not fully visible do not count towards shrink headroom | 1395 | // panels that are not fully visible do not count towards shrink headroom |
1370 | if ((*panel_it)->mVisibleAmt < 1.f) | 1396 | if ((*panel_it)->getCollapseFactor() < 1.f) |
1371 | { | 1397 | { |
1372 | continue; | 1398 | continue; |
1373 | } | 1399 | } |
@@ -1431,7 +1457,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize) | |||
1431 | S32 delta_size = 0; | 1457 | S32 delta_size = 0; |
1432 | 1458 | ||
1433 | // if panel can automatically resize (not animating, and resize flag set)... | 1459 | // if panel can automatically resize (not animating, and resize flag set)... |
1434 | if ((*panel_it)->mVisibleAmt == 1.f | 1460 | if ((*panel_it)->getCollapseFactor() == 1.f |
1435 | && (force_resize || (*panel_it)->mAutoResize) | 1461 | && (force_resize || (*panel_it)->mAutoResize) |
1436 | && !(*panel_it)->mResizeBar->hasMouseCapture()) | 1462 | && !(*panel_it)->mResizeBar->hasMouseCapture()) |
1437 | { | 1463 | { |
@@ -1515,11 +1541,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize) | |||
1515 | 1541 | ||
1516 | if (mOrientation == HORIZONTAL) | 1542 | if (mOrientation == HORIZONTAL) |
1517 | { | 1543 | { |
1518 | cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + mPanelSpacing; | 1544 | cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing; |
1519 | } | 1545 | } |
1520 | else //VERTICAL | 1546 | else //VERTICAL |
1521 | { | 1547 | { |
1522 | cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + mPanelSpacing; | 1548 | cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing; |
1523 | } | 1549 | } |
1524 | } | 1550 | } |
1525 | 1551 | ||
diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h index 46022e5..756d02e 100644 --- a/linden/indra/llui/llpanel.h +++ b/linden/indra/llui/llpanel.h | |||
@@ -18,7 +18,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 21 | * online at |
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
@@ -49,23 +50,13 @@ const BOOL BORDER_YES = TRUE; | |||
49 | const BOOL BORDER_NO = FALSE; | 50 | const BOOL BORDER_NO = FALSE; |
50 | 51 | ||
51 | 52 | ||
52 | struct LLAlertInfo | ||
53 | { | ||
54 | std::string mLabel; | ||
55 | LLStringUtil::format_map_t mArgs; | ||
56 | |||
57 | LLAlertInfo(std::string label, LLStringUtil::format_map_t args) : mLabel(label), mArgs(args) { } | ||
58 | LLAlertInfo(){} | ||
59 | }; | ||
60 | |||
61 | |||
62 | /* | 53 | /* |
63 | * General purpose concrete view base class. | 54 | * General purpose concrete view base class. |
64 | * Transparent or opaque, | 55 | * Transparent or opaque, |
65 | * With or without border, | 56 | * With or without border, |
66 | * Can contain LLUICtrls. | 57 | * Can contain LLUICtrls. |
67 | */ | 58 | */ |
68 | class LLPanel : public LLUICtrl | 59 | class LLPanel : public LLUICtrl, public boost::signals::trackable |
69 | { | 60 | { |
70 | public: | 61 | public: |
71 | 62 | ||
@@ -205,7 +196,7 @@ public: | |||
205 | // LLTabContainer | 196 | // LLTabContainer |
206 | void childShowTab(const std::string& id, const std::string& tabname, bool visible = true); | 197 | void childShowTab(const std::string& id, const std::string& tabname, bool visible = true); |
207 | LLPanel *childGetVisibleTab(const std::string& id) const; | 198 | LLPanel *childGetVisibleTab(const std::string& id) const; |
208 | void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata); | 199 | void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool) = NULL); |
209 | 200 | ||
210 | // LLTextBox | 201 | // LLTextBox |
211 | void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true); | 202 | void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true); |
@@ -220,15 +211,13 @@ public: | |||
220 | 211 | ||
221 | // LLButton | 212 | // LLButton |
222 | void childSetAction(const std::string& id, void(*function)(void*), void* value); | 213 | void childSetAction(const std::string& id, void(*function)(void*), void* value); |
223 | void childSetActionTextbox(const std::string& id, void(*function)(void*)); | 214 | void childSetActionTextbox(const std::string& id, void(*function)(void*), void* value = NULL); |
224 | void childSetControlName(const std::string& id, const std::string& control_name); | 215 | void childSetControlName(const std::string& id, const std::string& control_name); |
225 | 216 | ||
226 | // Error reporting | 217 | // Error reporting |
227 | void childNotFound(const std::string& id) const; | 218 | void childNotFound(const std::string& id) const; |
228 | void childDisplayNotFound(); | 219 | void childDisplayNotFound(); |
229 | 220 | ||
230 | static void alertXml(const std::string& label, LLStringUtil::format_map_t args = LLStringUtil::format_map_t()); | ||
231 | static BOOL nextAlert(LLAlertInfo &alert); | ||
232 | static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); | 221 | static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); |
233 | 222 | ||
234 | protected: | 223 | protected: |
@@ -266,8 +255,6 @@ private: | |||
266 | 255 | ||
267 | std::string mRequirementsError; | 256 | std::string mRequirementsError; |
268 | 257 | ||
269 | typedef std::queue<LLAlertInfo> alert_queue_t; | ||
270 | static alert_queue_t sAlertQueue; | ||
271 | }; // end class LLPanel | 258 | }; // end class LLPanel |
272 | 259 | ||
273 | 260 | ||
@@ -292,8 +279,16 @@ public: | |||
292 | S32 getMinWidth() const { return mMinWidth; } | 279 | S32 getMinWidth() const { return mMinWidth; } |
293 | S32 getMinHeight() const { return mMinHeight; } | 280 | S32 getMinHeight() const { return mMinHeight; } |
294 | 281 | ||
295 | void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index = S32_MAX); | 282 | typedef enum e_animate |
283 | { | ||
284 | NO_ANIMATE, | ||
285 | ANIMATE | ||
286 | } EAnimate; | ||
287 | |||
288 | void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX); | ||
296 | void removePanel(LLPanel* panel); | 289 | void removePanel(LLPanel* panel); |
290 | void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE); | ||
291 | S32 getNumPanels() { return mPanels.size(); } | ||
297 | 292 | ||
298 | private: | 293 | private: |
299 | struct LLEmbeddedPanel; | 294 | struct LLEmbeddedPanel; |
diff --git a/linden/indra/llui/llprogressbar.cpp b/linden/indra/llui/llprogressbar.cpp new file mode 100644 index 0000000..8833494 --- /dev/null +++ b/linden/indra/llui/llprogressbar.cpp | |||
@@ -0,0 +1,181 @@ | |||
1 | /** | ||
2 | * @file llprogressbar.cpp | ||
3 | * @brief LLProgressBar class implementation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "llprogressbar.h" | ||
36 | |||
37 | #include "indra_constants.h" | ||
38 | #include "llmath.h" | ||
39 | #include "llgl.h" | ||
40 | #include "llui.h" | ||
41 | #include "llfontgl.h" | ||
42 | #include "llimagegl.h" | ||
43 | #include "lltimer.h" | ||
44 | #include "llglheaders.h" | ||
45 | |||
46 | #include "llfocusmgr.h" | ||
47 | |||
48 | static LLRegisterWidget<LLProgressBar> r("progress_bar"); | ||
49 | |||
50 | LLProgressBar::LLProgressBar(const std::string& name, const LLRect &rect) | ||
51 | : LLView(name, rect, FALSE), | ||
52 | mImageBar( NULL ), | ||
53 | mImageShadow( NULL ) | ||
54 | { | ||
55 | mPercentDone = 0.f; | ||
56 | |||
57 | // Defaults: | ||
58 | |||
59 | setImageBar("rounded_square.tga"); | ||
60 | setImageShadow("rounded_square_soft.tga"); | ||
61 | |||
62 | mColorBackground = LLColor4(0.3254f, 0.4000f, 0.5058f, 1.0f); | ||
63 | mColorBar = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f); | ||
64 | mColorBar2 = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f); | ||
65 | mColorShadow = LLColor4(0.2000f, 0.2000f, 0.4000f, 1.0f); | ||
66 | } | ||
67 | |||
68 | LLProgressBar::~LLProgressBar() | ||
69 | { | ||
70 | gFocusMgr.releaseFocusIfNeeded( this ); | ||
71 | } | ||
72 | |||
73 | void LLProgressBar::draw() | ||
74 | { | ||
75 | static LLTimer timer; | ||
76 | |||
77 | LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); | ||
78 | LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga"); | ||
79 | LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga"); | ||
80 | LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga"); | ||
81 | LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor"); | ||
82 | |||
83 | bar_bg_imagep->draw(getLocalRect(), | ||
84 | background_color); | ||
85 | |||
86 | F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); | ||
87 | LLColor4 bar_color = LLUI::sColorsGroup->getColor("LoginProgressBarFgColor"); | ||
88 | bar_color.mV[3] = alpha; | ||
89 | LLRect progress_rect = getLocalRect(); | ||
90 | progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f)); | ||
91 | bar_fg_imagep->draw(progress_rect); | ||
92 | } | ||
93 | |||
94 | void LLProgressBar::setPercent(const F32 percent) | ||
95 | { | ||
96 | mPercentDone = llclamp(percent, 0.f, 100.f); | ||
97 | } | ||
98 | |||
99 | void LLProgressBar::setImageBar( const std::string &bar_name ) | ||
100 | { | ||
101 | mImageBar = LLUI::sImageProvider->getUIImage(bar_name)->getImage(); | ||
102 | } | ||
103 | |||
104 | void LLProgressBar::setImageShadow(const std::string &shadow_name) | ||
105 | { | ||
106 | mImageShadow = LLUI::sImageProvider->getUIImage(shadow_name)->getImage(); | ||
107 | } | ||
108 | |||
109 | void LLProgressBar::setColorBar(const LLColor4 &c) | ||
110 | { | ||
111 | mColorBar = c; | ||
112 | } | ||
113 | void LLProgressBar::setColorBar2(const LLColor4 &c) | ||
114 | { | ||
115 | mColorBar2 = c; | ||
116 | } | ||
117 | void LLProgressBar::setColorShadow(const LLColor4 &c) | ||
118 | { | ||
119 | mColorShadow = c; | ||
120 | } | ||
121 | void LLProgressBar::setColorBackground(const LLColor4 &c) | ||
122 | { | ||
123 | mColorBackground = c; | ||
124 | } | ||
125 | |||
126 | |||
127 | // static | ||
128 | LLView* LLProgressBar::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) | ||
129 | { | ||
130 | std::string name("progress_bar"); | ||
131 | node->getAttributeString("name", name); | ||
132 | |||
133 | LLProgressBar *progress = new LLProgressBar(name, LLRect()); | ||
134 | |||
135 | |||
136 | std::string image_bar; | ||
137 | if (node->hasAttribute("image_bar")) node->getAttributeString("image_bar",image_bar); | ||
138 | if (image_bar != LLStringUtil::null) progress->setImageBar(image_bar); | ||
139 | |||
140 | |||
141 | std::string image_shadow; | ||
142 | if (node->hasAttribute("image_shadow")) node->getAttributeString("image_shadow",image_shadow); | ||
143 | if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow); | ||
144 | |||
145 | |||
146 | LLColor4 color_bar; | ||
147 | if (node->hasAttribute("color_bar")) | ||
148 | { | ||
149 | node->getAttributeColor4("color_bar",color_bar); | ||
150 | progress->setColorBar(color_bar); | ||
151 | } | ||
152 | |||
153 | |||
154 | LLColor4 color_bar2; | ||
155 | if (node->hasAttribute("color_bar2")) | ||
156 | { | ||
157 | node->getAttributeColor4("color_bar2",color_bar2); | ||
158 | progress->setColorBar2(color_bar2); | ||
159 | } | ||
160 | |||
161 | |||
162 | LLColor4 color_shadow; | ||
163 | if (node->hasAttribute("color_shadow")) | ||
164 | { | ||
165 | node->getAttributeColor4("color_shadow",color_shadow); | ||
166 | progress->setColorShadow(color_shadow); | ||
167 | } | ||
168 | |||
169 | |||
170 | LLColor4 color_bg; | ||
171 | if (node->hasAttribute("color_bg")) | ||
172 | { | ||
173 | node->getAttributeColor4("color_bg",color_bg); | ||
174 | progress->setColorBackground(color_bg); | ||
175 | } | ||
176 | |||
177 | |||
178 | progress->initFromXML(node, parent); | ||
179 | |||
180 | return progress; | ||
181 | } | ||
diff --git a/linden/indra/llui/llprogressbar.h b/linden/indra/llui/llprogressbar.h new file mode 100644 index 0000000..00ad61d --- /dev/null +++ b/linden/indra/llui/llprogressbar.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /** | ||
2 | * @file llprogressbar.h | ||
3 | * @brief LLProgressBar class definition | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LLPROGRESSBAR_H | ||
34 | #define LL_LLPROGRESSBAR_H | ||
35 | |||
36 | #include "llview.h" | ||
37 | #include "llframetimer.h" | ||
38 | |||
39 | class LLProgressBar | ||
40 | : public LLView | ||
41 | { | ||
42 | public: | ||
43 | LLProgressBar(const std::string& name, const LLRect &rect); | ||
44 | virtual ~LLProgressBar(); | ||
45 | |||
46 | void setPercent(const F32 percent); | ||
47 | |||
48 | void setImageBar(const std::string &bar_name); | ||
49 | void setImageShadow(const std::string &shadow_name); | ||
50 | |||
51 | void setColorBar(const LLColor4 &c); | ||
52 | void setColorBar2(const LLColor4 &c); | ||
53 | void setColorShadow(const LLColor4 &c); | ||
54 | void setColorBackground(const LLColor4 &c); | ||
55 | |||
56 | static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); | ||
57 | |||
58 | /*virtual*/ void draw(); | ||
59 | |||
60 | protected: | ||
61 | F32 mPercentDone; | ||
62 | |||
63 | LLPointer<LLImageGL> mImageBar; | ||
64 | //LLUUID mImageBarID; | ||
65 | //LLString mImageBarName; | ||
66 | LLColor4 mColorBar; | ||
67 | LLColor4 mColorBar2; | ||
68 | |||
69 | LLPointer<LLImageGL> mImageShadow; | ||
70 | //LLUUID mImageShadowID; | ||
71 | //LLString mImageShadowName; | ||
72 | LLColor4 mColorShadow; | ||
73 | LLColor4 mColorBackground; | ||
74 | }; | ||
75 | |||
76 | #endif // LL_LLPROGRESSBAR_H | ||
diff --git a/linden/indra/llui/llradiogroup.cpp b/linden/indra/llui/llradiogroup.cpp index f6778f3..33b9398 100644 --- a/linden/indra/llui/llradiogroup.cpp +++ b/linden/indra/llui/llradiogroup.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llradiogroup.h b/linden/indra/llui/llradiogroup.h index 06729bc..3410b74 100644 --- a/linden/indra/llui/llradiogroup.h +++ b/linden/indra/llui/llradiogroup.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llresizebar.cpp b/linden/indra/llui/llresizebar.cpp index 0ba02fa..5b9fe72 100644 --- a/linden/indra/llui/llresizebar.cpp +++ b/linden/indra/llui/llresizebar.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llresizebar.h b/linden/indra/llui/llresizebar.h index b8494b0..b9fc405 100644 --- a/linden/indra/llui/llresizebar.h +++ b/linden/indra/llui/llresizebar.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llresizehandle.cpp b/linden/indra/llui/llresizehandle.cpp index 3202ffe..c5d57d8 100644 --- a/linden/indra/llui/llresizehandle.cpp +++ b/linden/indra/llui/llresizehandle.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llresizehandle.h b/linden/indra/llui/llresizehandle.h index 32d382a..0e23d52 100644 --- a/linden/indra/llui/llresizehandle.h +++ b/linden/indra/llui/llresizehandle.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llresmgr.cpp b/linden/indra/llui/llresmgr.cpp index d111bd6..32d3d1f 100644 --- a/linden/indra/llui/llresmgr.cpp +++ b/linden/indra/llui/llresmgr.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -54,11 +55,11 @@ LLResMgr::LLResMgr() | |||
54 | { | 55 | { |
55 | mUSAFonts[i] = NULL; | 56 | mUSAFonts[i] = NULL; |
56 | } | 57 | } |
57 | mUSAFonts[ LLFONT_OCRA ] = LLFontGL::sMonospace; | 58 | mUSAFonts[ LLFONT_OCRA ] = LLFontGL::getFontMonospace(); |
58 | mUSAFonts[ LLFONT_SANSSERIF ] = LLFontGL::sSansSerif; | 59 | mUSAFonts[ LLFONT_SANSSERIF ] = LLFontGL::getFontSansSerif(); |
59 | mUSAFonts[ LLFONT_SANSSERIF_SMALL ] = LLFontGL::sSansSerifSmall; | 60 | mUSAFonts[ LLFONT_SANSSERIF_SMALL ] = LLFontGL::getFontSansSerifSmall(); |
60 | mUSAFonts[ LLFONT_SANSSERIF_BIG ] = LLFontGL::sSansSerifBig; | 61 | mUSAFonts[ LLFONT_SANSSERIF_BIG ] = LLFontGL::getFontSansSerifBig(); |
61 | mUSAFonts[ LLFONT_SMALL ] = LLFontGL::sMonospace; | 62 | mUSAFonts[ LLFONT_SMALL ] = LLFontGL::getFontMonospace(); |
62 | /* | 63 | /* |
63 | // USA Strings | 64 | // USA Strings |
64 | for( i=0; i<LLSTR_COUNT; i++ ) | 65 | for( i=0; i<LLSTR_COUNT; i++ ) |
diff --git a/linden/indra/llui/llresmgr.h b/linden/indra/llui/llresmgr.h index 86bb6dd..d54505c 100644 --- a/linden/indra/llui/llresmgr.h +++ b/linden/indra/llui/llresmgr.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llrootview.cpp b/linden/indra/llui/llrootview.cpp index de1f90b..e4f178b 100644 --- a/linden/indra/llui/llrootview.cpp +++ b/linden/indra/llui/llrootview.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llrootview.h b/linden/indra/llui/llrootview.h index 4aa4467..33ebf8d 100644 --- a/linden/indra/llui/llrootview.h +++ b/linden/indra/llui/llrootview.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llscrollbar.cpp b/linden/indra/llui/llscrollbar.cpp index 1b87c69..65086d8 100644 --- a/linden/indra/llui/llscrollbar.cpp +++ b/linden/indra/llui/llscrollbar.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -113,7 +114,7 @@ LLScrollbar::LLScrollbar( | |||
113 | 114 | ||
114 | LLButton* line_up_btn = new LLButton(std::string("Line Up"), line_up_rect, | 115 | LLButton* line_up_btn = new LLButton(std::string("Line Up"), line_up_rect, |
115 | line_up_img, line_up_selected_img, LLStringUtil::null, | 116 | line_up_img, line_up_selected_img, LLStringUtil::null, |
116 | &LLScrollbar::onLineUpBtnPressed, this, LLFontGL::sSansSerif ); | 117 | &LLScrollbar::onLineUpBtnPressed, this, LLFontGL::getFontSansSerif() ); |
117 | if( LLScrollbar::VERTICAL == mOrientation ) | 118 | if( LLScrollbar::VERTICAL == mOrientation ) |
118 | { | 119 | { |
119 | line_up_btn->setFollowsRight(); | 120 | line_up_btn->setFollowsRight(); |
@@ -127,15 +128,18 @@ LLScrollbar::LLScrollbar( | |||
127 | } | 128 | } |
128 | line_up_btn->setHeldDownCallback( &LLScrollbar::onLineUpBtnPressed ); | 129 | line_up_btn->setHeldDownCallback( &LLScrollbar::onLineUpBtnPressed ); |
129 | line_up_btn->setTabStop(FALSE); | 130 | line_up_btn->setTabStop(FALSE); |
131 | line_up_btn->setScaleImage(TRUE); | ||
132 | |||
130 | addChild(line_up_btn); | 133 | addChild(line_up_btn); |
131 | 134 | ||
132 | LLButton* line_down_btn = new LLButton(std::string("Line Down"), line_down_rect, | 135 | LLButton* line_down_btn = new LLButton(std::string("Line Down"), line_down_rect, |
133 | line_down_img, line_down_selected_img, LLStringUtil::null, | 136 | line_down_img, line_down_selected_img, LLStringUtil::null, |
134 | &LLScrollbar::onLineDownBtnPressed, this, LLFontGL::sSansSerif ); | 137 | &LLScrollbar::onLineDownBtnPressed, this, LLFontGL::getFontSansSerif() ); |
135 | line_down_btn->setFollowsRight(); | 138 | line_down_btn->setFollowsRight(); |
136 | line_down_btn->setFollowsBottom(); | 139 | line_down_btn->setFollowsBottom(); |
137 | line_down_btn->setHeldDownCallback( &LLScrollbar::onLineDownBtnPressed ); | 140 | line_down_btn->setHeldDownCallback( &LLScrollbar::onLineDownBtnPressed ); |
138 | line_down_btn->setTabStop(FALSE); | 141 | line_down_btn->setTabStop(FALSE); |
142 | line_down_btn->setScaleImage(TRUE); | ||
139 | addChild(line_down_btn); | 143 | addChild(line_down_btn); |
140 | } | 144 | } |
141 | 145 | ||
@@ -148,20 +152,29 @@ LLScrollbar::~LLScrollbar() | |||
148 | void LLScrollbar::setDocParams( S32 size, S32 pos ) | 152 | void LLScrollbar::setDocParams( S32 size, S32 pos ) |
149 | { | 153 | { |
150 | mDocSize = size; | 154 | mDocSize = size; |
151 | mDocPos = llclamp( pos, 0, getDocPosMax() ); | 155 | setDocPos(pos); |
152 | mDocChanged = TRUE; | 156 | mDocChanged = TRUE; |
153 | 157 | ||
154 | updateThumbRect(); | 158 | updateThumbRect(); |
155 | } | 159 | } |
156 | 160 | ||
157 | void LLScrollbar::setDocPos(S32 pos) | 161 | void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb) |
158 | { | 162 | { |
163 | pos = llclamp(pos, 0, getDocPosMax()); | ||
159 | if (pos != mDocPos) | 164 | if (pos != mDocPos) |
160 | { | 165 | { |
161 | mDocPos = llclamp( pos, 0, getDocPosMax() ); | 166 | mDocPos = pos; |
162 | mDocChanged = TRUE; | 167 | mDocChanged = TRUE; |
163 | 168 | ||
164 | updateThumbRect(); | 169 | if( mChangeCallback ) |
170 | { | ||
171 | mChangeCallback( mDocPos, this, mCallbackUserData ); | ||
172 | } | ||
173 | |||
174 | if( update_thumb ) | ||
175 | { | ||
176 | updateThumbRect(); | ||
177 | } | ||
165 | } | 178 | } |
166 | } | 179 | } |
167 | 180 | ||
@@ -170,7 +183,7 @@ void LLScrollbar::setDocSize(S32 size) | |||
170 | if (size != mDocSize) | 183 | if (size != mDocSize) |
171 | { | 184 | { |
172 | mDocSize = size; | 185 | mDocSize = size; |
173 | mDocPos = llclamp( mDocPos, 0, getDocPosMax() ); | 186 | setDocPos(mDocPos); |
174 | mDocChanged = TRUE; | 187 | mDocChanged = TRUE; |
175 | 188 | ||
176 | updateThumbRect(); | 189 | updateThumbRect(); |
@@ -182,7 +195,7 @@ void LLScrollbar::setPageSize( S32 page_size ) | |||
182 | if (page_size != mPageSize) | 195 | if (page_size != mPageSize) |
183 | { | 196 | { |
184 | mPageSize = page_size; | 197 | mPageSize = page_size; |
185 | mDocPos = llclamp( mDocPos, 0, getDocPosMax() ); | 198 | setDocPos(mDocPos); |
186 | mDocChanged = TRUE; | 199 | mDocChanged = TRUE; |
187 | 200 | ||
188 | updateThumbRect(); | 201 | updateThumbRect(); |
@@ -208,9 +221,9 @@ void LLScrollbar::updateThumbRect() | |||
208 | const S32 THUMB_MIN_LENGTH = 16; | 221 | const S32 THUMB_MIN_LENGTH = 16; |
209 | 222 | ||
210 | S32 window_length = (mOrientation == LLScrollbar::HORIZONTAL) ? getRect().getWidth() : getRect().getHeight(); | 223 | S32 window_length = (mOrientation == LLScrollbar::HORIZONTAL) ? getRect().getWidth() : getRect().getHeight(); |
211 | S32 thumb_bg_length = window_length - 2 * SCROLLBAR_SIZE; | 224 | S32 thumb_bg_length = llmax(0, window_length - 2 * SCROLLBAR_SIZE); |
212 | S32 visible_lines = llmin( mDocSize, mPageSize ); | 225 | S32 visible_lines = llmin( mDocSize, mPageSize ); |
213 | S32 thumb_length = mDocSize ? llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH ) : thumb_bg_length; | 226 | S32 thumb_length = mDocSize ? llmin(llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH), thumb_bg_length) : thumb_bg_length; |
214 | 227 | ||
215 | S32 variable_lines = mDocSize - visible_lines; | 228 | S32 variable_lines = mDocSize - visible_lines; |
216 | 229 | ||
@@ -218,7 +231,7 @@ void LLScrollbar::updateThumbRect() | |||
218 | { | 231 | { |
219 | S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE; | 232 | S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE; |
220 | S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH; | 233 | S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH; |
221 | S32 thumb_start = variable_lines ? llclamp( thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min, thumb_start_max ) : thumb_start_max; | 234 | S32 thumb_start = variable_lines ? llmin( llmax(thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_max; |
222 | 235 | ||
223 | mThumbRect.mLeft = 0; | 236 | mThumbRect.mLeft = 0; |
224 | mThumbRect.mTop = thumb_start; | 237 | mThumbRect.mTop = thumb_start; |
@@ -230,7 +243,7 @@ void LLScrollbar::updateThumbRect() | |||
230 | // Horizontal | 243 | // Horizontal |
231 | S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length; | 244 | S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length; |
232 | S32 thumb_start_min = SCROLLBAR_SIZE; | 245 | S32 thumb_start_min = SCROLLBAR_SIZE; |
233 | S32 thumb_start = variable_lines ? llclamp( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min, thumb_start_max ) : thumb_start_min; | 246 | S32 thumb_start = variable_lines ? llmin(llmax( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_min; |
234 | 247 | ||
235 | mThumbRect.mLeft = thumb_start; | 248 | mThumbRect.mLeft = thumb_start; |
236 | mThumbRect.mTop = SCROLLBAR_SIZE; | 249 | mThumbRect.mTop = SCROLLBAR_SIZE; |
@@ -446,7 +459,7 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask) | |||
446 | } | 459 | } |
447 | else | 460 | else |
448 | { | 461 | { |
449 | // Opaque, so don't just check children | 462 | // Opaque, so don't just check children |
450 | handled = LLView::handleMouseUp( x, y, mask ); | 463 | handled = LLView::handleMouseUp( x, y, mask ); |
451 | } | 464 | } |
452 | 465 | ||
@@ -455,21 +468,34 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask) | |||
455 | 468 | ||
456 | void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent) | 469 | void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent) |
457 | { | 470 | { |
471 | if (width == getRect().getWidth() && height == getRect().getHeight()) return; | ||
458 | LLView::reshape( width, height, called_from_parent ); | 472 | LLView::reshape( width, height, called_from_parent ); |
473 | LLButton* up_button = getChild<LLButton>("Line Up"); | ||
474 | LLButton* down_button = getChild<LLButton>("Line Down"); | ||
475 | |||
476 | if (mOrientation == VERTICAL) | ||
477 | { | ||
478 | up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE)); | ||
479 | down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE)); | ||
480 | up_button->setOrigin(up_button->getRect().mLeft, getRect().getHeight() - up_button->getRect().getHeight()); | ||
481 | } | ||
482 | else | ||
483 | { | ||
484 | up_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), up_button->getRect().getHeight()); | ||
485 | down_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), down_button->getRect().getHeight()); | ||
486 | down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(), down_button->getRect().mBottom); | ||
487 | } | ||
459 | updateThumbRect(); | 488 | updateThumbRect(); |
460 | } | 489 | } |
461 | 490 | ||
462 | 491 | ||
463 | void LLScrollbar::draw() | 492 | void LLScrollbar::draw() |
464 | { | 493 | { |
494 | if (!getRect().isValid()) return; | ||
495 | |||
465 | S32 local_mouse_x; | 496 | S32 local_mouse_x; |
466 | S32 local_mouse_y; | 497 | S32 local_mouse_y; |
467 | LLCoordWindow cursor_pos_window; | 498 | LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); |
468 | getWindow()->getCursorPosition(&cursor_pos_window); | ||
469 | LLCoordGL cursor_pos_gl; | ||
470 | getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); | ||
471 | |||
472 | screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); | ||
473 | BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; | 499 | BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; |
474 | BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); | 500 | BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); |
475 | if (hovered) | 501 | if (hovered) |
@@ -536,21 +562,7 @@ void LLScrollbar::draw() | |||
536 | 562 | ||
537 | void LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) | 563 | void LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) |
538 | { | 564 | { |
539 | S32 new_pos = llclamp( mDocPos + delta, 0, getDocPosMax() ); | 565 | setDocPos(mDocPos + delta, update_thumb); |
540 | if( new_pos != mDocPos ) | ||
541 | { | ||
542 | mDocPos = new_pos; | ||
543 | } | ||
544 | |||
545 | if( mChangeCallback ) | ||
546 | { | ||
547 | mChangeCallback( mDocPos, this, mCallbackUserData ); | ||
548 | } | ||
549 | |||
550 | if( update_thumb ) | ||
551 | { | ||
552 | updateThumbRect(); | ||
553 | } | ||
554 | } | 566 | } |
555 | 567 | ||
556 | void LLScrollbar::setValue(const LLSD& value) | 568 | void LLScrollbar::setValue(const LLSD& value) |
@@ -566,22 +578,22 @@ BOOL LLScrollbar::handleKeyHere(KEY key, MASK mask) | |||
566 | switch( key ) | 578 | switch( key ) |
567 | { | 579 | { |
568 | case KEY_HOME: | 580 | case KEY_HOME: |
569 | changeLine( -mDocPos, TRUE ); | 581 | setDocPos( 0 ); |
570 | handled = TRUE; | 582 | handled = TRUE; |
571 | break; | 583 | break; |
572 | 584 | ||
573 | case KEY_END: | 585 | case KEY_END: |
574 | changeLine( getDocPosMax() - mDocPos, TRUE ); | 586 | setDocPos( getDocPosMax() ); |
575 | handled = TRUE; | 587 | handled = TRUE; |
576 | break; | 588 | break; |
577 | 589 | ||
578 | case KEY_DOWN: | 590 | case KEY_DOWN: |
579 | changeLine( mStepSize, TRUE ); | 591 | setDocPos( getDocPos() + mStepSize ); |
580 | handled = TRUE; | 592 | handled = TRUE; |
581 | break; | 593 | break; |
582 | 594 | ||
583 | case KEY_UP: | 595 | case KEY_UP: |
584 | changeLine( - mStepSize, TRUE ); | 596 | setDocPos( getDocPos() - mStepSize ); |
585 | handled = TRUE; | 597 | handled = TRUE; |
586 | break; | 598 | break; |
587 | 599 | ||
diff --git a/linden/indra/llui/llscrollbar.h b/linden/indra/llui/llscrollbar.h index 0703263..0bbf866 100644 --- a/linden/indra/llui/llscrollbar.h +++ b/linden/indra/llui/llscrollbar.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -81,7 +82,7 @@ public: | |||
81 | 82 | ||
82 | // How many "lines" the "document" has scrolled. | 83 | // How many "lines" the "document" has scrolled. |
83 | // 0 <= DocPos <= DocSize - DocVisibile | 84 | // 0 <= DocPos <= DocSize - DocVisibile |
84 | void setDocPos( S32 pos ); | 85 | void setDocPos( S32 pos, BOOL update_thumb = TRUE ); |
85 | S32 getDocPos() const { return mDocPos; } | 86 | S32 getDocPos() const { return mDocPos; } |
86 | 87 | ||
87 | BOOL isAtBeginning(); | 88 | BOOL isAtBeginning(); |
diff --git a/linden/indra/llui/llscrollcontainer.cpp b/linden/indra/llui/llscrollcontainer.cpp index f7c4200..cf03259 100644 --- a/linden/indra/llui/llscrollcontainer.cpp +++ b/linden/indra/llui/llscrollcontainer.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llscrollcontainer.h b/linden/indra/llui/llscrollcontainer.h index 80e67d2..70fc908 100644 --- a/linden/indra/llui/llscrollcontainer.h +++ b/linden/indra/llui/llscrollcontainer.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llscrollingpanellist.cpp b/linden/indra/llui/llscrollingpanellist.cpp index 0cd501c..05d0c6f 100644 --- a/linden/indra/llui/llscrollingpanellist.cpp +++ b/linden/indra/llui/llscrollingpanellist.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llscrollingpanellist.h b/linden/indra/llui/llscrollingpanellist.h index c96f12c..b9d7309 100644 --- a/linden/indra/llui/llscrollingpanellist.h +++ b/linden/indra/llui/llscrollingpanellist.h | |||
@@ -16,7 +16,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 19 | * online at |
20 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
20 | * | 21 | * |
21 | * By copying, modifying or distributing this software, you acknowledge | 22 | * By copying, modifying or distributing this software, you acknowledge |
22 | * 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/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp index 7dba55f..7b6c125 100644 --- a/linden/indra/llui/llscrolllistctrl.cpp +++ b/linden/indra/llui/llscrolllistctrl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -378,6 +379,22 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col | |||
378 | TRUE); | 379 | TRUE); |
379 | } | 380 | } |
380 | 381 | ||
382 | LLScrollListDate::LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible) | ||
383 | : LLScrollListText(date.asRFC1123(), font, width, font_style, font_alignment, color, use_color, visible), | ||
384 | mDate(date) | ||
385 | { | ||
386 | } | ||
387 | |||
388 | void LLScrollListDate::setValue(const LLSD& value) | ||
389 | { | ||
390 | mDate = value.asDate(); | ||
391 | LLScrollListText::setValue(mDate.asRFC1123()); | ||
392 | } | ||
393 | |||
394 | const LLSD LLScrollListDate::getValue() const | ||
395 | { | ||
396 | return mDate; | ||
397 | } | ||
381 | 398 | ||
382 | LLScrollListItem::~LLScrollListItem() | 399 | LLScrollListItem::~LLScrollListItem() |
383 | { | 400 | { |
@@ -578,6 +595,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, | |||
578 | mSearchColumn(0), | 595 | mSearchColumn(0), |
579 | mNumDynamicWidthColumns(0), | 596 | mNumDynamicWidthColumns(0), |
580 | mTotalStaticColumnWidth(0), | 597 | mTotalStaticColumnWidth(0), |
598 | mTotalColumnPadding(0), | ||
581 | mSorted(TRUE), | 599 | mSorted(TRUE), |
582 | mDirty(FALSE), | 600 | mDirty(FALSE), |
583 | mOriginalSelection(-1), | 601 | mOriginalSelection(-1), |
@@ -627,6 +645,28 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, | |||
627 | mLastSelected = NULL; | 645 | mLastSelected = NULL; |
628 | } | 646 | } |
629 | 647 | ||
648 | S32 LLScrollListCtrl::getSearchColumn() | ||
649 | { | ||
650 | // search for proper search column | ||
651 | if (mSearchColumn < 0) | ||
652 | { | ||
653 | LLScrollListItem* itemp = getFirstData(); | ||
654 | if (itemp) | ||
655 | { | ||
656 | for(S32 column = 0; column < getNumColumns(); column++) | ||
657 | { | ||
658 | LLScrollListCell* cell = itemp->getColumn(column); | ||
659 | if (cell && cell->isText()) | ||
660 | { | ||
661 | mSearchColumn = column; | ||
662 | break; | ||
663 | } | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | return llclamp(mSearchColumn, 0, getNumColumns()); | ||
668 | } | ||
669 | |||
630 | LLScrollListCtrl::~LLScrollListCtrl() | 670 | LLScrollListCtrl::~LLScrollListCtrl() |
631 | { | 671 | { |
632 | std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); | 672 | std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); |
@@ -890,8 +930,8 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r | |||
890 | // *TODO: Use bookkeeping to make this an incramental cost with item additions | 930 | // *TODO: Use bookkeeping to make this an incramental cost with item additions |
891 | void LLScrollListCtrl::calcColumnWidths() | 931 | void LLScrollListCtrl::calcColumnWidths() |
892 | { | 932 | { |
893 | const S32 HEADING_TEXT_PADDING = 30; | 933 | const S32 HEADING_TEXT_PADDING = 25; |
894 | const S32 COLUMN_TEXT_PADDING = 20; | 934 | const S32 COLUMN_TEXT_PADDING = 10; |
895 | 935 | ||
896 | mMaxContentWidth = 0; | 936 | mMaxContentWidth = 0; |
897 | 937 | ||
@@ -904,30 +944,27 @@ void LLScrollListCtrl::calcColumnWidths() | |||
904 | if (!column) continue; | 944 | if (!column) continue; |
905 | 945 | ||
906 | // update column width | 946 | // update column width |
907 | S32 new_width = column->mWidth; | 947 | S32 new_width = column->getWidth(); |
908 | if (column->mRelWidth >= 0) | 948 | if (column->mRelWidth >= 0) |
909 | { | 949 | { |
910 | new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth()); | 950 | new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth()); |
911 | } | 951 | } |
912 | else if (column->mDynamicWidth) | 952 | else if (column->mDynamicWidth) |
913 | { | 953 | { |
914 | new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; | 954 | new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns; |
915 | } | 955 | } |
916 | 956 | ||
917 | if (new_width != column->mWidth) | 957 | column->setWidth(new_width); |
918 | { | ||
919 | column->mWidth = new_width; | ||
920 | } | ||
921 | 958 | ||
922 | // update max content width for this column, by looking at all items | 959 | // update max content width for this column, by looking at all items |
923 | column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; | 960 | column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; |
924 | item_list::iterator iter; | 961 | item_list::iterator iter; |
925 | for (iter = mItemList.begin(); iter != mItemList.end(); iter++) | 962 | for (iter = mItemList.begin(); iter != mItemList.end(); iter++) |
926 | { | 963 | { |
927 | LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); | 964 | LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); |
928 | if (!cellp) continue; | 965 | if (!cellp) continue; |
929 | 966 | ||
930 | column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); | 967 | column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); |
931 | } | 968 | } |
932 | 969 | ||
933 | max_item_width += column->mMaxContentWidth; | 970 | max_item_width += column->mMaxContentWidth; |
@@ -971,28 +1008,13 @@ void LLScrollListCtrl::updateColumns() | |||
971 | { | 1008 | { |
972 | calcColumnWidths(); | 1009 | calcColumnWidths(); |
973 | 1010 | ||
974 | // propagate column widths to individual cells | ||
975 | item_list::iterator iter; | ||
976 | for (iter = mItemList.begin(); iter != mItemList.end(); iter++) | ||
977 | { | ||
978 | LLScrollListItem *itemp = *iter; | ||
979 | S32 num_cols = itemp->getNumColumns(); | ||
980 | S32 i = 0; | ||
981 | for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) | ||
982 | { | ||
983 | if (i >= (S32)mColumnsIndexed.size()) break; | ||
984 | |||
985 | cell->setWidth(mColumnsIndexed[i]->mWidth); | ||
986 | } | ||
987 | } | ||
988 | |||
989 | // update column headers | 1011 | // update column headers |
990 | std::vector<LLScrollListColumn*>::iterator column_ordered_it; | 1012 | std::vector<LLScrollListColumn*>::iterator column_ordered_it; |
991 | S32 left = mItemListRect.mLeft; | 1013 | S32 left = mItemListRect.mLeft; |
992 | LLColumnHeader* last_header = NULL; | 1014 | LLColumnHeader* last_header = NULL; |
993 | for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it) | 1015 | for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it) |
994 | { | 1016 | { |
995 | if ((*column_ordered_it)->mWidth < 0) | 1017 | if ((*column_ordered_it)->getWidth() < 0) |
996 | { | 1018 | { |
997 | // skip hidden columns | 1019 | // skip hidden columns |
998 | continue; | 1020 | continue; |
@@ -1001,9 +1023,11 @@ void LLScrollListCtrl::updateColumns() | |||
1001 | 1023 | ||
1002 | if (column->mHeader) | 1024 | if (column->mHeader) |
1003 | { | 1025 | { |
1026 | column->mHeader->updateResizeBars(); | ||
1027 | |||
1004 | last_header = column->mHeader; | 1028 | last_header = column->mHeader; |
1005 | S32 top = mItemListRect.mTop; | 1029 | S32 top = mItemListRect.mTop; |
1006 | S32 right = left + column->mWidth; | 1030 | S32 right = left + column->getWidth(); |
1007 | 1031 | ||
1008 | if (column->mIndex != (S32)mColumnsIndexed.size()-1) | 1032 | if (column->mIndex != (S32)mColumnsIndexed.size()-1) |
1009 | { | 1033 | { |
@@ -1021,14 +1045,30 @@ void LLScrollListCtrl::updateColumns() | |||
1021 | } | 1045 | } |
1022 | } | 1046 | } |
1023 | 1047 | ||
1024 | //FIXME: stretch the entire last column if it is resizable (gestures windows shows truncated text in last column) | ||
1025 | // expand last column header we encountered to full list width | 1048 | // expand last column header we encountered to full list width |
1026 | if (last_header) | 1049 | if (last_header && last_header->canResize()) |
1027 | { | 1050 | { |
1028 | S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft); | 1051 | S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft); |
1029 | last_header->reshape(new_width, last_header->getRect().getHeight()); | 1052 | last_header->reshape(new_width, last_header->getRect().getHeight()); |
1030 | last_header->setVisible(mDisplayColumnHeaders && new_width > 0); | 1053 | last_header->setVisible(mDisplayColumnHeaders && new_width > 0); |
1054 | last_header->getColumn()->setWidth(new_width); | ||
1055 | } | ||
1056 | |||
1057 | // propagate column widths to individual cells | ||
1058 | item_list::iterator iter; | ||
1059 | for (iter = mItemList.begin(); iter != mItemList.end(); iter++) | ||
1060 | { | ||
1061 | LLScrollListItem *itemp = *iter; | ||
1062 | S32 num_cols = itemp->getNumColumns(); | ||
1063 | S32 i = 0; | ||
1064 | for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) | ||
1065 | { | ||
1066 | if (i >= (S32)mColumnsIndexed.size()) break; | ||
1067 | |||
1068 | cell->setWidth(mColumnsIndexed[i]->getWidth()); | ||
1069 | } | ||
1031 | } | 1070 | } |
1071 | |||
1032 | } | 1072 | } |
1033 | 1073 | ||
1034 | void LLScrollListCtrl::setDisplayHeading(BOOL display) | 1074 | void LLScrollListCtrl::setDisplayHeading(BOOL display) |
@@ -1490,7 +1530,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen | |||
1490 | { | 1530 | { |
1491 | LLScrollListItem* item = *iter; | 1531 | LLScrollListItem* item = *iter; |
1492 | // Only select enabled items with matching names | 1532 | // Only select enabled items with matching names |
1493 | LLScrollListCell* cellp = item->getColumn(mSearchColumn); | 1533 | LLScrollListCell* cellp = item->getColumn(getSearchColumn()); |
1494 | BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE; | 1534 | BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE; |
1495 | if (select) | 1535 | if (select) |
1496 | { | 1536 | { |
@@ -1513,7 +1553,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen | |||
1513 | LLScrollListItem* item = *iter; | 1553 | LLScrollListItem* item = *iter; |
1514 | 1554 | ||
1515 | // Only select enabled items with matching names | 1555 | // Only select enabled items with matching names |
1516 | LLScrollListCell* cellp = item->getColumn(mSearchColumn); | 1556 | LLScrollListCell* cellp = item->getColumn(getSearchColumn()); |
1517 | if (!cellp) | 1557 | if (!cellp) |
1518 | { | 1558 | { |
1519 | continue; | 1559 | continue; |
@@ -1743,6 +1783,8 @@ void LLScrollListCtrl::drawItems() | |||
1743 | 1783 | ||
1744 | void LLScrollListCtrl::draw() | 1784 | void LLScrollListCtrl::draw() |
1745 | { | 1785 | { |
1786 | LLLocalClipRect clip(getLocalRect()); | ||
1787 | |||
1746 | // if user specifies sort, make sure it is maintained | 1788 | // if user specifies sort, make sure it is maintained |
1747 | if (needsSorting() && !isSorted()) | 1789 | if (needsSorting() && !isSorted()) |
1748 | { | 1790 | { |
@@ -1816,7 +1858,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti | |||
1816 | S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft; | 1858 | S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft; |
1817 | S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item)); | 1859 | S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item)); |
1818 | LLRect cell_rect; | 1860 | LLRect cell_rect; |
1819 | cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->mWidth, mLineHeight); | 1861 | cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight); |
1820 | // Convert rect local to screen coordinates | 1862 | // Convert rect local to screen coordinates |
1821 | localPointToScreen( | 1863 | localPointToScreen( |
1822 | cell_rect.mLeft, cell_rect.mBottom, | 1864 | cell_rect.mLeft, cell_rect.mBottom, |
@@ -2113,7 +2155,7 @@ S32 LLScrollListCtrl::getColumnIndexFromOffset(S32 x) | |||
2113 | ordered_columns_t::const_iterator end = mColumnsIndexed.end(); | 2155 | ordered_columns_t::const_iterator end = mColumnsIndexed.end(); |
2114 | for ( ; iter != end; ++iter) | 2156 | for ( ; iter != end; ++iter) |
2115 | { | 2157 | { |
2116 | width = (*iter)->mWidth + mColumnPadding; | 2158 | width = (*iter)->getWidth() + mColumnPadding; |
2117 | right += width; | 2159 | right += width; |
2118 | if (left <= x && x < right ) | 2160 | if (left <= x && x < right ) |
2119 | { | 2161 | { |
@@ -2140,7 +2182,7 @@ S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index) | |||
2140 | { | 2182 | { |
2141 | return column_offset; | 2183 | return column_offset; |
2142 | } | 2184 | } |
2143 | column_offset += (*iter)->mWidth + mColumnPadding; | 2185 | column_offset += (*iter)->getWidth() + mColumnPadding; |
2144 | } | 2186 | } |
2145 | 2187 | ||
2146 | // when running off the end, return the rightmost pixel | 2188 | // when running off the end, return the rightmost pixel |
@@ -2292,7 +2334,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) | |||
2292 | { | 2334 | { |
2293 | if (getFirstSelected()) | 2335 | if (getFirstSelected()) |
2294 | { | 2336 | { |
2295 | LLScrollListCell* cellp = getFirstSelected()->getColumn(mSearchColumn); | 2337 | LLScrollListCell* cellp = getFirstSelected()->getColumn(getSearchColumn()); |
2296 | if (cellp) | 2338 | if (cellp) |
2297 | { | 2339 | { |
2298 | cellp->highlightText(0, 0); | 2340 | cellp->highlightText(0, 0); |
@@ -2379,7 +2421,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) | |||
2379 | { | 2421 | { |
2380 | LLScrollListItem* item = *iter; | 2422 | LLScrollListItem* item = *iter; |
2381 | 2423 | ||
2382 | LLScrollListCell* cellp = item->getColumn(mSearchColumn); | 2424 | LLScrollListCell* cellp = item->getColumn(getSearchColumn()); |
2383 | if (cellp) | 2425 | if (cellp) |
2384 | { | 2426 | { |
2385 | // Only select enabled items with matching first characters | 2427 | // Only select enabled items with matching first characters |
@@ -2446,7 +2488,7 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it | |||
2446 | { | 2488 | { |
2447 | if (mLastSelected) | 2489 | if (mLastSelected) |
2448 | { | 2490 | { |
2449 | LLScrollListCell* cellp = mLastSelected->getColumn(mSearchColumn); | 2491 | LLScrollListCell* cellp = mLastSelected->getColumn(getSearchColumn()); |
2450 | if (cellp) | 2492 | if (cellp) |
2451 | { | 2493 | { |
2452 | cellp->highlightText(0, 0); | 2494 | cellp->highlightText(0, 0); |
@@ -2474,7 +2516,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp) | |||
2474 | } | 2516 | } |
2475 | 2517 | ||
2476 | itemp->setSelected(FALSE); | 2518 | itemp->setSelected(FALSE); |
2477 | LLScrollListCell* cellp = itemp->getColumn(mSearchColumn); | 2519 | LLScrollListCell* cellp = itemp->getColumn(getSearchColumn()); |
2478 | if (cellp) | 2520 | if (cellp) |
2479 | { | 2521 | { |
2480 | cellp->highlightText(0, 0); | 2522 | cellp->highlightText(0, 0); |
@@ -2501,9 +2543,14 @@ struct SameSortColumn | |||
2501 | bool operator()(std::pair<S32, BOOL> sort_column) { return sort_column.first == mColumn; } | 2543 | bool operator()(std::pair<S32, BOOL> sort_column) { return sort_column.first == mColumn; } |
2502 | }; | 2544 | }; |
2503 | 2545 | ||
2504 | BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending) | 2546 | BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) |
2505 | { | 2547 | { |
2506 | sort_column_t new_sort_column(column, ascending); | 2548 | LLScrollListColumn* sort_column = getColumn(column_idx); |
2549 | if (!sort_column) return FALSE; | ||
2550 | |||
2551 | sort_column->mSortAscending = ascending; | ||
2552 | |||
2553 | sort_column_t new_sort_column(column_idx, ascending); | ||
2507 | 2554 | ||
2508 | if (mSortColumns.empty()) | 2555 | if (mSortColumns.empty()) |
2509 | { | 2556 | { |
@@ -2517,7 +2564,7 @@ BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending) | |||
2517 | 2564 | ||
2518 | // remove any existing sort criterion referencing this column | 2565 | // remove any existing sort criterion referencing this column |
2519 | // and add the new one | 2566 | // and add the new one |
2520 | mSortColumns.erase(remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column)), mSortColumns.end()); | 2567 | mSortColumns.erase(remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column_idx)), mSortColumns.end()); |
2521 | mSortColumns.push_back(new_sort_column); | 2568 | mSortColumns.push_back(new_sort_column); |
2522 | 2569 | ||
2523 | // did the sort criteria change? | 2570 | // did the sort criteria change? |
@@ -2643,6 +2690,12 @@ void LLScrollListCtrl::scrollToShowSelected() | |||
2643 | } | 2690 | } |
2644 | } | 2691 | } |
2645 | 2692 | ||
2693 | void LLScrollListCtrl::updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width) | ||
2694 | { | ||
2695 | mTotalStaticColumnWidth += llmax(0, new_width) - llmax(0, col->getWidth()); | ||
2696 | } | ||
2697 | |||
2698 | |||
2646 | // virtual | 2699 | // virtual |
2647 | LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const | 2700 | LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const |
2648 | { | 2701 | { |
@@ -2689,7 +2742,7 @@ LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const | |||
2689 | 2742 | ||
2690 | child_node->createChild("name", TRUE)->setStringValue(column->mName); | 2743 | child_node->createChild("name", TRUE)->setStringValue(column->mName); |
2691 | child_node->createChild("label", TRUE)->setStringValue(column->mLabel); | 2744 | child_node->createChild("label", TRUE)->setStringValue(column->mLabel); |
2692 | child_node->createChild("width", TRUE)->setIntValue(column->mWidth); | 2745 | child_node->createChild("width", TRUE)->setIntValue(column->getWidth()); |
2693 | } | 2746 | } |
2694 | 2747 | ||
2695 | return node; | 2748 | return node; |
@@ -2813,15 +2866,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac | |||
2813 | 2866 | ||
2814 | scroll_list->setSearchColumn(search_column); | 2867 | scroll_list->setSearchColumn(search_column); |
2815 | 2868 | ||
2816 | if (sort_column >= 0) | ||
2817 | { | ||
2818 | scroll_list->sortByColumnIndex(sort_column, sort_ascending); | ||
2819 | } | ||
2820 | |||
2821 | LLSD columns; | 2869 | LLSD columns; |
2822 | S32 index = 0; | 2870 | S32 index = 0; |
2823 | LLXMLNodePtr child; | 2871 | LLXMLNodePtr child; |
2824 | S32 total_static = 0; | ||
2825 | for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) | 2872 | for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) |
2826 | { | 2873 | { |
2827 | if (child->hasName("column")) | 2874 | if (child->hasName("column")) |
@@ -2850,8 +2897,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac | |||
2850 | std::string tooltip; | 2897 | std::string tooltip; |
2851 | child->getAttributeString("tool_tip", tooltip); | 2898 | child->getAttributeString("tool_tip", tooltip); |
2852 | 2899 | ||
2853 | if(!columndynamicwidth) total_static += llmax(0, columnwidth); | ||
2854 | |||
2855 | F32 columnrelwidth = 0.f; | 2900 | F32 columnrelwidth = 0.f; |
2856 | child->getAttributeF32("relwidth", columnrelwidth); | 2901 | child->getAttributeF32("relwidth", columnrelwidth); |
2857 | 2902 | ||
@@ -2872,9 +2917,13 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac | |||
2872 | index++; | 2917 | index++; |
2873 | } | 2918 | } |
2874 | } | 2919 | } |
2875 | scroll_list->setTotalStaticColumnWidth(total_static); | ||
2876 | scroll_list->setColumnHeadings(columns); | 2920 | scroll_list->setColumnHeadings(columns); |
2877 | 2921 | ||
2922 | if (sort_column >= 0) | ||
2923 | { | ||
2924 | scroll_list->sortByColumnIndex(sort_column, sort_ascending); | ||
2925 | } | ||
2926 | |||
2878 | for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) | 2927 | for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) |
2879 | { | 2928 | { |
2880 | if (child->hasName("row")) | 2929 | if (child->hasName("row")) |
@@ -3019,22 +3068,26 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) | |||
3019 | if (mColumns.find(name) == mColumns.end()) | 3068 | if (mColumns.find(name) == mColumns.end()) |
3020 | { | 3069 | { |
3021 | // Add column | 3070 | // Add column |
3022 | mColumns[name] = LLScrollListColumn(column); | 3071 | mColumns[name] = LLScrollListColumn(column, this); |
3023 | LLScrollListColumn* new_column = &mColumns[name]; | 3072 | LLScrollListColumn* new_column = &mColumns[name]; |
3024 | new_column->mParentCtrl = this; | 3073 | new_column->mParentCtrl = this; |
3025 | new_column->mIndex = mColumns.size()-1; | 3074 | new_column->mIndex = mColumns.size()-1; |
3026 | 3075 | ||
3027 | // Add button | 3076 | // Add button |
3028 | if (new_column->mWidth > 0 || new_column->mRelWidth > 0 || new_column->mDynamicWidth) | 3077 | if (new_column->getWidth() > 0 || new_column->mRelWidth > 0 || new_column->mDynamicWidth) |
3029 | { | 3078 | { |
3079 | if (getNumColumns() > 0) | ||
3080 | { | ||
3081 | mTotalColumnPadding += mColumnPadding; | ||
3082 | } | ||
3030 | if (new_column->mRelWidth >= 0) | 3083 | if (new_column->mRelWidth >= 0) |
3031 | { | 3084 | { |
3032 | new_column->mWidth = (S32)llround(new_column->mRelWidth*mItemListRect.getWidth()); | 3085 | new_column->setWidth((S32)llround(new_column->mRelWidth*mItemListRect.getWidth())); |
3033 | } | 3086 | } |
3034 | else if(new_column->mDynamicWidth) | 3087 | else if(new_column->mDynamicWidth) |
3035 | { | 3088 | { |
3036 | mNumDynamicWidthColumns++; | 3089 | mNumDynamicWidthColumns++; |
3037 | new_column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; | 3090 | new_column->setWidth((mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns); |
3038 | } | 3091 | } |
3039 | S32 top = mItemListRect.mTop; | 3092 | S32 top = mItemListRect.mTop; |
3040 | S32 left = mItemListRect.mLeft; | 3093 | S32 left = mItemListRect.mLeft; |
@@ -3043,14 +3096,14 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) | |||
3043 | for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) | 3096 | for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) |
3044 | { | 3097 | { |
3045 | if (itor->second.mIndex < new_column->mIndex && | 3098 | if (itor->second.mIndex < new_column->mIndex && |
3046 | itor->second.mWidth > 0) | 3099 | itor->second.getWidth() > 0) |
3047 | { | 3100 | { |
3048 | left += itor->second.mWidth + mColumnPadding; | 3101 | left += itor->second.getWidth() + mColumnPadding; |
3049 | } | 3102 | } |
3050 | } | 3103 | } |
3051 | } | 3104 | } |
3052 | std::string button_name = "btn_" + name; | 3105 | std::string button_name = "btn_" + name; |
3053 | S32 right = left+new_column->mWidth; | 3106 | S32 right = left+new_column->getWidth(); |
3054 | if (new_column->mIndex != (S32)mColumns.size()-1) | 3107 | if (new_column->mIndex != (S32)mColumns.size()-1) |
3055 | { | 3108 | { |
3056 | right += mColumnPadding; | 3109 | right += mColumnPadding; |
@@ -3145,6 +3198,8 @@ void LLScrollListCtrl::clearColumns() | |||
3145 | } | 3198 | } |
3146 | mColumns.clear(); | 3199 | mColumns.clear(); |
3147 | mSortColumns.clear(); | 3200 | mSortColumns.clear(); |
3201 | mTotalStaticColumnWidth = 0; | ||
3202 | mTotalColumnPadding = 0; | ||
3148 | } | 3203 | } |
3149 | 3204 | ||
3150 | void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label) | 3205 | void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label) |
@@ -3244,7 +3299,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p | |||
3244 | } | 3299 | } |
3245 | 3300 | ||
3246 | S32 index = columnp->mIndex; | 3301 | S32 index = columnp->mIndex; |
3247 | S32 width = columnp->mWidth; | 3302 | S32 width = columnp->getWidth(); |
3248 | LLFontGL::HAlign font_alignment = columnp->mFontAlignment; | 3303 | LLFontGL::HAlign font_alignment = columnp->mFontAlignment; |
3249 | LLColor4 fcolor = LLColor4::black; | 3304 | LLColor4 fcolor = LLColor4::black; |
3250 | 3305 | ||
@@ -3301,6 +3356,19 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p | |||
3301 | } | 3356 | } |
3302 | new_item->setColumn(index, cell); | 3357 | new_item->setColumn(index, cell); |
3303 | } | 3358 | } |
3359 | else if (type == "date") | ||
3360 | { | ||
3361 | LLScrollListDate* cell = new LLScrollListDate(value.asDate(), font, width, font_style, font_alignment); | ||
3362 | if (has_color) | ||
3363 | { | ||
3364 | cell->setColor(color); | ||
3365 | } | ||
3366 | new_item->setColumn(index, cell); | ||
3367 | if (columnp->mHeader && !value.asString().empty()) | ||
3368 | { | ||
3369 | columnp->mHeader->setHasResizableElement(TRUE); | ||
3370 | } | ||
3371 | } | ||
3304 | else | 3372 | else |
3305 | { | 3373 | { |
3306 | LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE); | 3374 | LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE); |
@@ -3325,7 +3393,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p | |||
3325 | if (new_item->getColumn(column_idx) == NULL) | 3393 | if (new_item->getColumn(column_idx) == NULL) |
3326 | { | 3394 | { |
3327 | LLScrollListColumn* column_ptr = &column_it->second; | 3395 | LLScrollListColumn* column_ptr = &column_it->second; |
3328 | new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->mWidth, LLFontGL::NORMAL)); | 3396 | new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->getWidth(), LLFontGL::NORMAL)); |
3329 | } | 3397 | } |
3330 | } | 3398 | } |
3331 | 3399 | ||
@@ -3469,6 +3537,7 @@ LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLS | |||
3469 | mButton->setMouseDownCallback(onMouseDown); | 3537 | mButton->setMouseDownCallback(onMouseDown); |
3470 | 3538 | ||
3471 | mButton->setCallbackUserData(this); | 3539 | mButton->setCallbackUserData(this); |
3540 | mButton->setToolTip(label); | ||
3472 | 3541 | ||
3473 | mAscendingText = std::string("[LOW]...[HIGH](Ascending)"); // *TODO: Translate | 3542 | mAscendingText = std::string("[LOW]...[HIGH](Ascending)"); // *TODO: Translate |
3474 | mDescendingText = std::string("[HIGH]...[LOW](Descending)"); // *TODO: Translate | 3543 | mDescendingText = std::string("[HIGH]...[LOW](Descending)"); // *TODO: Translate |
@@ -3556,7 +3625,7 @@ void LLColumnHeader::onClick(void* user_data) | |||
3556 | 3625 | ||
3557 | LLScrollListCtrl::onClickColumn(column); | 3626 | LLScrollListCtrl::onClickColumn(column); |
3558 | 3627 | ||
3559 | // propage new sort order to sort order list | 3628 | // propagate new sort order to sort order list |
3560 | headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1); | 3629 | headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1); |
3561 | } | 3630 | } |
3562 | 3631 | ||
@@ -3642,11 +3711,11 @@ void LLColumnHeader::showList() | |||
3642 | descending_string = mDescendingText.getString(); | 3711 | descending_string = mDescendingText.getString(); |
3643 | } | 3712 | } |
3644 | 3713 | ||
3645 | S32 text_width = LLFontGL::sSansSerifSmall->getWidth(ascending_string); | 3714 | S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(ascending_string); |
3646 | text_width = llmax(text_width, LLFontGL::sSansSerifSmall->getWidth(descending_string)) + 10; | 3715 | text_width = llmax(text_width, LLFontGL::getFontSansSerifSmall()->getWidth(descending_string)) + 10; |
3647 | text_width = llmax(text_width, getRect().getWidth() - 30); | 3716 | text_width = llmax(text_width, getRect().getWidth() - 30); |
3648 | 3717 | ||
3649 | mList->getColumn(0)->mWidth = text_width; | 3718 | mList->getColumn(0)->setWidth(text_width); |
3650 | ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string); | 3719 | ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string); |
3651 | ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string); | 3720 | ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string); |
3652 | 3721 | ||
@@ -3688,7 +3757,7 @@ LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_d | |||
3688 | llassert(snap_edge == SNAP_RIGHT); | 3757 | llassert(snap_edge == SNAP_RIGHT); |
3689 | 3758 | ||
3690 | // use higher snap threshold for column headers | 3759 | // use higher snap threshold for column headers |
3691 | threshold = llmin(threshold, 15); | 3760 | threshold = llmin(threshold, 10); |
3692 | 3761 | ||
3693 | LLRect snap_rect = getSnapRect(); | 3762 | LLRect snap_rect = getSnapRect(); |
3694 | 3763 | ||
@@ -3727,47 +3796,48 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect) | |||
3727 | 3796 | ||
3728 | if (delta_width != 0) | 3797 | if (delta_width != 0) |
3729 | { | 3798 | { |
3730 | S32 remaining_width = delta_width; | 3799 | S32 remaining_width = -delta_width; |
3731 | S32 col; | 3800 | S32 col; |
3732 | for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++) | 3801 | for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++) |
3733 | { | 3802 | { |
3734 | LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); | 3803 | LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); |
3735 | if (!columnp) break; | 3804 | if (!columnp) continue; |
3736 | 3805 | ||
3737 | if (columnp->mHeader && columnp->mHeader->canResize()) | 3806 | if (columnp->mHeader && columnp->mHeader->canResize()) |
3738 | { | 3807 | { |
3739 | // how many pixels in width can this column afford to give up? | 3808 | // how many pixels in width can this column afford to give up? |
3740 | S32 resize_buffer_amt = llmax(0, columnp->mWidth - MIN_COLUMN_WIDTH); | 3809 | S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH); |
3741 | 3810 | ||
3742 | // user shrinking column, need to add width to other columns | 3811 | // user shrinking column, need to add width to other columns |
3743 | if (delta_width < 0) | 3812 | if (delta_width < 0) |
3744 | { | 3813 | { |
3745 | if (!columnp->mDynamicWidth && columnp->mWidth > 0) | 3814 | if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0) |
3746 | { | 3815 | { |
3747 | // statically sized column, give all remaining width to this column | 3816 | // statically sized column, give all remaining width to this column |
3748 | columnp->mWidth -= remaining_width; | 3817 | columnp->setWidth(columnp->getWidth() + remaining_width); |
3749 | if (columnp->mRelWidth > 0.f) | 3818 | if (columnp->mRelWidth > 0.f) |
3750 | { | 3819 | { |
3751 | columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); | 3820 | columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); |
3752 | } | 3821 | } |
3822 | // all padding went to this widget, we're done | ||
3823 | break; | ||
3753 | } | 3824 | } |
3754 | break; | ||
3755 | } | 3825 | } |
3756 | else | 3826 | else |
3757 | { | 3827 | { |
3758 | // user growing column, need to take width from other columns | 3828 | // user growing column, need to take width from other columns |
3759 | remaining_width -= resize_buffer_amt; | 3829 | remaining_width += resize_buffer_amt; |
3760 | 3830 | ||
3761 | if (!columnp->mDynamicWidth && columnp->mWidth > 0) | 3831 | if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0) |
3762 | { | 3832 | { |
3763 | columnp->mWidth -= llmin(columnp->mWidth - MIN_COLUMN_WIDTH, delta_width); | 3833 | columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width)); |
3764 | if (columnp->mRelWidth > 0.f) | 3834 | if (columnp->mRelWidth > 0.f) |
3765 | { | 3835 | { |
3766 | columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); | 3836 | columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); |
3767 | } | 3837 | } |
3768 | } | 3838 | } |
3769 | 3839 | ||
3770 | if (remaining_width <= 0) | 3840 | if (remaining_width >= 0) |
3771 | { | 3841 | { |
3772 | // width sucked up from neighboring columns, done | 3842 | // width sucked up from neighboring columns, done |
3773 | break; | 3843 | break; |
@@ -3779,14 +3849,14 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect) | |||
3779 | // clamp resize amount to maximum that can be absorbed by other columns | 3849 | // clamp resize amount to maximum that can be absorbed by other columns |
3780 | if (delta_width > 0) | 3850 | if (delta_width > 0) |
3781 | { | 3851 | { |
3782 | delta_width -= llmax(remaining_width, 0); | 3852 | delta_width += llmin(remaining_width, 0); |
3783 | } | 3853 | } |
3784 | 3854 | ||
3785 | // propagate constrained delta_width to new width for this column | 3855 | // propagate constrained delta_width to new width for this column |
3786 | new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding(); | 3856 | new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding(); |
3787 | 3857 | ||
3788 | // use requested width | 3858 | // use requested width |
3789 | mColumn->mWidth = new_width; | 3859 | mColumn->setWidth(new_width); |
3790 | 3860 | ||
3791 | // update proportional spacing | 3861 | // update proportional spacing |
3792 | if (mColumn->mRelWidth > 0.f) | 3862 | if (mColumn->mRelWidth > 0.f) |
@@ -3804,36 +3874,40 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect) | |||
3804 | void LLColumnHeader::setHasResizableElement(BOOL resizable) | 3874 | void LLColumnHeader::setHasResizableElement(BOOL resizable) |
3805 | { | 3875 | { |
3806 | // for now, dynamically spaced columns can't be resized | 3876 | // for now, dynamically spaced columns can't be resized |
3807 | if (mColumn->mDynamicWidth) return; | 3877 | // if (mColumn->mDynamicWidth) return; |
3808 | 3878 | ||
3809 | if (resizable != mHasResizableElement) | 3879 | if (mHasResizableElement != resizable) |
3810 | { | 3880 | { |
3881 | mColumn->mParentCtrl->dirtyColumns(); | ||
3811 | mHasResizableElement = resizable; | 3882 | mHasResizableElement = resizable; |
3883 | } | ||
3884 | } | ||
3812 | 3885 | ||
3813 | S32 num_resizable_columns = 0; | 3886 | void LLColumnHeader::updateResizeBars() |
3814 | S32 col; | 3887 | { |
3815 | for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) | 3888 | S32 num_resizable_columns = 0; |
3889 | S32 col; | ||
3890 | for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) | ||
3891 | { | ||
3892 | LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); | ||
3893 | if (columnp->mHeader && columnp->mHeader->canResize()) | ||
3816 | { | 3894 | { |
3817 | LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); | 3895 | num_resizable_columns++; |
3818 | if (columnp->mHeader && columnp->mHeader->canResize()) | ||
3819 | { | ||
3820 | num_resizable_columns++; | ||
3821 | } | ||
3822 | } | 3896 | } |
3897 | } | ||
3823 | 3898 | ||
3824 | S32 num_resizers_enabled = 0; | 3899 | S32 num_resizers_enabled = 0; |
3825 | 3900 | ||
3826 | // now enable/disable resize handles on resizable columns if we have at least two | 3901 | // now enable/disable resize handles on resizable columns if we have at least two |
3827 | for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) | 3902 | for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) |
3903 | { | ||
3904 | LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); | ||
3905 | if (!columnp->mHeader) continue; | ||
3906 | BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize(); | ||
3907 | columnp->mHeader->enableResizeBar(enable); | ||
3908 | if (enable) | ||
3828 | { | 3909 | { |
3829 | LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); | 3910 | num_resizers_enabled++; |
3830 | if (!columnp->mHeader) continue; | ||
3831 | BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize(); | ||
3832 | columnp->mHeader->enableResizeBar(enable); | ||
3833 | if (enable) | ||
3834 | { | ||
3835 | num_resizers_enabled++; | ||
3836 | } | ||
3837 | } | 3911 | } |
3838 | } | 3912 | } |
3839 | } | 3913 | } |
@@ -3841,7 +3915,7 @@ void LLColumnHeader::setHasResizableElement(BOOL resizable) | |||
3841 | void LLColumnHeader::enableResizeBar(BOOL enable) | 3915 | void LLColumnHeader::enableResizeBar(BOOL enable) |
3842 | { | 3916 | { |
3843 | // for now, dynamically spaced columns can't be resized | 3917 | // for now, dynamically spaced columns can't be resized |
3844 | if (!mColumn->mDynamicWidth) | 3918 | //if (!mColumn->mDynamicWidth) |
3845 | { | 3919 | { |
3846 | mResizeBar->setEnabled(enable); | 3920 | mResizeBar->setEnabled(enable); |
3847 | } | 3921 | } |
@@ -3851,3 +3925,78 @@ BOOL LLColumnHeader::canResize() | |||
3851 | { | 3925 | { |
3852 | return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); | 3926 | return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); |
3853 | } | 3927 | } |
3928 | |||
3929 | void LLScrollListColumn::setWidth(S32 width) | ||
3930 | { | ||
3931 | if (!mDynamicWidth && mRelWidth <= 0.f) | ||
3932 | { | ||
3933 | mParentCtrl->updateStaticColumnWidth(this, width); | ||
3934 | } | ||
3935 | mWidth = width; | ||
3936 | } | ||
3937 | |||
3938 | // Default constructor | ||
3939 | LLScrollListColumn::LLScrollListColumn() : | ||
3940 | mName(), | ||
3941 | mSortingColumn(), | ||
3942 | mSortAscending(TRUE), | ||
3943 | mLabel(), | ||
3944 | mWidth(-1), | ||
3945 | mRelWidth(-1.0), | ||
3946 | mDynamicWidth(FALSE), | ||
3947 | mMaxContentWidth(0), | ||
3948 | mIndex(-1), | ||
3949 | mParentCtrl(NULL), | ||
3950 | mHeader(NULL), | ||
3951 | mFontAlignment(LLFontGL::LEFT) | ||
3952 | { } | ||
3953 | |||
3954 | LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) : | ||
3955 | mWidth(0), | ||
3956 | mIndex (-1), | ||
3957 | mParentCtrl(parent), | ||
3958 | mHeader(NULL), | ||
3959 | mMaxContentWidth(0), | ||
3960 | mDynamicWidth(FALSE), | ||
3961 | mRelWidth(-1.f) | ||
3962 | { | ||
3963 | mName = sd.get("name").asString(); | ||
3964 | mSortingColumn = mName; | ||
3965 | if (sd.has("sort")) | ||
3966 | { | ||
3967 | mSortingColumn = sd.get("sort").asString(); | ||
3968 | } | ||
3969 | mSortAscending = TRUE; | ||
3970 | if (sd.has("sort_ascending")) | ||
3971 | { | ||
3972 | mSortAscending = sd.get("sort_ascending").asBoolean(); | ||
3973 | } | ||
3974 | mLabel = sd.get("label").asString(); | ||
3975 | if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0) | ||
3976 | { | ||
3977 | mRelWidth = (F32)sd.get("relwidth").asReal(); | ||
3978 | if (mRelWidth < 0) mRelWidth = 0; | ||
3979 | if (mRelWidth > 1) mRelWidth = 1; | ||
3980 | mDynamicWidth = FALSE; | ||
3981 | } | ||
3982 | else if(sd.has("dynamicwidth") && (BOOL)sd.get("dynamicwidth").asBoolean() == TRUE) | ||
3983 | { | ||
3984 | mDynamicWidth = TRUE; | ||
3985 | mRelWidth = -1; | ||
3986 | } | ||
3987 | else | ||
3988 | { | ||
3989 | |||
3990 | setWidth(sd.get("width").asInteger()); | ||
3991 | } | ||
3992 | |||
3993 | if (sd.has("halign")) | ||
3994 | { | ||
3995 | mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER); | ||
3996 | } | ||
3997 | else | ||
3998 | { | ||
3999 | mFontAlignment = LLFontGL::LEFT; | ||
4000 | } | ||
4001 | |||
4002 | } | ||
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h index f276562..72d8894 100644 --- a/linden/indra/llui/llscrolllistctrl.h +++ b/linden/indra/llui/llscrolllistctrl.h | |||
@@ -16,7 +16,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 19 | * online at |
20 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
20 | * | 21 | * |
21 | * By copying, modifying or distributing this software, you acknowledge | 22 | * By copying, modifying or distributing this software, you acknowledge |
22 | * that you have read and understood your obligations described above, | 23 | * that you have read and understood your obligations described above, |
@@ -47,6 +48,7 @@ | |||
47 | #include "llcombobox.h" | 48 | #include "llcombobox.h" |
48 | #include "llscrollbar.h" | 49 | #include "llscrollbar.h" |
49 | #include "llresizebar.h" | 50 | #include "llresizebar.h" |
51 | #include "lldate.h" | ||
50 | 52 | ||
51 | /* | 53 | /* |
52 | * Represents a cell in a scrollable table. | 54 | * Represents a cell in a scrollable table. |
@@ -133,6 +135,18 @@ private: | |||
133 | static U32 sCount; | 135 | static U32 sCount; |
134 | }; | 136 | }; |
135 | 137 | ||
138 | |||
139 | class LLScrollListDate : public LLScrollListText | ||
140 | { | ||
141 | public: | ||
142 | LLScrollListDate( const LLDate& date, 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); | ||
143 | virtual void setValue(const LLSD& value); | ||
144 | virtual const LLSD getValue() const; | ||
145 | |||
146 | private: | ||
147 | LLDate mDate; | ||
148 | }; | ||
149 | |||
136 | /* | 150 | /* |
137 | * Cell displaying an image. | 151 | * Cell displaying an image. |
138 | */ | 152 | */ |
@@ -185,88 +199,11 @@ private: | |||
185 | class LLScrollListColumn | 199 | class LLScrollListColumn |
186 | { | 200 | { |
187 | public: | 201 | public: |
188 | // Default constructor | 202 | LLScrollListColumn(); |
189 | LLScrollListColumn() : | 203 | LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent); |
190 | mName(), | 204 | |
191 | mSortingColumn(), | 205 | void setWidth(S32 width); |
192 | mSortAscending(TRUE), | 206 | S32 getWidth() const { return mWidth; } |
193 | mLabel(), | ||
194 | mWidth(-1), | ||
195 | mRelWidth(-1.0), | ||
196 | mDynamicWidth(FALSE), | ||
197 | mMaxContentWidth(0), | ||
198 | mIndex(-1), | ||
199 | mParentCtrl(NULL), | ||
200 | mHeader(NULL), | ||
201 | mFontAlignment(LLFontGL::LEFT) | ||
202 | { } | ||
203 | |||
204 | LLScrollListColumn(std::string name, std::string label, S32 width, F32 relwidth) : | ||
205 | mName(name), | ||
206 | mSortingColumn(name), | ||
207 | mSortAscending(TRUE), | ||
208 | mLabel(label), | ||
209 | mWidth(width), | ||
210 | mRelWidth(relwidth), | ||
211 | mDynamicWidth(FALSE), | ||
212 | mMaxContentWidth(0), | ||
213 | mIndex(-1), | ||
214 | mParentCtrl(NULL), | ||
215 | mHeader(NULL), | ||
216 | mFontAlignment(LLFontGL::LEFT) | ||
217 | { } | ||
218 | |||
219 | LLScrollListColumn(const LLSD &sd) | ||
220 | { | ||
221 | mMaxContentWidth = 0; | ||
222 | |||
223 | mName = sd.get("name").asString(); | ||
224 | mSortingColumn = mName; | ||
225 | if (sd.has("sort")) | ||
226 | { | ||
227 | mSortingColumn = sd.get("sort").asString(); | ||
228 | } | ||
229 | mSortAscending = TRUE; | ||
230 | if (sd.has("sort_ascending")) | ||
231 | { | ||
232 | mSortAscending = sd.get("sort_ascending").asBoolean(); | ||
233 | } | ||
234 | mLabel = sd.get("label").asString(); | ||
235 | if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0) | ||
236 | { | ||
237 | mRelWidth = (F32)sd.get("relwidth").asReal(); | ||
238 | if (mRelWidth < 0) mRelWidth = 0; | ||
239 | if (mRelWidth > 1) mRelWidth = 1; | ||
240 | mDynamicWidth = FALSE; | ||
241 | mWidth = 0; | ||
242 | } | ||
243 | else if(sd.has("dynamicwidth") && (BOOL)sd.get("dynamicwidth").asBoolean() == TRUE) | ||
244 | { | ||
245 | mDynamicWidth = TRUE; | ||
246 | mRelWidth = -1; | ||
247 | mWidth = 0; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | mWidth = sd.get("width").asInteger(); | ||
252 | mDynamicWidth = FALSE; | ||
253 | mRelWidth = -1; | ||
254 | } | ||
255 | |||
256 | if (sd.has("halign")) | ||
257 | { | ||
258 | mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER); | ||
259 | } | ||
260 | else | ||
261 | { | ||
262 | mFontAlignment = LLFontGL::LEFT; | ||
263 | } | ||
264 | |||
265 | mIndex = -1; | ||
266 | mParentCtrl = NULL; | ||
267 | mHeader = NULL; | ||
268 | mFontAlignment = LLFontGL::LEFT; | ||
269 | } | ||
270 | 207 | ||
271 | // Public data is fine so long as this remains a simple struct-like data class. | 208 | // Public data is fine so long as this remains a simple struct-like data class. |
272 | // If it ever gets any smarter than that, these should all become private | 209 | // If it ever gets any smarter than that, these should all become private |
@@ -275,7 +212,6 @@ public: | |||
275 | std::string mSortingColumn; | 212 | std::string mSortingColumn; |
276 | BOOL mSortAscending; | 213 | BOOL mSortAscending; |
277 | std::string mLabel; | 214 | std::string mLabel; |
278 | S32 mWidth; | ||
279 | F32 mRelWidth; | 215 | F32 mRelWidth; |
280 | BOOL mDynamicWidth; | 216 | BOOL mDynamicWidth; |
281 | S32 mMaxContentWidth; | 217 | S32 mMaxContentWidth; |
@@ -283,6 +219,10 @@ public: | |||
283 | LLScrollListCtrl* mParentCtrl; | 219 | LLScrollListCtrl* mParentCtrl; |
284 | class LLColumnHeader* mHeader; | 220 | class LLColumnHeader* mHeader; |
285 | LLFontGL::HAlign mFontAlignment; | 221 | LLFontGL::HAlign mFontAlignment; |
222 | |||
223 | private: | ||
224 | S32 mWidth; | ||
225 | |||
286 | }; | 226 | }; |
287 | 227 | ||
288 | class LLColumnHeader : public LLComboBox | 228 | class LLColumnHeader : public LLComboBox |
@@ -301,6 +241,7 @@ public: | |||
301 | void setImage(const std::string &image_name); | 241 | void setImage(const std::string &image_name); |
302 | LLScrollListColumn* getColumn() { return mColumn; } | 242 | LLScrollListColumn* getColumn() { return mColumn; } |
303 | void setHasResizableElement(BOOL resizable); | 243 | void setHasResizableElement(BOOL resizable); |
244 | void updateResizeBars(); | ||
304 | BOOL canResize(); | 245 | BOOL canResize(); |
305 | void enableResizeBar(BOOL enable); | 246 | void enableResizeBar(BOOL enable); |
306 | std::string getLabel() { return mOrigLabel; } | 247 | std::string getLabel() { return mOrigLabel; } |
@@ -551,8 +492,7 @@ public: | |||
551 | 492 | ||
552 | virtual S32 getScrollPos() const; | 493 | virtual S32 getScrollPos() const; |
553 | virtual void setScrollPos( S32 pos ); | 494 | virtual void setScrollPos( S32 pos ); |
554 | 495 | S32 getSearchColumn(); | |
555 | S32 getSearchColumn() { return mSearchColumn; } | ||
556 | void setSearchColumn(S32 column) { mSearchColumn = column; } | 496 | void setSearchColumn(S32 column) { mSearchColumn = column; } |
557 | S32 getColumnIndexFromOffset(S32 x); | 497 | S32 getColumnIndexFromOffset(S32 x); |
558 | S32 getColumnOffsetFromIndex(S32 index); | 498 | S32 getColumnOffsetFromIndex(S32 index); |
@@ -613,8 +553,9 @@ public: | |||
613 | virtual void deselect(); | 553 | virtual void deselect(); |
614 | virtual BOOL canDeselect() const; | 554 | virtual BOOL canDeselect() const; |
615 | 555 | ||
616 | void setNumDynamicColumns(int num) { mNumDynamicWidthColumns = num; } | 556 | void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; } |
617 | void setTotalStaticColumnWidth(int width) { mTotalStaticColumnWidth = width; } | 557 | void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width); |
558 | S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; } | ||
618 | 559 | ||
619 | std::string getSortColumnName(); | 560 | std::string getSortColumnName(); |
620 | BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } | 561 | BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } |
@@ -719,6 +660,7 @@ private: | |||
719 | S32 mSearchColumn; | 660 | S32 mSearchColumn; |
720 | S32 mNumDynamicWidthColumns; | 661 | S32 mNumDynamicWidthColumns; |
721 | S32 mTotalStaticColumnWidth; | 662 | S32 mTotalStaticColumnWidth; |
663 | S32 mTotalColumnPadding; | ||
722 | 664 | ||
723 | BOOL mSorted; | 665 | BOOL mSorted; |
724 | 666 | ||
diff --git a/linden/indra/llui/llslider.cpp b/linden/indra/llui/llslider.cpp index 51b96c1..4dfc904 100644 --- a/linden/indra/llui/llslider.cpp +++ b/linden/indra/llui/llslider.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llslider.h b/linden/indra/llui/llslider.h index 94f5992..154685f 100644 --- a/linden/indra/llui/llslider.h +++ b/linden/indra/llui/llslider.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp index 477003b..31baddd 100644 --- a/linden/indra/llui/llsliderctrl.cpp +++ b/linden/indra/llui/llsliderctrl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -463,7 +464,7 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory | |||
463 | // HACK: Font might not be specified. | 464 | // HACK: Font might not be specified. |
464 | if (!font) | 465 | if (!font) |
465 | { | 466 | { |
466 | font = LLFontGL::sSansSerifSmall; | 467 | font = LLFontGL::getFontSansSerifSmall(); |
467 | } | 468 | } |
468 | 469 | ||
469 | S32 label_width = 0; | 470 | S32 label_width = 0; |
diff --git a/linden/indra/llui/llsliderctrl.h b/linden/indra/llui/llsliderctrl.h index 56f4661..272dd7f 100644 --- a/linden/indra/llui/llsliderctrl.h +++ b/linden/indra/llui/llsliderctrl.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llspinctrl.cpp b/linden/indra/llui/llspinctrl.cpp index e1b47eb..c54a2cd 100644 --- a/linden/indra/llui/llspinctrl.cpp +++ b/linden/indra/llui/llspinctrl.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -98,7 +99,7 @@ LLSpinCtrl::LLSpinCtrl( const std::string& name, const LLRect& rect, const std:: | |||
98 | out_id, | 99 | out_id, |
99 | in_id, | 100 | in_id, |
100 | LLStringUtil::null, | 101 | LLStringUtil::null, |
101 | &LLSpinCtrl::onUpBtn, this, LLFontGL::sSansSerif ); | 102 | &LLSpinCtrl::onUpBtn, this, LLFontGL::getFontSansSerif() ); |
102 | mUpBtn->setFollowsLeft(); | 103 | mUpBtn->setFollowsLeft(); |
103 | mUpBtn->setFollowsBottom(); | 104 | mUpBtn->setFollowsBottom(); |
104 | mUpBtn->setHeldDownCallback( &LLSpinCtrl::onUpBtn ); | 105 | mUpBtn->setHeldDownCallback( &LLSpinCtrl::onUpBtn ); |
@@ -112,7 +113,7 @@ LLSpinCtrl::LLSpinCtrl( const std::string& name, const LLRect& rect, const std:: | |||
112 | out_id, | 113 | out_id, |
113 | in_id, | 114 | in_id, |
114 | LLStringUtil::null, | 115 | LLStringUtil::null, |
115 | &LLSpinCtrl::onDownBtn, this, LLFontGL::sSansSerif ); | 116 | &LLSpinCtrl::onDownBtn, this, LLFontGL::getFontSansSerif() ); |
116 | mDownBtn->setFollowsLeft(); | 117 | mDownBtn->setFollowsLeft(); |
117 | mDownBtn->setFollowsBottom(); | 118 | mDownBtn->setFollowsBottom(); |
118 | mDownBtn->setHeldDownCallback( &LLSpinCtrl::onDownBtn ); | 119 | mDownBtn->setHeldDownCallback( &LLSpinCtrl::onDownBtn ); |
diff --git a/linden/indra/llui/llspinctrl.h b/linden/indra/llui/llspinctrl.h index 1a96767..dfd0eb3 100644 --- a/linden/indra/llui/llspinctrl.h +++ b/linden/indra/llui/llspinctrl.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -81,6 +82,7 @@ public: | |||
81 | virtual void setFocus( BOOL b ); | 82 | virtual void setFocus( BOOL b ); |
82 | virtual void clear(); | 83 | virtual void clear(); |
83 | virtual BOOL isDirty() const { return( mValue != mInitialValue ); } | 84 | virtual BOOL isDirty() const { return( mValue != mInitialValue ); } |
85 | virtual void resetDirty() { mInitialValue = mValue; } | ||
84 | 86 | ||
85 | virtual void setPrecision(S32 precision); | 87 | virtual void setPrecision(S32 precision); |
86 | virtual void setMinValue(F32 min) { mMinValue = min; } | 88 | virtual void setMinValue(F32 min) { mMinValue = min; } |
diff --git a/linden/indra/llui/llstyle.cpp b/linden/indra/llui/llstyle.cpp index fc6c14e..a716cbb 100644 --- a/linden/indra/llui/llstyle.cpp +++ b/linden/indra/llui/llstyle.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llstyle.h b/linden/indra/llui/llstyle.h index 8dc1a40..3ad379c 100644 --- a/linden/indra/llui/llstyle.h +++ b/linden/indra/llui/llstyle.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lltabcontainer.cpp b/linden/indra/llui/lltabcontainer.cpp index 6b028d4..f416948 100644 --- a/linden/indra/llui/lltabcontainer.cpp +++ b/linden/indra/llui/lltabcontainer.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -70,6 +71,7 @@ LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabP | |||
70 | : | 71 | : |
71 | LLPanel(name, rect, bordered), | 72 | LLPanel(name, rect, bordered), |
72 | mCurrentTabIdx(-1), | 73 | mCurrentTabIdx(-1), |
74 | mNextTabIdx(-1), | ||
73 | mTabsHidden(FALSE), | 75 | mTabsHidden(FALSE), |
74 | mScrolled(FALSE), | 76 | mScrolled(FALSE), |
75 | mScrollPos(0), | 77 | mScrollPos(0), |
@@ -1149,9 +1151,37 @@ BOOL LLTabContainer::selectTab(S32 which) | |||
1149 | { | 1151 | { |
1150 | return FALSE; | 1152 | return FALSE; |
1151 | } | 1153 | } |
1152 | 1154 | ||
1155 | if (!selected_tuple->mPrecommitChangeCallback) | ||
1156 | { | ||
1157 | return setTab(which); | ||
1158 | } | ||
1159 | |||
1160 | mNextTabIdx = which; | ||
1161 | selected_tuple->mPrecommitChangeCallback(selected_tuple->mUserData, false); | ||
1162 | return TRUE; | ||
1163 | } | ||
1164 | |||
1165 | BOOL LLTabContainer::setTab(S32 which) | ||
1166 | { | ||
1167 | if (which == -1) | ||
1168 | { | ||
1169 | if (mNextTabIdx == -1) | ||
1170 | { | ||
1171 | return FALSE; | ||
1172 | } | ||
1173 | which = mNextTabIdx; | ||
1174 | mNextTabIdx = -1; | ||
1175 | } | ||
1176 | |||
1177 | LLTabTuple* selected_tuple = getTab(which); | ||
1178 | if (!selected_tuple) | ||
1179 | { | ||
1180 | return FALSE; | ||
1181 | } | ||
1182 | |||
1153 | BOOL is_visible = FALSE; | 1183 | BOOL is_visible = FALSE; |
1154 | if (getTab(which)->mButton->getEnabled()) | 1184 | if (selected_tuple->mButton->getEnabled()) |
1155 | { | 1185 | { |
1156 | setCurrentPanelIndex(which); | 1186 | setCurrentPanelIndex(which); |
1157 | 1187 | ||
@@ -1331,6 +1361,15 @@ void LLTabContainer::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(v | |||
1331 | } | 1361 | } |
1332 | } | 1362 | } |
1333 | 1363 | ||
1364 | void LLTabContainer::setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool)) | ||
1365 | { | ||
1366 | LLTabTuple* tuplep = getTabByPanel(tab); | ||
1367 | if (tuplep) | ||
1368 | { | ||
1369 | tuplep->mPrecommitChangeCallback = on_precommit; | ||
1370 | } | ||
1371 | } | ||
1372 | |||
1334 | void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata) | 1373 | void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata) |
1335 | { | 1374 | { |
1336 | LLTabTuple* tuplep = getTabByPanel(tab); | 1375 | LLTabTuple* tuplep = getTabByPanel(tab); |
@@ -1370,11 +1409,6 @@ void LLTabContainer::onTabBtn( void* userdata ) | |||
1370 | LLTabTuple* tuple = (LLTabTuple*) userdata; | 1409 | LLTabTuple* tuple = (LLTabTuple*) userdata; |
1371 | LLTabContainer* self = tuple->mTabContainer; | 1410 | LLTabContainer* self = tuple->mTabContainer; |
1372 | self->selectTabPanel( tuple->mTabPanel ); | 1411 | self->selectTabPanel( tuple->mTabPanel ); |
1373 | |||
1374 | if( tuple->mOnChangeCallback ) | ||
1375 | { | ||
1376 | tuple->mOnChangeCallback( tuple->mUserData, true ); | ||
1377 | } | ||
1378 | 1412 | ||
1379 | tuple->mTabPanel->setFocus(TRUE); | 1413 | tuple->mTabPanel->setFocus(TRUE); |
1380 | } | 1414 | } |
@@ -1624,14 +1658,14 @@ void LLTabContainer::initButtons() | |||
1624 | in_id = "UIImgBtnJumpLeftInUUID"; | 1658 | in_id = "UIImgBtnJumpLeftInUUID"; |
1625 | mJumpPrevArrowBtn = new LLButton(std::string("Jump Left Arrow"), jump_left_arrow_btn_rect, | 1659 | mJumpPrevArrowBtn = new LLButton(std::string("Jump Left Arrow"), jump_left_arrow_btn_rect, |
1626 | out_id, in_id, LLStringUtil::null, | 1660 | out_id, in_id, LLStringUtil::null, |
1627 | &LLTabContainer::onJumpFirstBtn, this, LLFontGL::sSansSerif ); | 1661 | &LLTabContainer::onJumpFirstBtn, this, LLFontGL::getFontSansSerif() ); |
1628 | mJumpPrevArrowBtn->setFollowsLeft(); | 1662 | mJumpPrevArrowBtn->setFollowsLeft(); |
1629 | 1663 | ||
1630 | out_id = "UIImgBtnScrollLeftOutUUID"; | 1664 | out_id = "UIImgBtnScrollLeftOutUUID"; |
1631 | in_id = "UIImgBtnScrollLeftInUUID"; | 1665 | in_id = "UIImgBtnScrollLeftInUUID"; |
1632 | mPrevArrowBtn = new LLButton(std::string("Left Arrow"), left_arrow_btn_rect, | 1666 | mPrevArrowBtn = new LLButton(std::string("Left Arrow"), left_arrow_btn_rect, |
1633 | out_id, in_id, LLStringUtil::null, | 1667 | out_id, in_id, LLStringUtil::null, |
1634 | &LLTabContainer::onPrevBtn, this, LLFontGL::sSansSerif ); | 1668 | &LLTabContainer::onPrevBtn, this, LLFontGL::getFontSansSerif() ); |
1635 | mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld); | 1669 | mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld); |
1636 | mPrevArrowBtn->setFollowsLeft(); | 1670 | mPrevArrowBtn->setFollowsLeft(); |
1637 | 1671 | ||
@@ -1640,7 +1674,7 @@ void LLTabContainer::initButtons() | |||
1640 | mJumpNextArrowBtn = new LLButton(std::string("Jump Right Arrow"), jump_right_arrow_btn_rect, | 1674 | mJumpNextArrowBtn = new LLButton(std::string("Jump Right Arrow"), jump_right_arrow_btn_rect, |
1641 | out_id, in_id, LLStringUtil::null, | 1675 | out_id, in_id, LLStringUtil::null, |
1642 | &LLTabContainer::onJumpLastBtn, this, | 1676 | &LLTabContainer::onJumpLastBtn, this, |
1643 | LLFontGL::sSansSerif); | 1677 | LLFontGL::getFontSansSerif()); |
1644 | mJumpNextArrowBtn->setFollowsRight(); | 1678 | mJumpNextArrowBtn->setFollowsRight(); |
1645 | 1679 | ||
1646 | out_id = "UIImgBtnScrollRightOutUUID"; | 1680 | out_id = "UIImgBtnScrollRightOutUUID"; |
@@ -1648,7 +1682,7 @@ void LLTabContainer::initButtons() | |||
1648 | mNextArrowBtn = new LLButton(std::string("Right Arrow"), right_arrow_btn_rect, | 1682 | mNextArrowBtn = new LLButton(std::string("Right Arrow"), right_arrow_btn_rect, |
1649 | out_id, in_id, LLStringUtil::null, | 1683 | out_id, in_id, LLStringUtil::null, |
1650 | &LLTabContainer::onNextBtn, this, | 1684 | &LLTabContainer::onNextBtn, this, |
1651 | LLFontGL::sSansSerif); | 1685 | LLFontGL::getFontSansSerif()); |
1652 | mNextArrowBtn->setFollowsRight(); | 1686 | mNextArrowBtn->setFollowsRight(); |
1653 | 1687 | ||
1654 | if( getTabPosition() == TOP ) | 1688 | if( getTabPosition() == TOP ) |
diff --git a/linden/indra/llui/lltabcontainer.h b/linden/indra/llui/lltabcontainer.h index 96400f0..8117cde 100644 --- a/linden/indra/llui/lltabcontainer.h +++ b/linden/indra/llui/lltabcontainer.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -107,6 +108,7 @@ public: | |||
107 | BOOL selectTabPanel( LLPanel* child ); | 108 | BOOL selectTabPanel( LLPanel* child ); |
108 | BOOL selectTab(S32 which); | 109 | BOOL selectTab(S32 which); |
109 | BOOL selectTabByName(const std::string& title); | 110 | BOOL selectTabByName(const std::string& title); |
111 | BOOL setTab(S32 which); | ||
110 | 112 | ||
111 | BOOL getTabPanelFlashing(LLPanel* child); | 113 | BOOL getTabPanelFlashing(LLPanel* child); |
112 | void setTabPanelFlashing(LLPanel* child, BOOL state); | 114 | void setTabPanelFlashing(LLPanel* child, BOOL state); |
@@ -118,6 +120,7 @@ public: | |||
118 | S32 getTopBorderHeight() const; | 120 | S32 getTopBorderHeight() const; |
119 | 121 | ||
120 | void setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*,bool)); | 122 | void setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*,bool)); |
123 | void setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool)); | ||
121 | void setTabUserData(LLPanel* tab, void* userdata); | 124 | void setTabUserData(LLPanel* tab, void* userdata); |
122 | 125 | ||
123 | void setRightTabBtnOffset( S32 offset ); | 126 | void setRightTabBtnOffset( S32 offset ); |
@@ -147,12 +150,14 @@ private: | |||
147 | struct LLTabTuple | 150 | struct LLTabTuple |
148 | { | 151 | { |
149 | LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, | 152 | LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, |
150 | void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL ) | 153 | void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL, |
154 | void (*pcb)(void*,bool) = NULL) | ||
151 | : | 155 | : |
152 | mTabContainer(c), | 156 | mTabContainer(c), |
153 | mTabPanel(p), | 157 | mTabPanel(p), |
154 | mButton(b), | 158 | mButton(b), |
155 | mOnChangeCallback( cb ), | 159 | mOnChangeCallback( cb ), |
160 | mPrecommitChangeCallback( pcb ), | ||
156 | mUserData( userdata ), | 161 | mUserData( userdata ), |
157 | mOldState(FALSE), | 162 | mOldState(FALSE), |
158 | mPlaceholderText(placeholder), | 163 | mPlaceholderText(placeholder), |
@@ -163,6 +168,9 @@ private: | |||
163 | LLPanel* mTabPanel; | 168 | LLPanel* mTabPanel; |
164 | LLButton* mButton; | 169 | LLButton* mButton; |
165 | void (*mOnChangeCallback)(void*, bool); | 170 | void (*mOnChangeCallback)(void*, bool); |
171 | void (*mPrecommitChangeCallback)(void*,bool); // Precommit callback gets called before tab is changed and | ||
172 | // can prevent it from being changed. onChangeCallback is called | ||
173 | // immediately after tab is actually changed - Nyx | ||
166 | void* mUserData; | 174 | void* mUserData; |
167 | BOOL mOldState; | 175 | BOOL mOldState; |
168 | LLTextBox* mPlaceholderText; | 176 | LLTextBox* mPlaceholderText; |
@@ -199,6 +207,7 @@ private: | |||
199 | tuple_list_t mTabList; | 207 | tuple_list_t mTabList; |
200 | 208 | ||
201 | S32 mCurrentTabIdx; | 209 | S32 mCurrentTabIdx; |
210 | S32 mNextTabIdx; | ||
202 | BOOL mTabsHidden; | 211 | BOOL mTabsHidden; |
203 | 212 | ||
204 | BOOL mScrolled; | 213 | BOOL mScrolled; |
diff --git a/linden/indra/llui/lltabcontainervertical.cpp b/linden/indra/llui/lltabcontainervertical.cpp index fa24ed1..a729c95 100644 --- a/linden/indra/llui/lltabcontainervertical.cpp +++ b/linden/indra/llui/lltabcontainervertical.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lltabcontainervertical.h b/linden/indra/llui/lltabcontainervertical.h index d01d20a..ce42367 100644 --- a/linden/indra/llui/lltabcontainervertical.h +++ b/linden/indra/llui/lltabcontainervertical.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lltextbox.cpp b/linden/indra/llui/lltextbox.cpp index f43b7d2..89893bc 100644 --- a/linden/indra/llui/lltextbox.cpp +++ b/linden/indra/llui/lltextbox.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -33,32 +34,16 @@ | |||
33 | #include "lltextbox.h" | 34 | #include "lltextbox.h" |
34 | #include "lluictrlfactory.h" | 35 | #include "lluictrlfactory.h" |
35 | #include "llfocusmgr.h" | 36 | #include "llfocusmgr.h" |
37 | #include "llwindow.h" | ||
36 | 38 | ||
37 | static LLRegisterWidget<LLTextBox> r("text"); | 39 | static LLRegisterWidget<LLTextBox> r("text"); |
38 | 40 | ||
39 | LLTextBox::LLTextBox(const std::string& name, const LLRect& rect, const std::string& text, | 41 | LLTextBox::LLTextBox(const std::string& name, const LLRect& rect, const std::string& text, |
40 | const LLFontGL* font, BOOL mouse_opaque) | 42 | const LLFontGL* font, BOOL mouse_opaque) |
41 | : LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ), | 43 | : LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ), |
42 | mFontGL(font ? font : LLFontGL::sSansSerifSmall), | 44 | mFontGL(font ? font : LLFontGL::getFontSansSerifSmall()) |
43 | mTextColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ), | ||
44 | mDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ), | ||
45 | mBackgroundColor( LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" ) ), | ||
46 | mBorderColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ), | ||
47 | mHoverColor( LLUI::sColorsGroup->getColor( "LabelSelectedColor" ) ), | ||
48 | mHoverActive( FALSE ), | ||
49 | mHasHover( FALSE ), | ||
50 | mBackgroundVisible( FALSE ), | ||
51 | mBorderVisible( FALSE ), | ||
52 | mFontStyle(LLFontGL::DROP_SHADOW_SOFT), | ||
53 | mBorderDropShadowVisible( FALSE ), | ||
54 | mUseEllipses( FALSE ), | ||
55 | mHPad(0), | ||
56 | mVPad(0), | ||
57 | mHAlign( LLFontGL::LEFT ), | ||
58 | mVAlign( LLFontGL::TOP ), | ||
59 | mClickedCallback(NULL), | ||
60 | mCallbackUserData(NULL) | ||
61 | { | 45 | { |
46 | initDefaults(); | ||
62 | setText( text ); | 47 | setText( text ); |
63 | setTabStop(FALSE); | 48 | setTabStop(FALSE); |
64 | } | 49 | } |
@@ -66,26 +51,9 @@ LLTextBox::LLTextBox(const std::string& name, const LLRect& rect, const std::str | |||
66 | LLTextBox::LLTextBox(const std::string& name, const std::string& text, F32 max_width, | 51 | LLTextBox::LLTextBox(const std::string& name, const std::string& text, F32 max_width, |
67 | const LLFontGL* font, BOOL mouse_opaque) : | 52 | const LLFontGL* font, BOOL mouse_opaque) : |
68 | LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), | 53 | LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), |
69 | mFontGL(font ? font : LLFontGL::sSansSerifSmall), | 54 | mFontGL(font ? font : LLFontGL::getFontSansSerifSmall()) |
70 | mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")), | ||
71 | mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")), | ||
72 | mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")), | ||
73 | mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")), | ||
74 | mHoverColor( LLUI::sColorsGroup->getColor( "LabelSelectedColor" ) ), | ||
75 | mHoverActive( FALSE ), | ||
76 | mHasHover( FALSE ), | ||
77 | mBackgroundVisible(FALSE), | ||
78 | mBorderVisible(FALSE), | ||
79 | mFontStyle(LLFontGL::DROP_SHADOW_SOFT), | ||
80 | mBorderDropShadowVisible(FALSE), | ||
81 | mUseEllipses( FALSE ), | ||
82 | mHPad(0), | ||
83 | mVPad(0), | ||
84 | mHAlign(LLFontGL::LEFT), | ||
85 | mVAlign( LLFontGL::TOP ), | ||
86 | mClickedCallback(NULL), | ||
87 | mCallbackUserData(NULL) | ||
88 | { | 55 | { |
56 | initDefaults(); | ||
89 | setWrappedText(text, max_width); | 57 | setWrappedText(text, max_width); |
90 | reshapeToFitText(); | 58 | reshapeToFitText(); |
91 | setTabStop(FALSE); | 59 | setTabStop(FALSE); |
@@ -93,47 +61,34 @@ LLTextBox::LLTextBox(const std::string& name, const std::string& text, F32 max_w | |||
93 | 61 | ||
94 | LLTextBox::LLTextBox(const std::string& name_and_label, const LLRect& rect) : | 62 | LLTextBox::LLTextBox(const std::string& name_and_label, const LLRect& rect) : |
95 | LLUICtrl(name_and_label, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), | 63 | LLUICtrl(name_and_label, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), |
96 | mFontGL(LLFontGL::sSansSerifSmall), | 64 | mFontGL(LLFontGL::getFontSansSerifSmall()) |
97 | mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")), | ||
98 | mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")), | ||
99 | mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")), | ||
100 | mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")), | ||
101 | mBackgroundVisible(FALSE), | ||
102 | mBorderVisible(FALSE), | ||
103 | mFontStyle(LLFontGL::DROP_SHADOW_SOFT), | ||
104 | mBorderDropShadowVisible(FALSE), | ||
105 | mHPad(0), | ||
106 | mVPad(0), | ||
107 | mHAlign(LLFontGL::LEFT), | ||
108 | mVAlign( LLFontGL::TOP ), | ||
109 | mClickedCallback(NULL), | ||
110 | mCallbackUserData(NULL) | ||
111 | { | 65 | { |
66 | initDefaults(); | ||
112 | setText( name_and_label ); | 67 | setText( name_and_label ); |
113 | setTabStop(FALSE); | 68 | setTabStop(FALSE); |
114 | } | 69 | } |
115 | 70 | ||
116 | LLTextBox::LLTextBox(const std::string& name_and_label) : | 71 | void LLTextBox::initDefaults() |
117 | LLUICtrl(name_and_label, LLRect(0, 0, 1, 1), TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), | ||
118 | mFontGL(LLFontGL::sSansSerifSmall), | ||
119 | mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")), | ||
120 | mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")), | ||
121 | mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")), | ||
122 | mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")), | ||
123 | mBackgroundVisible(FALSE), | ||
124 | mBorderVisible(FALSE), | ||
125 | mFontStyle(LLFontGL::DROP_SHADOW_SOFT), | ||
126 | mBorderDropShadowVisible(FALSE), | ||
127 | mHPad(0), | ||
128 | mVPad(0), | ||
129 | mHAlign(LLFontGL::LEFT), | ||
130 | mVAlign( LLFontGL::TOP ), | ||
131 | mClickedCallback(NULL), | ||
132 | mCallbackUserData(NULL) | ||
133 | { | 72 | { |
134 | setWrappedText(name_and_label); | 73 | mTextColor = LLUI::sColorsGroup->getColor("LabelTextColor"); |
135 | reshapeToFitText(); | 74 | mDisabledColor = LLUI::sColorsGroup->getColor("LabelDisabledColor"); |
136 | setTabStop(FALSE); | 75 | mBackgroundColor = LLUI::sColorsGroup->getColor("DefaultBackgroundColor"); |
76 | mBorderColor = LLUI::sColorsGroup->getColor("DefaultHighlightLight"); | ||
77 | mHoverColor = LLUI::sColorsGroup->getColor( "LabelSelectedColor" ); | ||
78 | mHoverActive = FALSE; | ||
79 | mHasHover = FALSE; | ||
80 | mBackgroundVisible = FALSE; | ||
81 | mBorderVisible = FALSE; | ||
82 | mFontStyle = LLFontGL::DROP_SHADOW_SOFT; | ||
83 | mBorderDropShadowVisible = FALSE; | ||
84 | mUseEllipses = FALSE; | ||
85 | mLineSpacing = 0; | ||
86 | mHPad = 0; | ||
87 | mVPad = 0; | ||
88 | mHAlign = LLFontGL::LEFT; | ||
89 | mVAlign = LLFontGL::TOP; | ||
90 | mClickedCallback = NULL; | ||
91 | mCallbackUserData = NULL; | ||
137 | } | 92 | } |
138 | 93 | ||
139 | BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask) | 94 | BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask) |
@@ -193,12 +148,14 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask) | |||
193 | 148 | ||
194 | BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask) | 149 | BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask) |
195 | { | 150 | { |
151 | BOOL handled = LLView::handleHover(x,y,mask); | ||
196 | if(mHoverActive) | 152 | if(mHoverActive) |
197 | { | 153 | { |
198 | mHasHover = TRUE; // This should be set every frame during a hover. | 154 | mHasHover = TRUE; // This should be set every frame during a hover. |
199 | return TRUE; | 155 | getWindow()->setCursor(UI_CURSOR_ARROW); |
200 | } | 156 | } |
201 | return LLView::handleHover(x,y,mask); | 157 | |
158 | return (handled || mHasHover); | ||
202 | } | 159 | } |
203 | 160 | ||
204 | void LLTextBox::setText(const LLStringExplicit& text) | 161 | void LLTextBox::setText(const LLStringExplicit& text) |
@@ -412,7 +369,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color ) | |||
412 | mFontStyle, | 369 | mFontStyle, |
413 | line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses ); | 370 | line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses ); |
414 | cur_pos += line_length + 1; | 371 | cur_pos += line_length + 1; |
415 | y -= llfloor(mFontGL->getLineHeight()); | 372 | y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing; |
416 | } | 373 | } |
417 | } | 374 | } |
418 | } | 375 | } |
@@ -469,6 +426,8 @@ LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f | |||
469 | 426 | ||
470 | text_box->initFromXML(node, parent); | 427 | text_box->initFromXML(node, parent); |
471 | 428 | ||
429 | node->getAttributeS32("line_spacing", text_box->mLineSpacing); | ||
430 | |||
472 | std::string font_style; | 431 | std::string font_style; |
473 | if (node->getAttributeString("font-style", font_style)) | 432 | if (node->getAttributeString("font-style", font_style)) |
474 | { | 433 | { |
diff --git a/linden/indra/llui/lltextbox.h b/linden/indra/llui/lltextbox.h index 83e4a9b..07a6aa3 100644 --- a/linden/indra/llui/lltextbox.h +++ b/linden/indra/llui/lltextbox.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -54,7 +55,10 @@ public: | |||
54 | 55 | ||
55 | // "Simple" constructors for text boxes that have the same name and label *TO BE DEPRECATED* | 56 | // "Simple" constructors for text boxes that have the same name and label *TO BE DEPRECATED* |
56 | LLTextBox(const std::string& name_and_label, const LLRect& rect); | 57 | LLTextBox(const std::string& name_and_label, const LLRect& rect); |
57 | LLTextBox(const std::string& name_and_label); | 58 | |
59 | // Consolidate common member initialization | ||
60 | // 20+ initializers times 3+ constructors is unmaintainable. | ||
61 | void initDefaults(); | ||
58 | 62 | ||
59 | virtual ~LLTextBox() {} | 63 | virtual ~LLTextBox() {} |
60 | 64 | ||
@@ -88,8 +92,7 @@ public: | |||
88 | void setVPad(S32 pixels) { mVPad = pixels; } | 92 | void setVPad(S32 pixels) { mVPad = pixels; } |
89 | void setRightAlign() { mHAlign = LLFontGL::RIGHT; } | 93 | void setRightAlign() { mHAlign = LLFontGL::RIGHT; } |
90 | void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } | 94 | void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } |
91 | void setClickedCallback( void (*cb)(void *data) ){ mClickedCallback = cb; } // mouse down and up within button | 95 | void setClickedCallback( void (*cb)(void *data), void* data = NULL ){ mClickedCallback = cb; mCallbackUserData = data; } // mouse down and up within button |
92 | void setCallbackUserData( void* data ) { mCallbackUserData = data; } | ||
93 | 96 | ||
94 | const LLFontGL* getFont() const { return mFontGL; } | 97 | const LLFontGL* getFont() const { return mFontGL; } |
95 | 98 | ||
@@ -124,6 +127,8 @@ private: | |||
124 | BOOL mBorderDropShadowVisible; | 127 | BOOL mBorderDropShadowVisible; |
125 | BOOL mUseEllipses; | 128 | BOOL mUseEllipses; |
126 | 129 | ||
130 | S32 mLineSpacing; | ||
131 | |||
127 | S32 mHPad; | 132 | S32 mHPad; |
128 | S32 mVPad; | 133 | S32 mVPad; |
129 | LLFontGL::HAlign mHAlign; | 134 | LLFontGL::HAlign mHAlign; |
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp index 62064d9..7928887 100644 --- a/linden/indra/llui/lltexteditor.cpp +++ b/linden/indra/llui/lltexteditor.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -56,6 +57,7 @@ | |||
56 | #include "llcontrol.h" | 57 | #include "llcontrol.h" |
57 | #include "llimagegl.h" | 58 | #include "llimagegl.h" |
58 | #include "llwindow.h" | 59 | #include "llwindow.h" |
60 | #include "lltextparser.h" | ||
59 | #include <queue> | 61 | #include <queue> |
60 | 62 | ||
61 | // | 63 | // |
@@ -299,7 +301,7 @@ LLTextEditor::LLTextEditor( | |||
299 | } | 301 | } |
300 | else | 302 | else |
301 | { | 303 | { |
302 | mGLFont = LLFontGL::sSansSerif; | 304 | mGLFont = LLFontGL::getFontSansSerif(); |
303 | } | 305 | } |
304 | 306 | ||
305 | updateTextRect(); | 307 | updateTextRect(); |
@@ -382,7 +384,7 @@ void LLTextEditor::updateLineStartList(S32 startpos) | |||
382 | { | 384 | { |
383 | updateSegments(); | 385 | updateSegments(); |
384 | 386 | ||
385 | bindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) ); | 387 | bindEmbeddedChars(mGLFont); |
386 | 388 | ||
387 | S32 seg_num = mSegments.size(); | 389 | S32 seg_num = mSegments.size(); |
388 | S32 seg_idx = 0; | 390 | S32 seg_idx = 0; |
@@ -460,7 +462,7 @@ void LLTextEditor::updateLineStartList(S32 startpos) | |||
460 | } | 462 | } |
461 | } | 463 | } |
462 | 464 | ||
463 | unbindEmbeddedChars(const_cast<LLFontGL*>(mGLFont)); | 465 | unbindEmbeddedChars(mGLFont); |
464 | 466 | ||
465 | mScrollbar->setDocSize( getLineCount() ); | 467 | mScrollbar->setDocSize( getLineCount() ); |
466 | 468 | ||
@@ -851,13 +853,13 @@ S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL rou | |||
851 | if (mAllowEmbeddedItems) | 853 | if (mAllowEmbeddedItems) |
852 | { | 854 | { |
853 | // Figure out which character we're nearest to. | 855 | // Figure out which character we're nearest to. |
854 | bindEmbeddedChars(const_cast<LLFontGL*>(mGLFont)); | 856 | bindEmbeddedChars(mGLFont); |
855 | pos = mGLFont->charFromPixelOffset(mWText.c_str(), line_start, | 857 | pos = mGLFont->charFromPixelOffset(mWText.c_str(), line_start, |
856 | (F32)(local_x - mTextRect.mLeft), | 858 | (F32)(local_x - mTextRect.mLeft), |
857 | (F32)(mTextRect.getWidth()), | 859 | (F32)(mTextRect.getWidth()), |
858 | line_len, | 860 | line_len, |
859 | round, TRUE); | 861 | round, TRUE); |
860 | unbindEmbeddedChars(const_cast<LLFontGL*>(mGLFont)); | 862 | unbindEmbeddedChars(mGLFont); |
861 | } | 863 | } |
862 | else | 864 | else |
863 | { | 865 | { |
@@ -1009,7 +1011,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) | |||
1009 | } | 1011 | } |
1010 | else | 1012 | else |
1011 | { | 1013 | { |
1012 | while( right < getLength() && (text[right] != '\n') ) | 1014 | while( (text[right] != '\n') && (right <= getLength() ) ) |
1013 | { | 1015 | { |
1014 | right++; | 1016 | right++; |
1015 | } | 1017 | } |
@@ -1321,6 +1323,8 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask) | |||
1321 | 1323 | ||
1322 | setCursorAtLocalPos( x, y, TRUE ); | 1324 | setCursorAtLocalPos( x, y, TRUE ); |
1323 | endSelection(); | 1325 | endSelection(); |
1326 | |||
1327 | updateScrollFromCursor(); | ||
1324 | } | 1328 | } |
1325 | 1329 | ||
1326 | if( !hasSelection() ) | 1330 | if( !hasSelection() ) |
@@ -2928,7 +2932,7 @@ void LLTextEditor::drawText() | |||
2928 | // draw the line numbers | 2932 | // draw the line numbers |
2929 | if( mShowLineNumbers && !cur_line_is_continuation) | 2933 | if( mShowLineNumbers && !cur_line_is_continuation) |
2930 | { | 2934 | { |
2931 | const LLFontGL *num_font = LLFontGL::sMonospace; | 2935 | const LLFontGL *num_font = LLFontGL::getFontMonospace(); |
2932 | F32 y_top = text_y + ((F32)llround(num_font->getLineHeight()) / 2); | 2936 | F32 y_top = text_y + ((F32)llround(num_font->getLineHeight()) / 2); |
2933 | const LLWString ltext = utf8str_to_wstring(llformat("%*d", UI_TEXTEDITOR_LINE_NUMBER_DIGITS, cur_line_num )); | 2937 | const LLWString ltext = utf8str_to_wstring(llformat("%*d", UI_TEXTEDITOR_LINE_NUMBER_DIGITS, cur_line_num )); |
2934 | BOOL is_cur_line = getCurrentLine() == cur_line_num; | 2938 | BOOL is_cur_line = getCurrentLine() == cur_line_num; |
@@ -3113,7 +3117,7 @@ void LLTextEditor::draw() | |||
3113 | { | 3117 | { |
3114 | LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0)); | 3118 | LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0)); |
3115 | 3119 | ||
3116 | bindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) ); | 3120 | bindEmbeddedChars(mGLFont); |
3117 | 3121 | ||
3118 | drawBackground(); | 3122 | drawBackground(); |
3119 | drawSelectionBackground(); | 3123 | drawSelectionBackground(); |
@@ -3121,7 +3125,7 @@ void LLTextEditor::draw() | |||
3121 | drawText(); | 3125 | drawText(); |
3122 | drawCursor(); | 3126 | drawCursor(); |
3123 | 3127 | ||
3124 | unbindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) ); | 3128 | unbindEmbeddedChars(mGLFont); |
3125 | 3129 | ||
3126 | //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret | 3130 | //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret |
3127 | // when in readonly mode | 3131 | // when in readonly mode |
@@ -3242,7 +3246,7 @@ void LLTextEditor::changePage( S32 delta ) | |||
3242 | 3246 | ||
3243 | void LLTextEditor::changeLine( S32 delta ) | 3247 | void LLTextEditor::changeLine( S32 delta ) |
3244 | { | 3248 | { |
3245 | bindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) ); | 3249 | bindEmbeddedChars(mGLFont); |
3246 | 3250 | ||
3247 | S32 line, offset; | 3251 | S32 line, offset; |
3248 | getLineAndOffset( mCursorPos, &line, &offset ); | 3252 | getLineAndOffset( mCursorPos, &line, &offset ); |
@@ -3269,7 +3273,7 @@ void LLTextEditor::changeLine( S32 delta ) | |||
3269 | } | 3273 | } |
3270 | else | 3274 | else |
3271 | { | 3275 | { |
3272 | unbindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) ); | 3276 | unbindEmbeddedChars(mGLFont); |
3273 | return; | 3277 | return; |
3274 | } | 3278 | } |
3275 | 3279 | ||
@@ -3294,7 +3298,7 @@ void LLTextEditor::changeLine( S32 delta ) | |||
3294 | 3298 | ||
3295 | // put desired position into remember-buffer after setCursorPos() | 3299 | // put desired position into remember-buffer after setCursorPos() |
3296 | mDesiredXPixel = desired_x_pixel; | 3300 | mDesiredXPixel = desired_x_pixel; |
3297 | unbindEmbeddedChars( const_cast<LLFontGL*>(mGLFont) ); | 3301 | unbindEmbeddedChars(mGLFont); |
3298 | } | 3302 | } |
3299 | 3303 | ||
3300 | BOOL LLTextEditor::isScrolledToTop() | 3304 | BOOL LLTextEditor::isScrolledToTop() |
@@ -3384,7 +3388,9 @@ void LLTextEditor::endOfLine() | |||
3384 | 3388 | ||
3385 | void LLTextEditor::endOfDoc() | 3389 | void LLTextEditor::endOfDoc() |
3386 | { | 3390 | { |
3387 | mScrollbar->setDocPos( mScrollbar->getDocPosMax() ); | 3391 | mScrollbar->setDocPos(mScrollbar->getDocPosMax()); |
3392 | mScrolledToBottom = true; | ||
3393 | |||
3388 | S32 len = getLength(); | 3394 | S32 len = getLength(); |
3389 | if( len ) | 3395 | if( len ) |
3390 | { | 3396 | { |
@@ -3514,18 +3520,26 @@ void LLTextEditor::appendColoredText(const std::string &new_text, | |||
3514 | const LLColor4 &color, | 3520 | const LLColor4 &color, |
3515 | const std::string& font_name) | 3521 | const std::string& font_name) |
3516 | { | 3522 | { |
3523 | LLColor4 lcolor=color; | ||
3524 | if (mParseHighlights) | ||
3525 | { | ||
3526 | LLTextParser* highlight = LLTextParser::getInstance(); | ||
3527 | highlight->parseFullLineHighlights(new_text, &lcolor); | ||
3528 | } | ||
3529 | |||
3517 | LLStyleSP style(new LLStyle); | 3530 | LLStyleSP style(new LLStyle); |
3518 | style->setVisible(true); | 3531 | style->setVisible(true); |
3519 | style->setColor(color); | 3532 | style->setColor(lcolor); |
3520 | style->setFontName(font_name); | 3533 | style->setFontName(font_name); |
3521 | appendStyledText(new_text, allow_undo, prepend_newline, &style); | 3534 | appendStyledText(new_text, allow_undo, prepend_newline, style); |
3522 | } | 3535 | } |
3523 | 3536 | ||
3524 | void LLTextEditor::appendStyledText(const std::string &new_text, | 3537 | void LLTextEditor::appendStyledText(const std::string &new_text, |
3525 | bool allow_undo, | 3538 | bool allow_undo, |
3526 | bool prepend_newline, | 3539 | bool prepend_newline, |
3527 | const LLStyleSP *stylep) | 3540 | LLStyleSP stylep) |
3528 | { | 3541 | { |
3542 | S32 part = (S32)LLTextParser::WHOLE; | ||
3529 | if(mParseHTML) | 3543 | if(mParseHTML) |
3530 | { | 3544 | { |
3531 | 3545 | ||
@@ -3538,34 +3552,80 @@ void LLTextEditor::appendStyledText(const std::string &new_text, | |||
3538 | html->setColor(mLinkColor); | 3552 | html->setColor(mLinkColor); |
3539 | if (stylep) | 3553 | if (stylep) |
3540 | { | 3554 | { |
3541 | html->setFontName((*stylep)->getFontString()); | 3555 | html->setFontName(stylep->getFontString()); |
3542 | } | 3556 | } |
3543 | html->mUnderline = TRUE; | 3557 | html->mUnderline = TRUE; |
3544 | 3558 | ||
3545 | if (start > 0) appendText(text.substr(0,start),allow_undo, prepend_newline, stylep); | 3559 | if (start > 0) |
3560 | { | ||
3561 | if (part == (S32)LLTextParser::WHOLE || | ||
3562 | part == (S32)LLTextParser::START) | ||
3563 | { | ||
3564 | part = (S32)LLTextParser::START; | ||
3565 | } | ||
3566 | else | ||
3567 | { | ||
3568 | part = (S32)LLTextParser::MIDDLE; | ||
3569 | } | ||
3570 | std::string subtext=text.substr(0,start); | ||
3571 | appendHighlightedText(subtext,allow_undo, prepend_newline, part, stylep); | ||
3572 | } | ||
3573 | |||
3546 | html->setLinkHREF(text.substr(start,end-start)); | 3574 | html->setLinkHREF(text.substr(start,end-start)); |
3547 | appendText(text.substr(start, end-start),allow_undo, prepend_newline, &html); | 3575 | appendText(text.substr(start, end-start),allow_undo, prepend_newline, html); |
3548 | if (end < (S32)text.length()) | 3576 | if (end < (S32)text.length()) |
3549 | { | 3577 | { |
3550 | text = text.substr(end,text.length() - end); | 3578 | text = text.substr(end,text.length() - end); |
3551 | end=0; | 3579 | end=0; |
3580 | part=(S32)LLTextParser::END; | ||
3552 | } | 3581 | } |
3553 | else | 3582 | else |
3554 | { | 3583 | { |
3555 | break; | 3584 | break; |
3556 | } | 3585 | } |
3557 | } | 3586 | } |
3558 | if (end < (S32)text.length()) appendText(text,allow_undo, prepend_newline, stylep); | 3587 | if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END; |
3588 | if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, stylep); | ||
3559 | } | 3589 | } |
3560 | else | 3590 | else |
3561 | { | 3591 | { |
3562 | appendText(new_text, allow_undo, prepend_newline, stylep); | 3592 | appendHighlightedText(new_text, allow_undo, prepend_newline, part, stylep); |
3563 | } | 3593 | } |
3564 | } | 3594 | } |
3565 | 3595 | ||
3596 | void LLTextEditor::appendHighlightedText(const std::string &new_text, | ||
3597 | bool allow_undo, | ||
3598 | bool prepend_newline, | ||
3599 | S32 highlight_part, | ||
3600 | LLStyleSP stylep) | ||
3601 | { | ||
3602 | if (mParseHighlights) | ||
3603 | { | ||
3604 | LLTextParser* highlight = LLTextParser::getInstance(); | ||
3605 | |||
3606 | if (highlight && stylep) | ||
3607 | { | ||
3608 | LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), highlight_part); | ||
3609 | bool lprepend=prepend_newline; | ||
3610 | for (S32 i=0;i<pieces.size();i++) | ||
3611 | { | ||
3612 | LLSD color_llsd = pieces[i]["color"]; | ||
3613 | LLColor4 lcolor; | ||
3614 | lcolor.setValue(color_llsd); | ||
3615 | LLStyleSP lstylep(new LLStyle(*stylep)); | ||
3616 | lstylep->setColor(lcolor); | ||
3617 | if (i != 0 && (pieces.size() > 1) ) lprepend=FALSE; | ||
3618 | appendText((std::string)pieces[i]["text"], allow_undo, lprepend, lstylep); | ||
3619 | } | ||
3620 | return; | ||
3621 | } | ||
3622 | } | ||
3623 | appendText(new_text, allow_undo, prepend_newline, stylep); | ||
3624 | } | ||
3625 | |||
3566 | // Appends new text to end of document | 3626 | // Appends new text to end of document |
3567 | void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, | 3627 | void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, |
3568 | const LLStyleSP *stylep) | 3628 | const LLStyleSP stylep) |
3569 | { | 3629 | { |
3570 | // Save old state | 3630 | // Save old state |
3571 | BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); | 3631 | BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); |
@@ -3597,7 +3657,7 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool | |||
3597 | { | 3657 | { |
3598 | S32 segment_start = old_length; | 3658 | S32 segment_start = old_length; |
3599 | S32 segment_end = getLength(); | 3659 | S32 segment_end = getLength(); |
3600 | LLTextSegment* segment = new LLTextSegment(*stylep, segment_start, segment_end ); | 3660 | LLTextSegment* segment = new LLTextSegment(stylep, segment_start, segment_end ); |
3601 | mSegments.push_back(segment); | 3661 | mSegments.push_back(segment); |
3602 | } | 3662 | } |
3603 | 3663 | ||
@@ -4270,7 +4330,6 @@ S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse) | |||
4270 | } | 4330 | } |
4271 | else | 4331 | else |
4272 | { | 4332 | { |
4273 | |||
4274 | for (int index=pos; index<(S32)line.length(); index++) | 4333 | for (int index=pos; index<(S32)line.length(); index++) |
4275 | { | 4334 | { |
4276 | char c = line[index]; | 4335 | char c = line[index]; |
diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h index 61341e2..56825e7 100644 --- a/linden/indra/llui/lltexteditor.h +++ b/linden/indra/llui/lltexteditor.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -75,6 +76,7 @@ public: | |||
75 | static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory); | 76 | static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory); |
76 | void setTextEditorParameters(LLXMLNodePtr node); | 77 | void setTextEditorParameters(LLXMLNodePtr node); |
77 | void setParseHTML(BOOL parsing) {mParseHTML=parsing;} | 78 | void setParseHTML(BOOL parsing) {mParseHTML=parsing;} |
79 | void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;} | ||
78 | 80 | ||
79 | // mousehandler overrides | 81 | // mousehandler overrides |
80 | virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); | 82 | virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); |
@@ -139,7 +141,7 @@ public: | |||
139 | void insertText(const std::string &text); | 141 | void insertText(const std::string &text); |
140 | // appends text at end | 142 | // appends text at end |
141 | void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline, | 143 | void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline, |
142 | const LLStyleSP *stylep = NULL); | 144 | const LLStyleSP stylep = NULL); |
143 | 145 | ||
144 | void appendColoredText(const std::string &wtext, bool allow_undo, | 146 | void appendColoredText(const std::string &wtext, bool allow_undo, |
145 | bool prepend_newline, | 147 | bool prepend_newline, |
@@ -148,8 +150,11 @@ public: | |||
148 | // if styled text starts a line, you need to prepend a newline. | 150 | // if styled text starts a line, you need to prepend a newline. |
149 | void appendStyledText(const std::string &new_text, bool allow_undo, | 151 | void appendStyledText(const std::string &new_text, bool allow_undo, |
150 | bool prepend_newline, | 152 | bool prepend_newline, |
151 | const LLStyleSP *stylep = NULL); | 153 | LLStyleSP stylep = NULL); |
152 | 154 | void appendHighlightedText(const std::string &new_text, bool allow_undo, | |
155 | bool prepend_newline, S32 highlight_part, | ||
156 | LLStyleSP stylep); | ||
157 | |||
153 | // Removes text from the end of document | 158 | // Removes text from the end of document |
154 | // Does not change highlight or cursor position. | 159 | // Does not change highlight or cursor position. |
155 | void removeTextFromEnd(S32 num_chars); | 160 | void removeTextFromEnd(S32 num_chars); |
@@ -312,8 +317,8 @@ protected: | |||
312 | virtual BOOL handleMouseUpOverSegment(S32 x, S32 y, MASK mask); | 317 | virtual BOOL handleMouseUpOverSegment(S32 x, S32 y, MASK mask); |
313 | 318 | ||
314 | virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } | 319 | virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } |
315 | virtual void bindEmbeddedChars(LLFontGL* font) const {} | 320 | virtual void bindEmbeddedChars(const LLFontGL* font) const {} |
316 | virtual void unbindEmbeddedChars(LLFontGL* font) const {} | 321 | virtual void unbindEmbeddedChars(const LLFontGL* font) const {} |
317 | 322 | ||
318 | S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const; | 323 | S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const; |
319 | BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const; | 324 | BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const; |
@@ -401,6 +406,7 @@ protected: | |||
401 | S32 mLastSelectionY; | 406 | S32 mLastSelectionY; |
402 | 407 | ||
403 | BOOL mParseHTML; | 408 | BOOL mParseHTML; |
409 | BOOL mParseHighlights; | ||
404 | std::string mHTML; | 410 | std::string mHTML; |
405 | 411 | ||
406 | typedef std::vector<LLTextSegment *> segment_list_t; | 412 | typedef std::vector<LLTextSegment *> segment_list_t; |
diff --git a/linden/indra/llui/lltextparser.cpp b/linden/indra/llui/lltextparser.cpp new file mode 100644 index 0000000..925b118 --- /dev/null +++ b/linden/indra/llui/lltextparser.cpp | |||
@@ -0,0 +1,299 @@ | |||
1 | /** | ||
2 | * @file lltexteditor.cpp | ||
3 | * @brief LLTextEditor base class | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2001&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2001-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "llsd.h" | ||
36 | #include "llsdserialize.h" | ||
37 | #include "llerror.h" | ||
38 | #include "lluuid.h" | ||
39 | #include "llstring.h" | ||
40 | #include "message.h" | ||
41 | #include "llmath.h" | ||
42 | #include "v4color.h" | ||
43 | #include "audioengine.h" | ||
44 | #include "llwindow.h" | ||
45 | #include "lldir.h" | ||
46 | |||
47 | #include "lltextparser.h" | ||
48 | //#include "lltexttospeech.h" | ||
49 | |||
50 | // Routines used for parsing text for TextParsers and html | ||
51 | |||
52 | LLTextParser* LLTextParser::sInstance = NULL; | ||
53 | |||
54 | // | ||
55 | // Constants | ||
56 | // | ||
57 | const F32 SOUND_GAIN = 1.0f; | ||
58 | |||
59 | // | ||
60 | // Member Functions | ||
61 | // | ||
62 | |||
63 | LLTextParser::~LLTextParser() | ||
64 | { | ||
65 | sInstance=NULL; | ||
66 | } | ||
67 | |||
68 | // static | ||
69 | LLTextParser* LLTextParser::getInstance() | ||
70 | { | ||
71 | if (!sInstance) | ||
72 | { | ||
73 | sInstance = new LLTextParser(); | ||
74 | sInstance->loadFromDisk(); | ||
75 | } | ||
76 | return sInstance; | ||
77 | } | ||
78 | |||
79 | void LLTextParser::triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window) | ||
80 | { | ||
81 | // bool spoken=FALSE; | ||
82 | for (S32 i=0;i<mHighlights.size();i++) | ||
83 | { | ||
84 | if (findPattern(text,mHighlights[i]) >= 0 ) | ||
85 | { | ||
86 | if(gAudiop) | ||
87 | { | ||
88 | if ((std::string)mHighlights[i]["sound_lluuid"] != LLUUID::null.asString()) | ||
89 | { | ||
90 | gAudiop->triggerSound(mHighlights[i]["sound_lluuid"].asUUID(), agent_id, SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, position); | ||
91 | } | ||
92 | /* | ||
93 | if (!spoken) | ||
94 | { | ||
95 | LLTextToSpeech* text_to_speech = NULL; | ||
96 | text_to_speech = LLTextToSpeech::getInstance(); | ||
97 | spoken = text_to_speech->speak((LLString)mHighlights[i]["voice"],text); | ||
98 | } | ||
99 | */ | ||
100 | } | ||
101 | if (mHighlights[i]["flash"]) | ||
102 | { | ||
103 | if (viewer_window && viewer_window->getMinimized()) | ||
104 | { | ||
105 | viewer_window->flashIcon(5.f); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | S32 LLTextParser::findPattern(const std::string &text, LLSD highlight) | ||
113 | { | ||
114 | if (!highlight.has("pattern")) return -1; | ||
115 | |||
116 | std::string pattern=std::string(highlight["pattern"]); | ||
117 | std::string ltext=text; | ||
118 | |||
119 | if (!(bool)highlight["case_sensitive"]) | ||
120 | { | ||
121 | ltext = utf8str_tolower(text); | ||
122 | pattern= utf8str_tolower(pattern); | ||
123 | } | ||
124 | |||
125 | size_t found=std::string::npos; | ||
126 | |||
127 | switch ((S32)highlight["condition"]) | ||
128 | { | ||
129 | case CONTAINS: | ||
130 | found = ltext.find(pattern); | ||
131 | break; | ||
132 | case MATCHES: | ||
133 | found = (! ltext.compare(pattern) ? 0 : std::string::npos); | ||
134 | break; | ||
135 | case STARTS_WITH: | ||
136 | found = (! ltext.find(pattern) ? 0 : std::string::npos); | ||
137 | break; | ||
138 | case ENDS_WITH: | ||
139 | S32 pos = ltext.rfind(pattern); | ||
140 | if (pos >= 0 && (ltext.length()-pattern.length()==pos)) found = pos; | ||
141 | break; | ||
142 | } | ||
143 | return found; | ||
144 | } | ||
145 | |||
146 | LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, S32 part, S32 index) | ||
147 | { | ||
148 | //evil recursive string atomizer. | ||
149 | LLSD ret_llsd, start_llsd, middle_llsd, end_llsd; | ||
150 | |||
151 | for (S32 i=index;i<mHighlights.size();i++) | ||
152 | { | ||
153 | S32 condition = mHighlights[i]["condition"]; | ||
154 | if ((S32)mHighlights[i]["highlight"]==PART && condition!=MATCHES) | ||
155 | { | ||
156 | if ( (condition==STARTS_WITH && part==START) || | ||
157 | (condition==ENDS_WITH && part==END) || | ||
158 | condition==CONTAINS || part==WHOLE ) | ||
159 | { | ||
160 | S32 start = findPattern(text,mHighlights[i]); | ||
161 | if (start >= 0 ) | ||
162 | { | ||
163 | S32 end = std::string(mHighlights[i]["pattern"]).length(); | ||
164 | S32 len = text.length(); | ||
165 | S32 newpart; | ||
166 | if (start==0) | ||
167 | { | ||
168 | start_llsd[0]["text"] =text.substr(0,end); | ||
169 | start_llsd[0]["color"]=mHighlights[i]["color"]; | ||
170 | |||
171 | if (end < len) | ||
172 | { | ||
173 | if (part==END || part==WHOLE) newpart=END; else newpart=MIDDLE; | ||
174 | end_llsd=parsePartialLineHighlights(text.substr( end ),color,newpart,i); | ||
175 | } | ||
176 | } | ||
177 | else | ||
178 | { | ||
179 | if (part==START || part==WHOLE) newpart=START; else newpart=MIDDLE; | ||
180 | |||
181 | start_llsd=parsePartialLineHighlights(text.substr(0,start),color,newpart,i+1); | ||
182 | |||
183 | if (end < len) | ||
184 | { | ||
185 | middle_llsd[0]["text"] =text.substr(start,end); | ||
186 | middle_llsd[0]["color"]=mHighlights[i]["color"]; | ||
187 | |||
188 | if (part==END || part==WHOLE) newpart=END; else newpart=MIDDLE; | ||
189 | |||
190 | end_llsd=parsePartialLineHighlights(text.substr( (start+end) ),color,newpart,i); | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | end_llsd[0]["text"] =text.substr(start,end); | ||
195 | end_llsd[0]["color"]=mHighlights[i]["color"]; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | S32 retcount=0; | ||
200 | |||
201 | //FIXME These loops should be wrapped into a subroutine. | ||
202 | for (LLSD::array_iterator iter = start_llsd.beginArray(); | ||
203 | iter != start_llsd.endArray();++iter) | ||
204 | { | ||
205 | LLSD highlight = *iter; | ||
206 | ret_llsd[retcount++]=highlight; | ||
207 | } | ||
208 | |||
209 | for (LLSD::array_iterator iter = middle_llsd.beginArray(); | ||
210 | iter != middle_llsd.endArray();++iter) | ||
211 | { | ||
212 | LLSD highlight = *iter; | ||
213 | ret_llsd[retcount++]=highlight; | ||
214 | } | ||
215 | |||
216 | for (LLSD::array_iterator iter = end_llsd.beginArray(); | ||
217 | iter != end_llsd.endArray();++iter) | ||
218 | { | ||
219 | LLSD highlight = *iter; | ||
220 | ret_llsd[retcount++]=highlight; | ||
221 | } | ||
222 | |||
223 | return ret_llsd; | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
229 | //No patterns found. Just send back what was passed in. | ||
230 | ret_llsd[0]["text"] =text; | ||
231 | LLSD color_sd = color.getValue(); | ||
232 | ret_llsd[0]["color"]=color_sd; | ||
233 | return ret_llsd; | ||
234 | } | ||
235 | |||
236 | bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color) | ||
237 | { | ||
238 | for (S32 i=0;i<mHighlights.size();i++) | ||
239 | { | ||
240 | if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES) | ||
241 | { | ||
242 | if (findPattern(text,mHighlights[i]) >= 0 ) | ||
243 | { | ||
244 | LLSD color_llsd = mHighlights[i]["color"]; | ||
245 | color->setValue(color_llsd); | ||
246 | return TRUE; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | return FALSE; //No matches found. | ||
251 | } | ||
252 | |||
253 | std::string LLTextParser::getFileName() | ||
254 | { | ||
255 | std::string path=gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, ""); | ||
256 | |||
257 | if (!path.empty()) | ||
258 | { | ||
259 | path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "highlights.xml"); | ||
260 | } | ||
261 | return path; | ||
262 | } | ||
263 | |||
264 | LLSD LLTextParser::loadFromDisk() | ||
265 | { | ||
266 | std::string filename=getFileName(); | ||
267 | if (filename.empty()) | ||
268 | { | ||
269 | llwarns << "LLTextParser::loadFromDisk() no valid user directory." << llendl; | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | llifstream file; | ||
274 | file.open(filename.c_str()); | ||
275 | if (file.is_open()) | ||
276 | { | ||
277 | LLSDSerialize::fromXML(mHighlights, file); | ||
278 | } | ||
279 | file.close(); | ||
280 | } | ||
281 | |||
282 | return mHighlights; | ||
283 | } | ||
284 | |||
285 | bool LLTextParser::saveToDisk(LLSD highlights) | ||
286 | { | ||
287 | mHighlights=highlights; | ||
288 | std::string filename=getFileName(); | ||
289 | if (filename.empty()) | ||
290 | { | ||
291 | llwarns << "LLTextParser::saveToDisk() no valid user directory." << llendl; | ||
292 | return FALSE; | ||
293 | } | ||
294 | llofstream file; | ||
295 | file.open(filename.c_str()); | ||
296 | LLSDSerialize::toPrettyXML(mHighlights, file); | ||
297 | file.close(); | ||
298 | return TRUE; | ||
299 | } | ||
diff --git a/linden/indra/llui/lltextparser.h b/linden/indra/llui/lltextparser.h new file mode 100644 index 0000000..d69e3a2 --- /dev/null +++ b/linden/indra/llui/lltextparser.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /** | ||
2 | * @file llTextParser.h | ||
3 | * @brief GUI for user-defined highlights | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LLTEXTPARSER_H | ||
35 | #define LL_LLTEXTPARSER_H | ||
36 | |||
37 | #include <vector> | ||
38 | #include "linden_common.h" | ||
39 | |||
40 | #include "lltextparser.h" | ||
41 | |||
42 | class LLSD; | ||
43 | class LLUUID; | ||
44 | class LLVector3d; | ||
45 | class LLColor4; | ||
46 | |||
47 | class LLTextParser | ||
48 | { | ||
49 | public: | ||
50 | enum ConditionType { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH }; | ||
51 | enum HighlightType { PART, ALL }; | ||
52 | enum HighlightPosition { WHOLE, START, MIDDLE, END }; | ||
53 | enum DialogAction { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE }; | ||
54 | |||
55 | static LLTextParser* getInstance(); | ||
56 | LLTextParser(){}; | ||
57 | ~LLTextParser(); | ||
58 | |||
59 | S32 findPattern(const std::string &text, LLSD highlight); | ||
60 | LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0); | ||
61 | bool parseFullLineHighlights(const std::string &text, LLColor4 *color); | ||
62 | void triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window); | ||
63 | |||
64 | std::string getFileName(); | ||
65 | LLSD loadFromDisk(); | ||
66 | bool saveToDisk(LLSD highlights); | ||
67 | public: | ||
68 | LLSD mHighlights; | ||
69 | private: | ||
70 | static LLTextParser* sInstance; | ||
71 | }; | ||
72 | |||
73 | #endif | ||
diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp index f3e73fd..57ce13c 100644 --- a/linden/indra/llui/llui.cpp +++ b/linden/indra/llui/llui.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -30,6 +31,7 @@ | |||
30 | */ | 31 | */ |
31 | 32 | ||
32 | // Utilities functions the user interface needs | 33 | // Utilities functions the user interface needs |
34 | |||
33 | #include "linden_common.h" | 35 | #include "linden_common.h" |
34 | 36 | ||
35 | #include <string> | 37 | #include <string> |
@@ -65,6 +67,7 @@ std::map<std::string, std::string> gTranslation; | |||
65 | std::list<std::string> gUntranslated; | 67 | std::list<std::string> gUntranslated; |
66 | 68 | ||
67 | LLControlGroup* LLUI::sConfigGroup = NULL; | 69 | LLControlGroup* LLUI::sConfigGroup = NULL; |
70 | LLControlGroup* LLUI::sIgnoresGroup = NULL; | ||
68 | LLControlGroup* LLUI::sColorsGroup = NULL; | 71 | LLControlGroup* LLUI::sColorsGroup = NULL; |
69 | LLImageProviderInterface* LLUI::sImageProvider = NULL; | 72 | LLImageProviderInterface* LLUI::sImageProvider = NULL; |
70 | LLUIAudioCallback LLUI::sAudioCallback = NULL; | 73 | LLUIAudioCallback LLUI::sAudioCallback = NULL; |
@@ -90,7 +93,7 @@ void make_ui_sound(const char* namep) | |||
90 | LLUUID uuid(LLUI::sConfigGroup->getString(name)); | 93 | LLUUID uuid(LLUI::sConfigGroup->getString(name)); |
91 | if (uuid.isNull()) | 94 | if (uuid.isNull()) |
92 | { | 95 | { |
93 | if ("00000000-0000-0000-0000-000000000000" == LLUI::sConfigGroup->getString(name)) | 96 | if (LLUI::sConfigGroup->getString(name) == LLUUID::null.asString()) |
94 | { | 97 | { |
95 | if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle")) | 98 | if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle")) |
96 | { | 99 | { |
@@ -1552,6 +1555,7 @@ bool handleShowXUINamesChanged(const LLSD& newvalue) | |||
1552 | } | 1555 | } |
1553 | 1556 | ||
1554 | void LLUI::initClass(LLControlGroup* config, | 1557 | void LLUI::initClass(LLControlGroup* config, |
1558 | LLControlGroup* ignores, | ||
1555 | LLControlGroup* colors, | 1559 | LLControlGroup* colors, |
1556 | LLImageProviderInterface* image_provider, | 1560 | LLImageProviderInterface* image_provider, |
1557 | LLUIAudioCallback audio_callback, | 1561 | LLUIAudioCallback audio_callback, |
@@ -1559,7 +1563,16 @@ void LLUI::initClass(LLControlGroup* config, | |||
1559 | const std::string& language) | 1563 | const std::string& language) |
1560 | { | 1564 | { |
1561 | sConfigGroup = config; | 1565 | sConfigGroup = config; |
1566 | sIgnoresGroup = ignores; | ||
1562 | sColorsGroup = colors; | 1567 | sColorsGroup = colors; |
1568 | |||
1569 | if (sConfigGroup == NULL | ||
1570 | || sIgnoresGroup == NULL | ||
1571 | || sColorsGroup == NULL) | ||
1572 | { | ||
1573 | llerrs << "Failure to initialize configuration groups" << llendl; | ||
1574 | } | ||
1575 | |||
1563 | sImageProvider = image_provider; | 1576 | sImageProvider = image_provider; |
1564 | sAudioCallback = audio_callback; | 1577 | sAudioCallback = audio_callback; |
1565 | sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; | 1578 | sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; |
@@ -1567,7 +1580,7 @@ void LLUI::initClass(LLControlGroup* config, | |||
1567 | LLFontGL::sShadowColor = colors->getColor("ColorDropShadow"); | 1580 | LLFontGL::sShadowColor = colors->getColor("ColorDropShadow"); |
1568 | 1581 | ||
1569 | LLUI::sShowXUINames = LLUI::sConfigGroup->getBOOL("ShowXUINames"); | 1582 | LLUI::sShowXUINames = LLUI::sConfigGroup->getBOOL("ShowXUINames"); |
1570 | LLUI::sConfigGroup->getControl("ShowXUINames")->getSignal()->connect(boost::bind(&handleShowXUINamesChanged, _1)); | 1583 | LLUI::sConfigGroup->getControl("ShowXUINames")->getSignal()->connect(&handleShowXUINamesChanged); |
1571 | } | 1584 | } |
1572 | 1585 | ||
1573 | void LLUI::cleanupClass() | 1586 | void LLUI::cleanupClass() |
@@ -1645,6 +1658,18 @@ void LLUI::setCursorPositionLocal(const LLView* viewp, S32 x, S32 y) | |||
1645 | setCursorPositionScreen(screen_x, screen_y); | 1658 | setCursorPositionScreen(screen_x, screen_y); |
1646 | } | 1659 | } |
1647 | 1660 | ||
1661 | //static | ||
1662 | void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y) | ||
1663 | { | ||
1664 | LLCoordWindow cursor_pos_window; | ||
1665 | LLView::getWindow()->getCursorPosition(&cursor_pos_window); | ||
1666 | LLCoordGL cursor_pos_gl; | ||
1667 | LLView::getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); | ||
1668 | cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]); | ||
1669 | cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); | ||
1670 | viewp->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, x, y); | ||
1671 | } | ||
1672 | |||
1648 | // On Windows, the user typically sets the language when they install the | 1673 | // On Windows, the user typically sets the language when they install the |
1649 | // app (by running it with a shortcut that sets InstallLanguage). On Mac, | 1674 | // app (by running it with a shortcut that sets InstallLanguage). On Mac, |
1650 | // or on Windows if the SecondLife.exe executable is run directly, the | 1675 | // or on Windows if the SecondLife.exe executable is run directly, the |
diff --git a/linden/indra/llui/llui.h b/linden/indra/llui/llui.h index 1e731f1..ebcc730 100644 --- a/linden/indra/llui/llui.h +++ b/linden/indra/llui/llui.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -42,6 +43,7 @@ | |||
42 | #include "llgl.h" // *TODO: break this dependency | 43 | #include "llgl.h" // *TODO: break this dependency |
43 | #include <stack> | 44 | #include <stack> |
44 | //#include "llimagegl.h" | 45 | //#include "llimagegl.h" |
46 | #include <boost/signal.hpp> | ||
45 | 47 | ||
46 | // LLUIFactory | 48 | // LLUIFactory |
47 | #include "llsd.h" | 49 | #include "llsd.h" |
@@ -150,11 +152,13 @@ typedef void (*LLUIAudioCallback)(const LLUUID& uuid); | |||
150 | 152 | ||
151 | class LLUI | 153 | class LLUI |
152 | { | 154 | { |
155 | LOG_CLASS(LLUI); | ||
153 | public: | 156 | public: |
154 | // | 157 | // |
155 | // Methods | 158 | // Methods |
156 | // | 159 | // |
157 | static void initClass(LLControlGroup* config, | 160 | static void initClass(LLControlGroup* config, |
161 | LLControlGroup* ignores, | ||
158 | LLControlGroup* colors, | 162 | LLControlGroup* colors, |
159 | LLImageProviderInterface* image_provider, | 163 | LLImageProviderInterface* image_provider, |
160 | LLUIAudioCallback audio_callback = NULL, | 164 | LLUIAudioCallback audio_callback = NULL, |
@@ -175,6 +179,7 @@ public: | |||
175 | static std::string locateSkin(const std::string& filename); | 179 | static std::string locateSkin(const std::string& filename); |
176 | static void setCursorPositionScreen(S32 x, S32 y); | 180 | static void setCursorPositionScreen(S32 x, S32 y); |
177 | static void setCursorPositionLocal(const LLView* viewp, S32 x, S32 y); | 181 | static void setCursorPositionLocal(const LLView* viewp, S32 x, S32 y); |
182 | static void getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y); | ||
178 | static void setScaleFactor(const LLVector2& scale_factor); | 183 | static void setScaleFactor(const LLVector2& scale_factor); |
179 | static void setLineWidth(F32 width); | 184 | static void setLineWidth(F32 width); |
180 | static LLUIImage* getUIImage(const std::string& name); | 185 | static LLUIImage* getUIImage(const std::string& name); |
@@ -189,6 +194,7 @@ public: | |||
189 | // Data | 194 | // Data |
190 | // | 195 | // |
191 | static LLControlGroup* sConfigGroup; | 196 | static LLControlGroup* sConfigGroup; |
197 | static LLControlGroup* sIgnoresGroup; | ||
192 | static LLControlGroup* sColorsGroup; | 198 | static LLControlGroup* sColorsGroup; |
193 | static LLImageProviderInterface* sImageProvider; | 199 | static LLImageProviderInterface* sImageProvider; |
194 | static LLUIAudioCallback sAudioCallback; | 200 | static LLUIAudioCallback sAudioCallback; |
@@ -596,4 +602,237 @@ public: | |||
596 | virtual void cleanUp() = 0; | 602 | virtual void cleanUp() = 0; |
597 | }; | 603 | }; |
598 | 604 | ||
605 | // This mix-in class adds support for tracking all instances of the specificed class parameter T | ||
606 | // The (optional) key associates a value of type KEY with a given instance of T, for quick lookup | ||
607 | // If KEY is not provided, then instances are stored in a simple list | ||
608 | template<typename T, typename KEY = T*> | ||
609 | class LLInstanceTracker : boost::noncopyable | ||
610 | { | ||
611 | public: | ||
612 | typedef typename std::map<KEY, T*>::iterator instance_iter; | ||
613 | typedef typename std::map<KEY, T*>::const_iterator instance_const_iter; | ||
614 | |||
615 | static T* getInstance(KEY k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; } | ||
616 | |||
617 | static instance_iter beginInstances() { return sInstances.begin(); } | ||
618 | static instance_iter endInstances() { return sInstances.end(); } | ||
619 | static S32 instanceCount() { return sInstances.size(); } | ||
620 | protected: | ||
621 | LLInstanceTracker(KEY key) { add(key); } | ||
622 | virtual ~LLInstanceTracker() { remove(); } | ||
623 | virtual void setKey(KEY key) { remove(); add(key); } | ||
624 | virtual const KEY& getKey() const { return mKey; } | ||
625 | |||
626 | private: | ||
627 | void add(KEY key) | ||
628 | { | ||
629 | mKey = key; | ||
630 | sInstances[key] = static_cast<T*>(this); | ||
631 | } | ||
632 | void remove() { sInstances.erase(mKey); } | ||
633 | |||
634 | private: | ||
635 | |||
636 | KEY mKey; | ||
637 | static std::map<KEY, T*> sInstances; | ||
638 | }; | ||
639 | |||
640 | template<typename T> | ||
641 | class LLInstanceTracker<T, T*> : boost::noncopyable | ||
642 | { | ||
643 | public: | ||
644 | typedef typename std::set<T*>::iterator instance_iter; | ||
645 | typedef typename std::set<T*>::const_iterator instance_const_iter; | ||
646 | |||
647 | static instance_iter instancesBegin() { return sInstances.begin(); } | ||
648 | static instance_iter instancesEnd() { return sInstances.end(); } | ||
649 | static S32 instanceCount() { return sInstances.size(); } | ||
650 | |||
651 | protected: | ||
652 | LLInstanceTracker() { sInstances.insert(static_cast<T*>(this)); } | ||
653 | virtual ~LLInstanceTracker() { sInstances.erase(static_cast<T*>(this)); } | ||
654 | |||
655 | static std::set<T*> sInstances; | ||
656 | }; | ||
657 | |||
658 | template <typename T, typename KEY> std::map<KEY, T*> LLInstanceTracker<T, KEY>::sInstances; | ||
659 | template <typename T> std::set<T*> LLInstanceTracker<T, T*>::sInstances; | ||
660 | |||
661 | class LLCallbackRegistry | ||
662 | { | ||
663 | public: | ||
664 | typedef boost::signal<void()> callback_signal_t; | ||
665 | |||
666 | void registerCallback(const callback_signal_t::slot_type& slot) | ||
667 | { | ||
668 | mCallbacks.connect(slot); | ||
669 | } | ||
670 | |||
671 | void fireCallbacks() | ||
672 | { | ||
673 | mCallbacks(); | ||
674 | } | ||
675 | |||
676 | private: | ||
677 | callback_signal_t mCallbacks; | ||
678 | }; | ||
679 | |||
680 | class LLInitClassList : | ||
681 | public LLCallbackRegistry, | ||
682 | public LLSingleton<LLInitClassList> | ||
683 | { | ||
684 | friend class LLSingleton<LLInitClassList>; | ||
685 | private: | ||
686 | LLInitClassList() {} | ||
687 | }; | ||
688 | |||
689 | class LLDestroyClassList : | ||
690 | public LLCallbackRegistry, | ||
691 | public LLSingleton<LLDestroyClassList> | ||
692 | { | ||
693 | friend class LLSingleton<LLDestroyClassList>; | ||
694 | private: | ||
695 | LLDestroyClassList() {} | ||
696 | }; | ||
697 | |||
698 | template<typename T> | ||
699 | class LLRegisterWith | ||
700 | { | ||
701 | public: | ||
702 | LLRegisterWith(boost::function<void ()> func) | ||
703 | { | ||
704 | T::instance().registerCallback(func); | ||
705 | } | ||
706 | |||
707 | // this avoids a MSVC bug where non-referenced static members are "optimized" away | ||
708 | // even if their constructors have side effects | ||
709 | void reference() | ||
710 | { | ||
711 | S32 dummy; | ||
712 | dummy = 0; | ||
713 | } | ||
714 | }; | ||
715 | |||
716 | template<typename T> | ||
717 | class LLInitClass | ||
718 | { | ||
719 | public: | ||
720 | LLInitClass() { sRegister.reference(); } | ||
721 | |||
722 | static LLRegisterWith<LLInitClassList> sRegister; | ||
723 | private: | ||
724 | |||
725 | static void initClass() | ||
726 | { | ||
727 | llerrs << "No static initClass() method defined for " << typeid(T).name() << llendl; | ||
728 | } | ||
729 | }; | ||
730 | |||
731 | template<typename T> | ||
732 | class LLDestroyClass | ||
733 | { | ||
734 | public: | ||
735 | LLDestroyClass() { sRegister.reference(); } | ||
736 | |||
737 | static LLRegisterWith<LLDestroyClassList> sRegister; | ||
738 | private: | ||
739 | |||
740 | static void destroyClass() | ||
741 | { | ||
742 | llerrs << "No static destroyClass() method defined for " << typeid(T).name() << llendl; | ||
743 | } | ||
744 | }; | ||
745 | |||
746 | template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass); | ||
747 | template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass); | ||
748 | |||
749 | |||
750 | template <typename DERIVED> | ||
751 | class LLParamBlock | ||
752 | { | ||
753 | protected: | ||
754 | LLParamBlock() { sBlock = (DERIVED*)this; } | ||
755 | |||
756 | typedef typename boost::add_const<DERIVED>::type Tconst; | ||
757 | |||
758 | template <typename T> | ||
759 | class LLMandatoryParam | ||
760 | { | ||
761 | public: | ||
762 | typedef typename boost::add_const<T>::type T_const; | ||
763 | |||
764 | LLMandatoryParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {} | ||
765 | LLMandatoryParam(const LLMandatoryParam<T>& other) : mVal(other.mVal) {} | ||
766 | |||
767 | DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; } | ||
768 | operator T() const { return mVal; } | ||
769 | T operator=(T_const set_value) { mVal = set_value; return mVal; } | ||
770 | |||
771 | private: | ||
772 | T mVal; | ||
773 | DERIVED* mBlock; | ||
774 | }; | ||
775 | |||
776 | template <typename T> | ||
777 | class LLOptionalParam | ||
778 | { | ||
779 | public: | ||
780 | typedef typename boost::add_const<T>::type T_const; | ||
781 | |||
782 | LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {} | ||
783 | LLOptionalParam() : mBlock(sBlock) {} | ||
784 | LLOptionalParam(const LLOptionalParam<T>& other) : mVal(other.mVal) {} | ||
785 | |||
786 | DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; } | ||
787 | operator T() const { return mVal; } | ||
788 | T operator=(T_const set_value) { mVal = set_value; return mVal; } | ||
789 | |||
790 | private: | ||
791 | T mVal; | ||
792 | DERIVED* mBlock; | ||
793 | }; | ||
794 | |||
795 | // specialization that requires initialization for reference types | ||
796 | template <typename T> | ||
797 | class LLOptionalParam <T&> | ||
798 | { | ||
799 | public: | ||
800 | typedef typename boost::add_const<T&>::type T_const; | ||
801 | |||
802 | LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {} | ||
803 | LLOptionalParam(const LLOptionalParam<T&>& other) : mVal(other.mVal) {} | ||
804 | |||
805 | DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; } | ||
806 | operator T&() const { return mVal; } | ||
807 | T& operator=(T_const set_value) { mVal = set_value; return mVal; } | ||
808 | |||
809 | private: | ||
810 | T& mVal; | ||
811 | DERIVED* mBlock; | ||
812 | }; | ||
813 | |||
814 | // specialization that initializes pointer params to NULL | ||
815 | template<typename T> | ||
816 | class LLOptionalParam<T*> | ||
817 | { | ||
818 | public: | ||
819 | typedef typename boost::add_const<T*>::type T_const; | ||
820 | |||
821 | LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {} | ||
822 | LLOptionalParam() : mVal((T*)NULL), mBlock(sBlock) {} | ||
823 | LLOptionalParam(const LLOptionalParam<T*>& other) : mVal(other.mVal) {} | ||
824 | |||
825 | DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; } | ||
826 | operator T*() const { return mVal; } | ||
827 | T* operator=(T_const set_value) { mVal = set_value; return mVal; } | ||
828 | private: | ||
829 | T* mVal; | ||
830 | DERIVED* mBlock; | ||
831 | }; | ||
832 | |||
833 | static DERIVED* sBlock; | ||
834 | }; | ||
835 | |||
836 | template <typename T> T* LLParamBlock<T>::sBlock = NULL; | ||
837 | |||
599 | #endif | 838 | #endif |
diff --git a/linden/indra/llui/lluiconstants.h b/linden/indra/llui/lluiconstants.h index 14e7a81..f04062a 100644 --- a/linden/indra/llui/lluiconstants.h +++ b/linden/indra/llui/lluiconstants.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp index b2c14df..9d97312 100644 --- a/linden/indra/llui/lluictrl.cpp +++ b/linden/indra/llui/lluictrl.cpp | |||
@@ -18,7 +18,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 21 | * online at |
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
@@ -475,10 +476,10 @@ BOOL LLUICtrl::focusPrevItem(BOOL text_fields_only) | |||
475 | return focusPrev(result); | 476 | return focusPrev(result); |
476 | } | 477 | } |
477 | 478 | ||
478 | LLUICtrl* LLUICtrl::findRootMostFocusRoot() const | 479 | LLUICtrl* LLUICtrl::findRootMostFocusRoot() |
479 | { | 480 | { |
480 | const LLUICtrl* focus_root = NULL; | 481 | LLUICtrl* focus_root = NULL; |
481 | const LLUICtrl* next_view = this; | 482 | LLUICtrl* next_view = this; |
482 | while(next_view) | 483 | while(next_view) |
483 | { | 484 | { |
484 | if (next_view->isFocusRoot()) | 485 | if (next_view->isFocusRoot()) |
@@ -487,9 +488,8 @@ LLUICtrl* LLUICtrl::findRootMostFocusRoot() const | |||
487 | } | 488 | } |
488 | next_view = next_view->getParentUICtrl(); | 489 | next_view = next_view->getParentUICtrl(); |
489 | } | 490 | } |
490 | // since focus_root could be this, need to cast away const to return | 491 | |
491 | // a non-const result | 492 | return focus_root; |
492 | return const_cast<LLUICtrl*>(focus_root); | ||
493 | } | 493 | } |
494 | 494 | ||
495 | 495 | ||
@@ -551,19 +551,6 @@ LLView* LLUICtrl::fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFacto | |||
551 | } | 551 | } |
552 | 552 | ||
553 | 553 | ||
554 | // *NOTE: If other classes derive from LLPanel, they will need to be | ||
555 | // added to this function. | ||
556 | LLPanel* LLUICtrl::getParentPanel() const | ||
557 | { | ||
558 | LLView* parent = getParent(); | ||
559 | LLPanel* parent_panel = dynamic_cast<LLPanel*>(parent); | ||
560 | while (!parent_panel) | ||
561 | { | ||
562 | parent = parent->getParent(); | ||
563 | } | ||
564 | return (LLPanel*)(parent); | ||
565 | } | ||
566 | |||
567 | // Skip over any parents that are not LLUICtrl's | 554 | // Skip over any parents that are not LLUICtrl's |
568 | // Used in focus logic since only LLUICtrl elements can have focus | 555 | // Used in focus logic since only LLUICtrl elements can have focus |
569 | LLUICtrl* LLUICtrl::getParentUICtrl() const | 556 | LLUICtrl* LLUICtrl::getParentUICtrl() const |
diff --git a/linden/indra/llui/lluictrl.h b/linden/indra/llui/lluictrl.h index f11ece7..db41af8 100644 --- a/linden/indra/llui/lluictrl.h +++ b/linden/indra/llui/lluictrl.h | |||
@@ -18,7 +18,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 21 | * online at |
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
@@ -130,9 +131,7 @@ public: | |||
130 | void setTabStop( BOOL b ); | 131 | void setTabStop( BOOL b ); |
131 | BOOL hasTabStop() const; | 132 | BOOL hasTabStop() const; |
132 | 133 | ||
133 | // Returns containing panel/floater or NULL if none found. | 134 | LLUICtrl* getParentUICtrl() const; |
134 | class LLPanel* getParentPanel() const; | ||
135 | class LLUICtrl* getParentUICtrl() const; | ||
136 | 135 | ||
137 | void* getCallbackUserData() const { return mCallbackUserData; } | 136 | void* getCallbackUserData() const { return mCallbackUserData; } |
138 | void setCallbackUserData( void* data ) { mCallbackUserData = data; } | 137 | void setCallbackUserData( void* data ) { mCallbackUserData = data; } |
@@ -143,7 +142,7 @@ public: | |||
143 | 142 | ||
144 | static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory); | 143 | static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory); |
145 | 144 | ||
146 | LLUICtrl* findRootMostFocusRoot() const; | 145 | LLUICtrl* findRootMostFocusRoot(); |
147 | 146 | ||
148 | class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter> | 147 | class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter> |
149 | { | 148 | { |
diff --git a/linden/indra/llui/lluictrlfactory.cpp b/linden/indra/llui/lluictrlfactory.cpp index 07de717..983cc53 100644 --- a/linden/indra/llui/lluictrlfactory.cpp +++ b/linden/indra/llui/lluictrlfactory.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -148,7 +149,11 @@ void LLUICtrlFactory::setupPaths() | |||
148 | } | 149 | } |
149 | } | 150 | } |
150 | 151 | ||
151 | 152 | // static | |
153 | const std::vector<std::string>& LLUICtrlFactory::getXUIPaths() | ||
154 | { | ||
155 | return sXUIPaths; | ||
156 | } | ||
152 | 157 | ||
153 | //----------------------------------------------------------------------------- | 158 | //----------------------------------------------------------------------------- |
154 | // getLayeredXMLNode() | 159 | // getLayeredXMLNode() |
diff --git a/linden/indra/llui/lluictrlfactory.h b/linden/indra/llui/lluictrlfactory.h index b5b2853..5e7c24e 100644 --- a/linden/indra/llui/lluictrlfactory.h +++ b/linden/indra/llui/lluictrlfactory.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -77,7 +78,10 @@ public: | |||
77 | 78 | ||
78 | static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); | 79 | static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); |
79 | 80 | ||
81 | static const std::vector<std::string>& getXUIPaths(); | ||
82 | |||
80 | private: | 83 | private: |
84 | bool getLayeredXMLNodeImpl(const std::string &filename, LLXMLNodePtr& root); | ||
81 | 85 | ||
82 | typedef std::map<LLHandle<LLPanel>, std::string> built_panel_t; | 86 | typedef std::map<LLHandle<LLPanel>, std::string> built_panel_t; |
83 | built_panel_t mBuiltPanels; | 87 | built_panel_t mBuiltPanels; |
diff --git a/linden/indra/llui/lluifwd.h b/linden/indra/llui/lluifwd.h index ab8eb63..32d5c9b 100644 --- a/linden/indra/llui/lluifwd.h +++ b/linden/indra/llui/lluifwd.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/lluistring.cpp b/linden/indra/llui/lluistring.cpp index 974047f..0b76b8e 100644 --- a/linden/indra/llui/lluistring.cpp +++ b/linden/indra/llui/lluistring.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -31,6 +32,7 @@ | |||
31 | 32 | ||
32 | #include "linden_common.h" | 33 | #include "linden_common.h" |
33 | #include "lluistring.h" | 34 | #include "lluistring.h" |
35 | #include "llsd.h" | ||
34 | 36 | ||
35 | const LLStringUtil::format_map_t LLUIString::sNullArgs; | 37 | const LLStringUtil::format_map_t LLUIString::sNullArgs; |
36 | 38 | ||
@@ -54,6 +56,18 @@ void LLUIString::setArgList(const LLStringUtil::format_map_t& args) | |||
54 | format(); | 56 | format(); |
55 | } | 57 | } |
56 | 58 | ||
59 | void LLUIString::setArgs(const LLSD& sd) | ||
60 | { | ||
61 | if (!sd.isMap()) return; | ||
62 | for(LLSD::map_const_iterator sd_it = sd.beginMap(); | ||
63 | sd_it != sd.endMap(); | ||
64 | ++sd_it) | ||
65 | { | ||
66 | setArg(sd_it->first, sd_it->second.asString()); | ||
67 | } | ||
68 | format(); | ||
69 | } | ||
70 | |||
57 | void LLUIString::setArg(const std::string& key, const std::string& replacement) | 71 | void LLUIString::setArg(const std::string& key, const std::string& replacement) |
58 | { | 72 | { |
59 | mArgs[key] = replacement; | 73 | mArgs[key] = replacement; |
diff --git a/linden/indra/llui/lluistring.h b/linden/indra/llui/lluistring.h index 5983e1d..aedeca2 100644 --- a/linden/indra/llui/lluistring.h +++ b/linden/indra/llui/lluistring.h | |||
@@ -18,7 +18,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 21 | * online at |
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
@@ -50,9 +51,9 @@ | |||
50 | // llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life" | 51 | // llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life" |
51 | // mMessage.setArg("[USERNAME]", "Joe"); | 52 | // mMessage.setArg("[USERNAME]", "Joe"); |
52 | // llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life" | 53 | // llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life" |
53 | // mMessage = "Recepción a la [SECONDLIFE] [USERNAME]" | 54 | // mMessage = "Recepci￳n a la [SECONDLIFE] [USERNAME]" |
54 | // mMessage.setArg("[SECONDLIFE]", "Segunda Vida"); | 55 | // mMessage.setArg("[SECONDLIFE]", "Segunda Vida"); |
55 | // llinfos << mMessage.getString() << llendl; // outputs "Recepción a la Segunda Vida Joe" | 56 | // llinfos << mMessage.getString() << llendl; // outputs "Recepci￳n a la Segunda Vida Joe" |
56 | 57 | ||
57 | // Implementation Notes: | 58 | // Implementation Notes: |
58 | // Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have | 59 | // Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have |
@@ -71,6 +72,8 @@ public: | |||
71 | LLUIString& operator=(const std::string& s) { assign(s); return *this; } | 72 | LLUIString& operator=(const std::string& s) { assign(s); return *this; } |
72 | 73 | ||
73 | void setArgList(const LLStringUtil::format_map_t& args); | 74 | void setArgList(const LLStringUtil::format_map_t& args); |
75 | void setArgs(const LLStringUtil::format_map_t& args) { setArgList(args); } | ||
76 | void setArgs(const class LLSD& sd); | ||
74 | void setArg(const std::string& key, const std::string& replacement); | 77 | void setArg(const std::string& key, const std::string& replacement); |
75 | 78 | ||
76 | const std::string& getString() const { return mResult; } | 79 | const std::string& getString() const { return mResult; } |
diff --git a/linden/indra/llui/lluitrans.cpp b/linden/indra/llui/lluitrans.cpp new file mode 100644 index 0000000..920fe6a --- /dev/null +++ b/linden/indra/llui/lluitrans.cpp | |||
@@ -0,0 +1,101 @@ | |||
1 | /** | ||
2 | * @file lluitrans.cpp | ||
3 | * @brief LLUITrans implementation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | |||
34 | #include "linden_common.h" | ||
35 | #include "lluitrans.h" | ||
36 | #include "llxmlnode.h" | ||
37 | #include "lluictrlfactory.h" | ||
38 | #include "llalertdialog.h" | ||
39 | |||
40 | #include <map> | ||
41 | |||
42 | LLUITrans::template_map_t LLUITrans::sStringTemplates; | ||
43 | |||
44 | //static | ||
45 | bool LLUITrans::parseStrings(const std::string& xml_filename) | ||
46 | { | ||
47 | LLXMLNodePtr root; | ||
48 | BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); | ||
49 | |||
50 | if (!success || root.isNull() || !root->hasName( "strings" )) | ||
51 | { | ||
52 | llerrs << "Problem reading strings: " << xml_filename << llendl; | ||
53 | return false; | ||
54 | } | ||
55 | |||
56 | for (LLXMLNode* string = root->getFirstChild(); | ||
57 | string != NULL; string = string->getNextSibling()) | ||
58 | { | ||
59 | if (!string->hasName("string")) | ||
60 | { | ||
61 | continue; | ||
62 | } | ||
63 | |||
64 | std::string string_name; | ||
65 | |||
66 | if (! string->getAttributeString("name", string_name)) | ||
67 | { | ||
68 | llwarns << "Unable to parse string with no name" << llendl; | ||
69 | continue; | ||
70 | } | ||
71 | |||
72 | LLUITransTemplate xml_template(string_name, string->getTextContents()); | ||
73 | sStringTemplates[xml_template.mName] = xml_template; | ||
74 | } | ||
75 | |||
76 | return true; | ||
77 | } | ||
78 | |||
79 | //static | ||
80 | std::string LLUITrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) | ||
81 | { | ||
82 | template_map_t::iterator iter = sStringTemplates.find(xml_desc); | ||
83 | |||
84 | if (iter != sStringTemplates.end()) | ||
85 | { | ||
86 | std::string text = iter->second.mText; | ||
87 | LLStringUtil::format(text, args); | ||
88 | |||
89 | return text; | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | LLSD args; | ||
94 | args["STRING_NAME"] = xml_desc; | ||
95 | LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; | ||
96 | LLNotifications::instance().add("MissingString", args); | ||
97 | |||
98 | return xml_desc; | ||
99 | } | ||
100 | } | ||
101 | |||
diff --git a/linden/indra/llui/lluitrans.h b/linden/indra/llui/lluitrans.h new file mode 100644 index 0000000..32fb468 --- /dev/null +++ b/linden/indra/llui/lluitrans.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /** | ||
2 | * @file lluitrans.h | ||
3 | * @brief LLUITrans definition | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
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 | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
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 | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_UI_TRANS_H | ||
34 | #define LL_UI_TRANS_H | ||
35 | |||
36 | #include <map> | ||
37 | |||
38 | /** | ||
39 | * @brief String template loaded from strings.xml | ||
40 | */ | ||
41 | class LLUITransTemplate | ||
42 | { | ||
43 | public: | ||
44 | LLUITransTemplate(const std::string& name = LLStringUtil::null, const std::string& text = LLStringUtil::null) : mName(name), mText(text) {} | ||
45 | |||
46 | std::string mName; | ||
47 | std::string mText; | ||
48 | }; | ||
49 | |||
50 | class LLUITrans | ||
51 | { | ||
52 | public: | ||
53 | LLUITrans(); | ||
54 | |||
55 | /** | ||
56 | * @brief Parses the xml file that holds the strings. Used once on startup | ||
57 | * @param xml_filename Filename to parse | ||
58 | * @returns true if the file was parsed successfully, true if something went wrong | ||
59 | */ | ||
60 | static bool parseStrings(const std::string& xml_filename); | ||
61 | |||
62 | /** | ||
63 | * @brief Returns a translated string | ||
64 | * @param xml_desc String's description | ||
65 | * @param args A list of substrings to replace in the string | ||
66 | * @returns Translated string | ||
67 | */ | ||
68 | static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); | ||
69 | |||
70 | /** | ||
71 | * @brief Returns a translated string | ||
72 | * @param xml_desc String's description | ||
73 | * @returns Translated string | ||
74 | */ | ||
75 | static std::string getString(const std::string &xml_desc) | ||
76 | { | ||
77 | LLStringUtil::format_map_t empty; | ||
78 | return getString(xml_desc, empty); | ||
79 | } | ||
80 | |||
81 | |||
82 | private: | ||
83 | typedef std::map<std::string, LLUITransTemplate > template_map_t; | ||
84 | static template_map_t sStringTemplates; | ||
85 | }; | ||
86 | |||
87 | #endif | ||
diff --git a/linden/indra/llui/lluixmltags.h b/linden/indra/llui/lluixmltags.h index da31136..0456666 100644 --- a/linden/indra/llui/lluixmltags.h +++ b/linden/indra/llui/lluixmltags.h | |||
@@ -16,7 +16,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 19 | * online at |
20 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
20 | * | 21 | * |
21 | * By copying, modifying or distributing this software, you acknowledge | 22 | * By copying, modifying or distributing this software, you acknowledge |
22 | * 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.cpp b/linden/indra/llui/llundo.cpp index 05c8c11..8f57636 100644 --- a/linden/indra/llui/llundo.cpp +++ b/linden/indra/llui/llundo.cpp | |||
@@ -16,7 +16,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 19 | * online at |
20 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
20 | * | 21 | * |
21 | * By copying, modifying or distributing this software, you acknowledge | 22 | * By copying, modifying or distributing this software, you acknowledge |
22 | * 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 55d164e..b2edb57 100644 --- a/linden/indra/llui/llundo.h +++ b/linden/indra/llui/llundo.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llview.cpp b/linden/indra/llui/llview.cpp index 9cdf481..444922a 100644 --- a/linden/indra/llui/llview.cpp +++ b/linden/indra/llui/llview.cpp | |||
@@ -18,7 +18,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 21 | * online at |
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
@@ -85,7 +86,8 @@ LLView::LLView() : | |||
85 | mLastVisible(TRUE), | 86 | mLastVisible(TRUE), |
86 | mUseBoundingRect(FALSE), | 87 | mUseBoundingRect(FALSE), |
87 | mVisible(TRUE), | 88 | mVisible(TRUE), |
88 | mNextInsertionOrdinal(0) | 89 | mNextInsertionOrdinal(0), |
90 | mHoverCursor(UI_CURSOR_ARROW) | ||
89 | { | 91 | { |
90 | } | 92 | } |
91 | 93 | ||
@@ -102,7 +104,8 @@ LLView::LLView(const std::string& name, BOOL mouse_opaque) : | |||
102 | mLastVisible(TRUE), | 104 | mLastVisible(TRUE), |
103 | mUseBoundingRect(FALSE), | 105 | mUseBoundingRect(FALSE), |
104 | mVisible(TRUE), | 106 | mVisible(TRUE), |
105 | mNextInsertionOrdinal(0) | 107 | mNextInsertionOrdinal(0), |
108 | mHoverCursor(UI_CURSOR_ARROW) | ||
106 | { | 109 | { |
107 | } | 110 | } |
108 | 111 | ||
@@ -123,7 +126,8 @@ LLView::LLView( | |||
123 | mLastVisible(TRUE), | 126 | mLastVisible(TRUE), |
124 | mUseBoundingRect(FALSE), | 127 | mUseBoundingRect(FALSE), |
125 | mVisible(TRUE), | 128 | mVisible(TRUE), |
126 | mNextInsertionOrdinal(0) | 129 | mNextInsertionOrdinal(0), |
130 | mHoverCursor(UI_CURSOR_ARROW) | ||
127 | { | 131 | { |
128 | } | 132 | } |
129 | 133 | ||
@@ -657,7 +661,7 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask) | |||
657 | if( !handled | 661 | if( !handled |
658 | && blockMouseEvent(x, y) ) | 662 | && blockMouseEvent(x, y) ) |
659 | { | 663 | { |
660 | LLUI::sWindow->setCursor(UI_CURSOR_ARROW); | 664 | LLUI::sWindow->setCursor(mHoverCursor); |
661 | lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; | 665 | lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; |
662 | handled = TRUE; | 666 | handled = TRUE; |
663 | } | 667 | } |
@@ -705,9 +709,11 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s | |||
705 | LLView* viewp = *child_it; | 709 | LLView* viewp = *child_it; |
706 | S32 local_x = x - viewp->mRect.mLeft; | 710 | S32 local_x = x - viewp->mRect.mLeft; |
707 | S32 local_y = y - viewp->mRect.mBottom; | 711 | S32 local_y = y - viewp->mRect.mBottom; |
712 | // Allow tooltips for disabled views so we can explain to the user why | ||
713 | // the view is disabled. JC | ||
708 | if( viewp->pointInView(local_x, local_y) | 714 | if( viewp->pointInView(local_x, local_y) |
709 | && viewp->getVisible() | 715 | && viewp->getVisible() |
710 | && viewp->getEnabled() | 716 | // && viewp->getEnabled() |
711 | && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen )) | 717 | && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen )) |
712 | { | 718 | { |
713 | // child provided a tooltip, just return | 719 | // child provided a tooltip, just return |
@@ -1257,7 +1263,7 @@ void LLView::draw() | |||
1257 | { | 1263 | { |
1258 | LLView *viewp = *child_iter; | 1264 | LLView *viewp = *child_iter; |
1259 | 1265 | ||
1260 | if (viewp->getVisible() && viewp != focus_view) | 1266 | if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid()) |
1261 | { | 1267 | { |
1262 | // Only draw views that are within the root view | 1268 | // Only draw views that are within the root view |
1263 | localRectToScreen(viewp->getRect(),&screenRect); | 1269 | localRectToScreen(viewp->getRect(),&screenRect); |
@@ -1340,7 +1346,7 @@ void LLView::drawDebugRect() | |||
1340 | y = debug_rect.getHeight()/2; | 1346 | y = debug_rect.getHeight()/2; |
1341 | std::string debug_text = llformat("%s (%d x %d)", getName().c_str(), | 1347 | std::string debug_text = llformat("%s (%d x %d)", getName().c_str(), |
1342 | debug_rect.getWidth(), debug_rect.getHeight()); | 1348 | debug_rect.getWidth(), debug_rect.getHeight()); |
1343 | LLFontGL::sSansSerifSmall->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, | 1349 | LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, |
1344 | LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, | 1350 | LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, |
1345 | S32_MAX, S32_MAX, NULL, FALSE); | 1351 | S32_MAX, S32_MAX, NULL, FALSE); |
1346 | } | 1352 | } |
@@ -1354,7 +1360,8 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr | |||
1354 | { | 1360 | { |
1355 | ++sDepth; | 1361 | ++sDepth; |
1356 | 1362 | ||
1357 | if (childp->getVisible() || force_draw) | 1363 | if ((childp->getVisible() && childp->getRect().isValid()) |
1364 | || force_draw) | ||
1358 | { | 1365 | { |
1359 | glMatrixMode(GL_MODELVIEW); | 1366 | glMatrixMode(GL_MODELVIEW); |
1360 | LLUI::pushMatrix(); | 1367 | LLUI::pushMatrix(); |
@@ -2544,6 +2551,13 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent) | |||
2544 | node->getAttributeBOOL("visible", visible); | 2551 | node->getAttributeBOOL("visible", visible); |
2545 | setVisible(visible); | 2552 | setVisible(visible); |
2546 | } | 2553 | } |
2554 | |||
2555 | if (node->hasAttribute("hover_cursor")) | ||
2556 | { | ||
2557 | std::string cursor_string; | ||
2558 | node->getAttributeString("hover_cursor", cursor_string); | ||
2559 | mHoverCursor = getCursorFromString(cursor_string); | ||
2560 | } | ||
2547 | 2561 | ||
2548 | node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect); | 2562 | node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect); |
2549 | node->getAttributeBOOL("mouse_opaque", mMouseOpaque); | 2563 | node->getAttributeBOOL("mouse_opaque", mMouseOpaque); |
@@ -2595,19 +2609,40 @@ void LLView::parseFollowsFlags(LLXMLNodePtr node) | |||
2595 | } | 2609 | } |
2596 | } | 2610 | } |
2597 | 2611 | ||
2598 | |||
2599 | // static | 2612 | // static |
2600 | LLFontGL* LLView::selectFont(LLXMLNodePtr node) | 2613 | LLFontGL* LLView::selectFont(LLXMLNodePtr node) |
2601 | { | 2614 | { |
2602 | LLFontGL* gl_font = NULL; | 2615 | std::string font_name, font_size, font_style; |
2603 | 2616 | U8 style = 0; | |
2617 | |||
2604 | if (node->hasAttribute("font")) | 2618 | if (node->hasAttribute("font")) |
2605 | { | 2619 | { |
2606 | std::string font_name; | ||
2607 | node->getAttributeString("font", font_name); | 2620 | node->getAttributeString("font", font_name); |
2621 | } | ||
2622 | |||
2623 | if (node->hasAttribute("font_size")) | ||
2624 | { | ||
2625 | node->getAttributeString("font_size", font_size); | ||
2626 | } | ||
2608 | 2627 | ||
2609 | gl_font = LLFontGL::fontFromName(font_name); | 2628 | if (node->hasAttribute("font_style")) |
2629 | { | ||
2630 | node->getAttributeString("font_style", font_style); | ||
2631 | style = LLFontGL::getStyleFromString(font_style); | ||
2632 | } | ||
2633 | |||
2634 | if (node->hasAttribute("font-style")) | ||
2635 | { | ||
2636 | node->getAttributeString("font-style", font_style); | ||
2637 | style = LLFontGL::getStyleFromString(font_style); | ||
2610 | } | 2638 | } |
2639 | |||
2640 | if (font_name.empty()) | ||
2641 | return NULL; | ||
2642 | |||
2643 | LLFontDescriptor desc(font_name, font_size, style); | ||
2644 | LLFontGL* gl_font = LLFontGL::getFont(desc); | ||
2645 | |||
2611 | return gl_font; | 2646 | return gl_font; |
2612 | } | 2647 | } |
2613 | 2648 | ||
diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h index 80dd348..b5a34bd 100644 --- a/linden/indra/llui/llview.h +++ b/linden/indra/llui/llview.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -51,6 +52,7 @@ | |||
51 | #include "llxmlnode.h" | 52 | #include "llxmlnode.h" |
52 | #include "stdenums.h" | 53 | #include "stdenums.h" |
53 | #include "lluistring.h" | 54 | #include "lluistring.h" |
55 | #include "llcursortypes.h" | ||
54 | 56 | ||
55 | const U32 FOLLOWS_NONE = 0x00; | 57 | const U32 FOLLOWS_NONE = 0x00; |
56 | const U32 FOLLOWS_LEFT = 0x01; | 58 | const U32 FOLLOWS_LEFT = 0x01; |
@@ -484,7 +486,7 @@ public: | |||
484 | // did we find *something* with that name? | 486 | // did we find *something* with that name? |
485 | if (child) | 487 | if (child) |
486 | { | 488 | { |
487 | llwarns << "Found child named " << name << " but of wrong type" << llendl; | 489 | llwarns << "Found child named " << name << " but of wrong type " << typeid(child).name() << ", expecting " << typeid(T).name() << llendl; |
488 | } | 490 | } |
489 | if (create_if_missing) | 491 | if (create_if_missing) |
490 | { | 492 | { |
@@ -495,6 +497,11 @@ public: | |||
495 | return result; | 497 | return result; |
496 | } | 498 | } |
497 | 499 | ||
500 | template <class T> T& getChildRef(const std::string& name, BOOL recurse = TRUE) const | ||
501 | { | ||
502 | return *getChild<T>(name, recurse, TRUE); | ||
503 | } | ||
504 | |||
498 | virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; | 505 | virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; |
499 | 506 | ||
500 | template <class T> T* createDummyWidget(const std::string& name) const | 507 | template <class T> T* createDummyWidget(const std::string& name) const |
@@ -649,6 +656,8 @@ private: | |||
649 | mutable dummy_widget_map_t mDummyWidgets; | 656 | mutable dummy_widget_map_t mDummyWidgets; |
650 | 657 | ||
651 | boost::signals::connection mControlConnection; | 658 | boost::signals::connection mControlConnection; |
659 | |||
660 | ECursorType mHoverCursor; | ||
652 | 661 | ||
653 | public: | 662 | public: |
654 | static BOOL sDebugRects; // Draw debug rects behind everything. | 663 | static BOOL sDebugRects; // Draw debug rects behind everything. |
diff --git a/linden/indra/llui/llviewborder.cpp b/linden/indra/llui/llviewborder.cpp index ae24694..d4a9e9d 100644 --- a/linden/indra/llui/llviewborder.cpp +++ b/linden/indra/llui/llviewborder.cpp | |||
@@ -16,7 +16,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 19 | * online at |
20 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
20 | * | 21 | * |
21 | * By copying, modifying or distributing this software, you acknowledge | 22 | * By copying, modifying or distributing this software, you acknowledge |
22 | * that you have read and understood your obligations described above, | 23 | * that you have read and understood your obligations described above, |
@@ -231,8 +232,7 @@ void LLViewBorder::drawTextures() | |||
231 | //gGL.color4fv(UI_VERTEX_COLOR.mV); | 232 | //gGL.color4fv(UI_VERTEX_COLOR.mV); |
232 | 233 | ||
233 | //gGL.getTexUnit(0)->bind(mTexture); | 234 | //gGL.getTexUnit(0)->bind(mTexture); |
234 | //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); | 235 | //gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); |
235 | //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); | ||
236 | 236 | ||
237 | //drawTextureTrapezoid( 0.f, mBorderWidth, getRect().getWidth(), 0, 0 ); | 237 | //drawTextureTrapezoid( 0.f, mBorderWidth, getRect().getWidth(), 0, 0 ); |
238 | //drawTextureTrapezoid( 90.f, mBorderWidth, getRect().getHeight(), (F32)getRect().getWidth(),0 ); | 238 | //drawTextureTrapezoid( 90.f, mBorderWidth, getRect().getHeight(), (F32)getRect().getWidth(),0 ); |
diff --git a/linden/indra/llui/llviewborder.h b/linden/indra/llui/llviewborder.h index 7f72d54..a40e653 100644 --- a/linden/indra/llui/llviewborder.h +++ b/linden/indra/llui/llviewborder.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llviewquery.cpp b/linden/indra/llui/llviewquery.cpp index fe3c308..bdb3d22 100644 --- a/linden/indra/llui/llviewquery.cpp +++ b/linden/indra/llui/llviewquery.cpp | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * 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/llviewquery.h b/linden/indra/llui/llviewquery.h index a8cec09..e87795f 100644 --- a/linden/indra/llui/llviewquery.h +++ b/linden/indra/llui/llviewquery.h | |||
@@ -17,7 +17,8 @@ | |||
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://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |