diff options
Diffstat (limited to 'indra/llui')
34 files changed, 571 insertions, 184 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index f0b4436df5..74b49b846e 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -60,6 +60,7 @@ set(llui_SOURCE_FILES llmultisliderctrl.cpp llnotifications.cpp llnotificationslistener.cpp + llnotificationsutil.cpp llpanel.cpp llprogressbar.cpp llradiogroup.cpp @@ -147,8 +148,10 @@ set(llui_HEADER_FILES llmultifloater.h llmultisliderctrl.h llmultislider.h + llnotificationptr.h llnotifications.h llnotificationslistener.h + llnotificationsutil.h llpanel.h llprogressbar.h llradiogroup.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 8930e32055..7721137e29 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -32,6 +32,7 @@ #include "linden_common.h" +#define LLBUTTON_CPP #include "llbutton.h" // Linden library includes @@ -48,7 +49,7 @@ #include "llfloaterreg.h" #include "llfocusmgr.h" #include "llwindow.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llrender.h" #include "lluictrlfactory.h" #include "llhelp.h" @@ -56,6 +57,10 @@ static LLDefaultChildRegistry::Register<LLButton> r("button"); +// Compiler optimization, generate extern template +template class LLButton* LLView::getChild<class LLButton>( + const std::string& name, BOOL recurse) const; + // globals loaded from settings.xml S32 LLBUTTON_H_PAD = 0; S32 LLBUTTON_V_PAD = 0; @@ -1106,7 +1111,7 @@ void LLButton::showHelp(LLUICtrl* ctrl, const LLSD& sdname) // display an error if we can't find a help_topic string. // fix this by adding a help_topic attribute to the xui file - LLNotifications::instance().add("UnableToFindHelpTopic"); + LLNotificationsUtil::add("UnableToFindHelpTopic"); } void LLButton::resetMouseDownTimer() diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 8c3b4bd859..4c7400220d 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -322,5 +322,10 @@ private: LLFrameTimer mFlashingTimer; }; +// Build time optimization, generate once in .cpp file +#ifndef LLBUTTON_CPP +extern template class LLButton* LLView::getChild<class LLButton>( + const std::string& name, BOOL recurse) const; +#endif #endif // LL_LLBUTTON_H diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 7f0f9751db..cd10dfdb1c 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -33,6 +33,7 @@ // The mutants are coming! #include "linden_common.h" +#define LLCHECKBOXCTRL_CPP #include "llcheckboxctrl.h" #include "llgl.h" @@ -50,6 +51,10 @@ const U32 MAX_STRING_LENGTH = 10; static LLDefaultChildRegistry::Register<LLCheckBoxCtrl> r("check_box"); +// Compiler optimization, generate extern template +template class LLCheckBoxCtrl* LLView::getChild<class LLCheckBoxCtrl>( + const std::string& name, BOOL recurse) const; + LLCheckBoxCtrl::Params::Params() : text_enabled_color("text_enabled_color"), text_disabled_color("text_disabled_color"), diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index b14e66b915..28d50f957d 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -126,5 +126,10 @@ protected: LLUIColor mTextDisabledColor; }; +// Build time optimization, generate once in .cpp file +#ifndef LLCHECKBOXCTRL_CPP +extern template class LLCheckBoxCtrl* LLView::getChild<class LLCheckBoxCtrl>( + const std::string& name, BOOL recurse) const; +#endif #endif // LL_LLCHECKBOXCTRL_H diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 8de3a8a96f..ddfb0f8534 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -484,6 +484,8 @@ void LLFlatListView::rearrangeItems() void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) { if (!item_pair) return; + + setFocus(TRUE); bool select_item = !isSelected(item_pair); @@ -554,12 +556,21 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) break; } - if ( key == KEY_UP || key == KEY_DOWN ) + if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) { - LLRect selcted_rect = getLastSelectedItemRect().stretch(1); - LLRect visible_rect = getVisibleContentRect(); - if ( !visible_rect.contains (selcted_rect) ) - scrollToShowRect(selcted_rect); + LLRect visible_rc = getVisibleContentRect(); + LLRect selected_rc = getLastSelectedItemRect(); + + if ( !visible_rc.contains (selected_rc) ) + { + // But scroll in Items panel coordinates + scrollToShowRect(selected_rc); + } + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().insert("scrollToShowRect",screen_rc.getValue())); handled = TRUE; } @@ -645,8 +656,6 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select) onCommit(); } - setFocus(TRUE); - // Stretch selected items rect to ensure it won't be clipped mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1)); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 262afbe661..36a9e0a650 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -66,27 +66,6 @@ // use this to control "jumping" behavior when Ctrl-Tabbing const S32 TABBED_FLOATER_OFFSET = 0; -std::string LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = -{ - "Icon_Close_Foreground", //BUTTON_CLOSE - "Icon_Restore_Foreground", //BUTTON_RESTORE - "Icon_Minimize_Foreground", //BUTTON_MINIMIZE - "tearoffbox.tga", //BUTTON_TEAR_OFF - "Icon_Dock_Foreground", //BUTTON_DOCK - "Icon_Undock_Foreground", //BUTTON_UNDOCK - "Icon_Help_Foreground" //BUTTON_HELP -}; - -std::string LLFloater::sButtonPressedImageNames[BUTTON_COUNT] = -{ - "Icon_Close_Press", //BUTTON_CLOSE - "Icon_Restore_Press", //BUTTON_RESTORE - "Icon_Minimize_Press", //BUTTON_MINIMIZE - "tearoff_pressed.tga", //BUTTON_TEAR_OFF - "Icon_Dock_Press", //BUTTON_DOCK - "Icon_Undock_Press", //BUTTON_UNDOCK - "Icon_Help_Press" //BUTTON_HELP -}; std::string LLFloater::sButtonNames[BUTTON_COUNT] = { @@ -195,6 +174,20 @@ LLFloater::Params::Params() can_dock("can_dock", false), header_height("header_height", 0), legacy_header_height("legacy_header_height", 0), + close_image("close_image"), + restore_image("restore_image"), + minimize_image("minimize_image"), + tear_off_image("tear_off_image"), + dock_image("dock_image"), + undock_image("undock_image"), + help_image("help_image"), + close_pressed_image("close_pressed_image"), + restore_pressed_image("restore_pressed_image"), + minimize_pressed_image("minimize_pressed_image"), + tear_off_pressed_image("tear_off_pressed_image"), + dock_pressed_image("dock_pressed_image"), + undock_pressed_image("undock_pressed_image"), + help_pressed_image("help_pressed_image"), open_callback("open_callback"), close_callback("close_callback") { @@ -247,11 +240,11 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mDocked(false), mHasBeenDraggedWhileMinimized(FALSE), mPreviousMinimizedBottom(0), - mPreviousMinimizedLeft(0), - mNotificationContext(NULL) + mPreviousMinimizedLeft(0) +// mNotificationContext(NULL) { mHandle.bind(this); - mNotificationContext = new LLFloaterNotificationContext(getHandle()); +// mNotificationContext = new LLFloaterNotificationContext(getHandle()); // Clicks stop here. setMouseOpaque(TRUE); @@ -263,11 +256,9 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) // prior rectangle to be used on restore. mExpandedRect.set(0,0,0,0); - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; - } + memset(mButtonsEnabled, 0, BUTTON_COUNT * sizeof(bool)); + memset(mButtons, 0, BUTTON_COUNT * sizeof(LLButton*)); + addDragHandle(); addResizeCtrls(); @@ -276,11 +267,11 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) // chrome floaters don't take focus at all setFocusRoot(!getIsChrome()); - initFloater(); + initFloater(p); } // Note: Floaters constructed from XML call init() twice! -void LLFloater::initFloater() +void LLFloater::initFloater(const Params& p) { // Close button. if (mCanClose) @@ -305,7 +296,7 @@ void LLFloater::initFloater() mButtonsEnabled[BUTTON_DOCK] = TRUE; } - buildButtons(); + buildButtons(p); // Floaters are created in the invisible state setVisible(FALSE); @@ -468,8 +459,8 @@ LLFloater::~LLFloater() { LLFloaterReg::removeInstance(mInstanceName, mKey); - delete mNotificationContext; - mNotificationContext = NULL; +// delete mNotificationContext; +// mNotificationContext = NULL; //// am I not hosted by another floater? //if (mHostHandle.isDead()) @@ -1280,7 +1271,7 @@ void LLFloater::removeDependentFloater(LLFloater* floaterp) floaterp->mDependeeHandle = LLHandle<LLFloater>(); } -BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index) +BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index) { if( mButtonsEnabled[index] ) { @@ -1798,7 +1789,7 @@ void LLFloater::updateButtons() mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1))); } -void LLFloater::buildButtons() +void LLFloater::buildButtons(const Params& floater_params) { static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); static LLUICachedControl<S32> close_box_from_top ("UICloseBoxFromTop", 0); @@ -1832,17 +1823,18 @@ void LLFloater::buildButtons() LLButton::Params p; p.name(sButtonNames[i]); p.rect(btn_rect); - p.image_unselected.name(sButtonActiveImageNames[i]); + p.image_unselected = getButtonImage(floater_params, (EFloaterButton)i); // Selected, no matter if hovered or not, is "pressed" - p.image_selected.name(sButtonPressedImageNames[i]); - p.image_hover_selected.name(sButtonPressedImageNames[i]); + LLUIImage* pressed_image = getButtonPressedImage(floater_params, (EFloaterButton)i); + p.image_selected = pressed_image; + p.image_hover_selected = pressed_image; // Use a glow effect when the user hovers over the button // These icons are really small, need glow amount increased p.hover_glow_amount( 0.33f ); p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); p.tab_stop(false); p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); - p.tool_tip(sButtonToolTips[i]); + p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i); p.scale_image(true); p.chrome(true); @@ -1854,6 +1846,59 @@ void LLFloater::buildButtons() updateButtons(); } +// static +LLUIImage* LLFloater::getButtonImage(const Params& p, EFloaterButton e) +{ + switch(e) + { + default: + case BUTTON_CLOSE: + return p.close_image; + case BUTTON_RESTORE: + return p.restore_image; + case BUTTON_MINIMIZE: + return p.minimize_image; + case BUTTON_TEAR_OFF: + return p.tear_off_image; + case BUTTON_DOCK: + return p.dock_image; + case BUTTON_UNDOCK: + return p.undock_image; + case BUTTON_HELP: + return p.help_image; + } +} + +// static +LLUIImage* LLFloater::getButtonPressedImage(const Params& p, EFloaterButton e) +{ + switch(e) + { + default: + case BUTTON_CLOSE: + return p.close_pressed_image; + case BUTTON_RESTORE: + return p.restore_pressed_image; + case BUTTON_MINIMIZE: + return p.minimize_pressed_image; + case BUTTON_TEAR_OFF: + return p.tear_off_pressed_image; + case BUTTON_DOCK: + return p.dock_pressed_image; + case BUTTON_UNDOCK: + return p.undock_pressed_image; + case BUTTON_HELP: + return p.help_pressed_image; + } +} + +// static +std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e) +{ + // TODO: per-floater localizable tooltips set in XML + return sButtonToolTips[e]; +} + ///////////////////////////////////////////////////// // LLFloaterView @@ -2302,8 +2347,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out } LLRect::tCoordType screen_width = getSnapRect().getWidth(); LLRect::tCoordType screen_height = getSnapRect().getHeight(); - // convert to local coordinate frame - LLRect snap_rect_local = getLocalSnapRect(); + // only automatically resize non-minimized, resizable floaters if( floater->isResizable() && !floater->isMinimized() ) @@ -2343,7 +2387,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out } // move window fully onscreen - if (floater->translateIntoRect( snap_rect_local, allow_partial_outside )) + if (floater->translateIntoRect( getLocalRect(), allow_partial_outside )) { floater->clearSnapTarget(); } @@ -2672,7 +2716,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o setupParams(params, parent); initFromParams(params); - initFloater(); + initFloater(params); LLMultiFloater* last_host = LLFloater::getFloaterHost(); if (node->hasName("multi_floater")) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 1b98dddddc..d7ec0aac00 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -39,7 +39,7 @@ #include "llpanel.h" #include "lluuid.h" -#include "llnotifications.h" +//#include "llnotificationsutil.h" #include <set> class LLDragHandle; @@ -65,20 +65,6 @@ const BOOL CLOSE_NO = FALSE; const BOOL ADJUST_VERTICAL_YES = TRUE; const BOOL ADJUST_VERTICAL_NO = FALSE; -// associates a given notification instance with a particular floater -class LLFloaterNotificationContext : - public LLNotificationContext -{ -public: - LLFloaterNotificationContext(LLHandle<LLFloater> floater_handle) : - mFloaterHandle(floater_handle) - {} - - LLFloater* getFloater() { return mFloaterHandle.get(); } -private: - LLHandle<LLFloater> mFloaterHandle; -}; - class LLFloater : public LLPanel { friend class LLFloaterView; @@ -97,7 +83,7 @@ public: |*==========================================================================*/ }; - enum EFloaterButtons + enum EFloaterButton { BUTTON_CLOSE = 0, BUTTON_RESTORE, @@ -128,6 +114,22 @@ public: can_dock; Optional<S32> header_height, legacy_header_height; // HACK see initFromXML() + + // Images for top-right controls + Optional<LLUIImage*> close_image, + restore_image, + minimize_image, + tear_off_image, + dock_image, + undock_image, + help_image; + Optional<LLUIImage*> close_pressed_image, + restore_pressed_image, + minimize_pressed_image, + tear_off_pressed_image, + dock_pressed_image, + undock_pressed_image, + help_pressed_image; Optional<CommitCallbackParam> open_callback, close_callback; @@ -158,7 +160,7 @@ public: /*virtual*/ void setIsChrome(BOOL is_chrome); /*virtual*/ void setRect(const LLRect &rect); - void initFloater(); + void initFloater(const Params& p); void openFloater(const LLSD& key = LLSD()); @@ -264,10 +266,10 @@ public: // handle refocusing. static void closeFocusedFloater(); - LLNotification::Params contextualNotification(const std::string& name) - { - return LLNotification::Params(name).context(mNotificationContext); - } +// LLNotification::Params contextualNotification(const std::string& name) +// { +// return LLNotification::Params(name).context(mNotificationContext); +// } static void onClickClose(LLFloater* floater); static void onClickMinimize(LLFloater* floater); @@ -309,8 +311,15 @@ private: void cleanupHandles(); // remove handles to dead floaters void createMinimizeButton(); void updateButtons(); - void buildButtons(); - BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); + void buildButtons(const Params& p); + + // Images and tooltips are named in the XML, but we want to look them + // up by index. + static LLUIImage* getButtonImage(const Params& p, EFloaterButton e); + static LLUIImage* getButtonPressedImage(const Params& p, EFloaterButton e); + static std::string getButtonTooltip(const Params& p, EFloaterButton e); + + BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index); void addResizeCtrls(); void layoutResizeCtrls(); void enableResizeCtrls(bool enable); @@ -368,7 +377,7 @@ private: typedef std::set<LLHandle<LLFloater> >::iterator handle_set_iter_t; handle_set_t mDependents; - BOOL mButtonsEnabled[BUTTON_COUNT]; + bool mButtonsEnabled[BUTTON_COUNT]; LLButton* mButtons[BUTTON_COUNT]; F32 mButtonScale; BOOL mAutoFocus; @@ -382,8 +391,6 @@ private: static LLMultiFloater* sHostp; static BOOL sQuitting; - static std::string sButtonActiveImageNames[BUTTON_COUNT]; - static std::string sButtonPressedImageNames[BUTTON_COUNT]; static std::string sButtonNames[BUTTON_COUNT]; static std::string sButtonToolTips[BUTTON_COUNT]; static std::string sButtonToolTipsIndex[BUTTON_COUNT]; @@ -401,7 +408,7 @@ private: S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; - LLFloaterNotificationContext* mNotificationContext; +// LLFloaterNotificationContext* mNotificationContext; LLRootHandle<LLFloater> mHandle; }; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index bd5734312a..8a21155cc3 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -34,6 +34,7 @@ #include "linden_common.h" +#define LLLINEEDITOR_CPP #include "lllineeditor.h" #include "lltexteditor.h" @@ -71,6 +72,10 @@ const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor"); +// Compiler optimization, generate extern template +template class LLLineEditor* LLView::getChild<class LLLineEditor>( + const std::string& name, BOOL recurse) const; + // // Member functions // @@ -125,8 +130,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mScrollHPos( 0 ), mTextPadLeft(p.text_pad_left), mTextPadRight(p.text_pad_right), - mMinHPixels(0), // computed in updateTextPadding() below - mMaxHPixels(0), // computed in updateTextPadding() below + mTextLeftEdge(0), // computed in updateTextPadding() below + mTextRightEdge(0), // computed in updateTextPadding() below mCommitOnFocusLost( p.commit_on_focus_lost ), mRevertOnEsc( p.revert_on_esc ), mKeystrokeCallback( p.keystroke_callback() ), @@ -338,9 +343,8 @@ void LLLineEditor::setTextPadding(S32 left, S32 right) void LLLineEditor::updateTextPadding() { - static LLUICachedControl<S32> line_editor_hpad ("UILineEditorHPad", 0); - mMinHPixels = line_editor_hpad + llclamp(mTextPadLeft, 0, getRect().getWidth());; - mMaxHPixels = getRect().getWidth() - mMinHPixels - llclamp(mTextPadRight, 0, getRect().getWidth()); + mTextLeftEdge = llclamp(mTextPadLeft, 0, getRect().getWidth()); + mTextRightEdge = getRect().getWidth() - llclamp(mTextPadRight, 0, getRect().getWidth()); } @@ -406,8 +410,8 @@ void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x ) mScrollHPos + mGLFont->charFromPixelOffset( wtext, mScrollHPos, - (F32)(local_mouse_x - mMinHPixels), - (F32)(mMaxHPixels - mMinHPixels + 1)); // min-max range is inclusive + (F32)(local_mouse_x - mTextLeftEdge), + (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive setCursor(cursor_pos); } @@ -417,11 +421,11 @@ void LLLineEditor::setCursor( S32 pos ) mCursorPos = llclamp( pos, 0, mText.length()); S32 pixels_after_scroll = findPixelNearestPos(); - if( pixels_after_scroll > mMaxHPixels ) + if( pixels_after_scroll > mTextRightEdge ) { S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); - S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left))); - S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels), mText.length(), getCursor()); + S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mTextRightEdge - mTextLeftEdge + width_chars_to_left))); + S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), getCursor()); if (old_cursor_pos == last_visible_char) { mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); @@ -682,17 +686,17 @@ BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask) S32 increment = llround(mScrollTimer.getElapsedTimeF32() / AUTO_SCROLL_TIME); mScrollTimer.reset(); mScrollTimer.setTimerExpirySec(AUTO_SCROLL_TIME); - if( (x < mMinHPixels) && (mScrollHPos > 0 ) ) + if( (x < mTextLeftEdge) && (mScrollHPos > 0 ) ) { // Scroll to the left mScrollHPos = llclamp(mScrollHPos - increment, 0, mText.length()); } else - if( (x > mMaxHPixels) && (mCursorPos < (S32)mText.length()) ) + if( (x > mTextRightEdge) && (mCursorPos < (S32)mText.length()) ) { // If scrolling one pixel would make a difference... S32 pixels_after_scrolling_one_char = findPixelNearestPos(1); - if( pixels_after_scrolling_one_char >= mMaxHPixels ) + if( pixels_after_scrolling_one_char >= mTextRightEdge ) { // ...scroll to the right mScrollHPos = llclamp(mScrollHPos + increment, 0, mText.length()); @@ -1671,7 +1675,7 @@ void LLLineEditor::draw() } S32 rendered_text = 0; - F32 rendered_pixels_right = (F32)mMinHPixels; + F32 rendered_pixels_right = (F32)mTextLeftEdge; F32 text_bottom = (F32)background.mBottom + (F32)lineeditor_v_pad; if( (gFocusMgr.getKeyboardFocus() == this) && hasSelection() ) @@ -1700,17 +1704,17 @@ void LLLineEditor::draw() 0, LLFontGL::NO_SHADOW, select_left - mScrollHPos, - mMaxHPixels - llround(rendered_pixels_right), + mTextRightEdge - llround(rendered_pixels_right), &rendered_pixels_right); } - if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) ) + if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) { LLColor4 color = mHighlightColor; color.setAlpha(alpha); // selected middle S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text); - width = llmin(width, mMaxHPixels - llround(rendered_pixels_right)); + width = llmin(width, mTextRightEdge - llround(rendered_pixels_right)); gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color); LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ); @@ -1722,11 +1726,11 @@ void LLLineEditor::draw() 0, LLFontGL::NO_SHADOW, select_right - mScrollHPos - rendered_text, - mMaxHPixels - llround(rendered_pixels_right), + mTextRightEdge - llround(rendered_pixels_right), &rendered_pixels_right); } - if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) ) + if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) { // unselected, right side mGLFont->render( @@ -1737,7 +1741,7 @@ void LLLineEditor::draw() 0, LLFontGL::NO_SHADOW, S32_MAX, - mMaxHPixels - llround(rendered_pixels_right), + mTextRightEdge - llround(rendered_pixels_right), &rendered_pixels_right); } } @@ -1751,7 +1755,7 @@ void LLLineEditor::draw() 0, LLFontGL::NO_SHADOW, S32_MAX, - mMaxHPixels - llround(rendered_pixels_right), + mTextRightEdge - llround(rendered_pixels_right), &rendered_pixels_right); } #if 1 // for when we're ready for image art. @@ -1809,14 +1813,14 @@ void LLLineEditor::draw() if (0 == mText.length() && mReadOnly) { mGLFont->render(mLabel.getWString(), 0, - mMinHPixels, (F32)text_bottom, + mTextLeftEdge, (F32)text_bottom, label_color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, S32_MAX, - mMaxHPixels - llround(rendered_pixels_right), + mTextRightEdge - llround(rendered_pixels_right), &rendered_pixels_right, FALSE); } @@ -1834,14 +1838,14 @@ void LLLineEditor::draw() if (0 == mText.length()) { mGLFont->render(mLabel.getWString(), 0, - mMinHPixels, (F32)text_bottom, + mTextLeftEdge, (F32)text_bottom, label_color, LLFontGL::LEFT, LLFontGL::BOTTOM, 0, LLFontGL::NO_SHADOW, S32_MAX, - mMaxHPixels - llround(rendered_pixels_right), + mTextRightEdge - llround(rendered_pixels_right), &rendered_pixels_right, FALSE); } // Draw children (border) @@ -1859,7 +1863,7 @@ void LLLineEditor::draw() S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const { S32 dpos = getCursor() - mScrollHPos + cursor_offset; - S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mMinHPixels; + S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mTextLeftEdge; return result; } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 4c4b00094d..49e9539b16 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -303,8 +303,8 @@ protected: LLFrameTimer mScrollTimer; S32 mTextPadLeft; // Used to reserve space before the beginning of the text for children. S32 mTextPadRight; // Used to reserve space after the end of the text for children. - S32 mMinHPixels; - S32 mMaxHPixels; + S32 mTextLeftEdge; // Pixels, cached left edge of text based on left padding and width + S32 mTextRightEdge; // Pixels, cached right edge of text based on right padding and width BOOL mCommitOnFocusLost; BOOL mRevertOnEsc; @@ -395,5 +395,10 @@ private: }; // end class LLLineEditor +// Build time optimization, generate once in .cpp file +#ifndef LLLINEEDITOR_CPP +extern template class LLLineEditor* LLView::getChild<class LLLineEditor>( + const std::string& name, BOOL recurse) const; +#endif #endif // LL_LINEEDITOR_ diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h new file mode 100644 index 0000000000..0718f7d182 --- /dev/null +++ b/indra/llui/llnotificationptr.h @@ -0,0 +1,41 @@ +/** + * @file llnotificationptr.h + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLNOTIFICATIONPTR_H +#define LLNOTIFICATIONPTR_H + +// Many classes just store a single LLNotificationPtr +// and llnotifications.h is very large, so define this ligher header. +#include <boost/shared_ptr.hpp> + +class LLNotification; +typedef boost::shared_ptr<LLNotification> LLNotificationPtr; + +#endif diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index eb8cc3e2c5..05f2d3a9cf 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1395,10 +1395,9 @@ void LLNotifications::addFromCallback(const LLSD& name) add(LLNotification::Params().name(name.asString())); } -// we provide a couple of simple add notification functions so that it's reasonable to create notifications in one line LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload) + const LLSD& substitutions, + const LLSD& payload) { LLNotification::Params::Functor functor_p; functor_p.name = name; @@ -1406,15 +1405,16 @@ LLNotificationPtr LLNotifications::add(const std::string& name, } LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - const std::string& functor_name) + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name) { LLNotification::Params::Functor functor_p; functor_p.name = functor_name; return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } - + +//virtual LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 0d7cb74f70..aeb4cebf1b 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -103,9 +103,7 @@ #include "llpointer.h" #include "llinitparam.h" #include "llnotificationslistener.h" - -class LLNotification; -typedef boost::shared_ptr<LLNotification> LLNotificationPtr; +#include "llnotificationptr.h" typedef enum e_notification_priority @@ -841,10 +839,11 @@ public: // Add a simple notification (from XUI) void addFromCallback(const LLSD& name); - // we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line + // *NOTE: To add simple notifications, #include "llnotificationsutil.h" + // and use LLNotificationsUtil::add("MyNote") or add("MyNote", args) LLNotificationPtr add(const std::string& name, - const LLSD& substitutions = LLSD(), - const LLSD& payload = LLSD()); + const LLSD& substitutions, + const LLSD& payload); LLNotificationPtr add(const std::string& name, const LLSD& substitutions, const LLSD& payload, diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp new file mode 100644 index 0000000000..2cd165f1b3 --- /dev/null +++ b/indra/llui/llnotificationsutil.cpp @@ -0,0 +1,91 @@ +/** + * @file llnotificationsutil.cpp + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llnotificationsutil.h" + +#include "llnotifications.h" +#include "llsd.h" +#include "llxmlnode.h" // apparently needed to call LLNotifications::instance() + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name) +{ + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(LLSD()).payload(LLSD()).functor(functor_p)); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions) +{ + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(LLSD()).functor(functor_p)); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload) +{ + LLNotification::Params::Functor functor_p; + functor_p.name = name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name) +{ + LLNotification::Params::Functor functor_p; + functor_p.name = functor_name; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function<void (const LLSD&, const LLSD&)> functor) +{ + LLNotification::Params::Functor functor_p; + functor_p.function = functor; + return LLNotifications::instance().add( + LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); +} + +S32 LLNotificationsUtil::getSelectedOption(const LLSD& notification, const LLSD& response) +{ + return LLNotification::getSelectedOption(notification, response); +} diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h new file mode 100644 index 0000000000..a0801b338f --- /dev/null +++ b/indra/llui/llnotificationsutil.h @@ -0,0 +1,68 @@ +/** + * @file llnotificationsutil.h + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLNOTIFICATIONSUTIL_H +#define LLNOTIFICATIONSUTIL_H + +// The vast majority of clients of the notifications system just want to add +// a notification to the screen, so define this lightweight public interface +// to avoid including the heavyweight llnotifications.h + +#include "llnotificationptr.h" + +#include <boost/function.hpp> + +class LLSD; + +namespace LLNotificationsUtil +{ + LLNotificationPtr add(const std::string& name); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function<void (const LLSD&, const LLSD&)> functor); + + S32 getSelectedOption(const LLSD& notification, const LLSD& response); +} + +#endif diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 063822dd56..750b190953 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -34,6 +34,7 @@ #include "linden_common.h" +#define LLPANEL_CPP #include "llpanel.h" #include "llalertdialog.h" @@ -58,6 +59,10 @@ static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML); +// Compiler optimization, generate extern template +template class LLPanel* LLView::getChild<class LLPanel>( + const std::string& name, BOOL recurse) const; + LLPanel::LocalizedString::LocalizedString() : name("name"), value("value") diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 0a0fed82fb..a8bd5fd5e5 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -275,4 +275,10 @@ private: }; // end class LLPanel +// Build time optimization, generate once in .cpp file +#ifndef LLPANEL_CPP +extern template class LLPanel* LLView::getChild<class LLPanel>( + const std::string& name, BOOL recurse) const; +#endif + #endif diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index c8b6e814e1..62ca569e6c 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -72,12 +72,13 @@ LLProgressBar::~LLProgressBar() void LLProgressBar::draw() { static LLTimer timer; - - LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga"); + F32 alpha = getDrawContext().mAlpha; - mImageBar->draw(getLocalRect(), mColorBackground.get()); + LLColor4 image_bar_color = mColorBackground.get(); + image_bar_color.setAlpha(alpha); + mImageBar->draw(getLocalRect(), image_bar_color); - F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); + alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); LLColor4 bar_color = mColorBar.get(); bar_color.mV[VALPHA] *= alpha; // modulate alpha LLRect progress_rect = getLocalRect(); diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index a7cf9be277..0c46edf300 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -144,9 +144,10 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView ) { // undock floater when user resize it - if (((LLFloater*)getParent())->isDocked()) + LLFloater* parent = dynamic_cast<LLFloater*>( getParent()); + if (parent && parent->isDocked()) { - ((LLFloater*)getParent())->setDocked(false, false); + parent->setDocked( false, false); } // Resize the parent diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 5e17372fe9..53c5a8d07d 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -584,8 +584,9 @@ LLRect LLScrollContainer::getVisibleContentRect() return visible_rect; } -LLRect LLScrollContainer::getContentWindowRect() const +LLRect LLScrollContainer::getContentWindowRect() { + updateScroll(); LLRect scroller_view_rect; S32 visible_width = 0; S32 visible_height = 0; @@ -625,7 +626,7 @@ void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLRect& const rect_to_constrain.mTop - constraint.mTop); // translate from allowable region for lower left corner to upper left corner - allowable_scroll_rect.translate(0, content_window_rect.getHeight()); + allowable_scroll_rect.translate(0, content_window_rect.getHeight() - 1); S32 vert_pos = llclamp(mScrollbar[VERTICAL]->getDocPos(), mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mTop, // min vertical scroll diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index ac8ffe5258..25dcd071ab 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -96,7 +96,7 @@ public: void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; } LLRect getVisibleContentRect(); - LLRect getContentWindowRect() const; + LLRect getContentWindowRect(); const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } void pageUp(S32 overlap = 0); void pageDown(S32 overlap = 0); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7bf10d774c..db16670f79 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -156,6 +156,7 @@ LLTextBase::Params::Params() read_only("read_only", false), v_pad("v_pad", 0), h_pad("h_pad", 0), + clip_partial("clip_partial", true), line_spacing("line_spacing"), max_text_length("max_length", 255), font_shadow("font_shadow"), @@ -193,6 +194,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mHAlign(p.font_halign), mLineSpacingMult(p.line_spacing.multiple), mLineSpacingPixels(p.line_spacing.pixels), + mClipPartial(p.clip_partial), mTrackEnd( p.track_end ), mScrollIndex(-1), mSelectionStart( 0 ), @@ -379,10 +381,10 @@ void LLTextBase::drawSelectionBackground() // Draw the selection box (we're using a box instead of reversing the colors on the selected text). gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - const LLColor4& color = mReadOnly ? mReadOnlyBgColor.get() : mWriteableBgColor.get(); + const LLColor4& color = mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get(); F32 alpha = hasFocus() ? 0.7f : 0.3f; alpha *= getDrawContext().mAlpha; - gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha ); + LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha); for (std::vector<LLRect>::iterator rect_it = selection_rects.begin(); rect_it != selection_rects.end(); @@ -390,7 +392,7 @@ void LLTextBase::drawSelectionBackground() { LLRect selection_rect = *rect_it; selection_rect.translate(mTextRect.mLeft - content_display_rect.mLeft, mTextRect.mBottom - content_display_rect.mBottom); - gl_rect_2d(selection_rect); + gl_rect_2d(selection_rect, selection_color); } } } @@ -504,7 +506,7 @@ void LLTextBase::drawText() } LLRect scrolled_view_rect = getVisibleDocumentRect(); - std::pair<S32, S32> line_range = getVisibleLines(); + std::pair<S32, S32> line_range = getVisibleLines(mClipPartial); S32 first_line = line_range.first; S32 last_line = line_range.second; if (first_line >= last_line) @@ -524,6 +526,7 @@ void LLTextBase::drawText() for (S32 cur_line = first_line; cur_line < last_line; cur_line++) { + S32 next_line = cur_line + 1; line_info& line = mLineInfoList[cur_line]; if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mTextRect.mBottom) @@ -534,15 +537,15 @@ void LLTextBase::drawText() S32 next_start = -1; S32 line_end = text_len; - if ((cur_line + 1) < getLineCount()) + if (next_line < getLineCount()) { - next_start = getLineStart(cur_line + 1); + next_start = getLineStart(next_line); line_end = next_start; } LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft, line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom, - mDocumentView->getRect().getWidth() - scrolled_view_rect.mLeft, + llmin(mDocumentView->getRect().getWidth(), line.mRect.mRight) - scrolled_view_rect.mLeft, line.mRect.mBottom - scrolled_view_rect.mBottom + mTextRect.mBottom); // draw a single line of text @@ -562,6 +565,17 @@ void LLTextBase::drawText() } S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart(); + + if (mUseEllipses + && clipped_end == line_end + && next_line == last_line + && last_line < (S32)mLineInfoList.size()) + { + // more text to go, but we can't fit it + // so attempt to draw one extra character to force ellipses + clipped_end++; + } + text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect)); seg_start = clipped_end + cur_segment->getStart(); @@ -641,8 +655,6 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s if ( truncate() ) { - // The user's not getting everything he's hoping for - make_ui_sound("UISndBadKeystroke"); insert_len = getLength() - old_len; } @@ -1070,6 +1082,8 @@ void LLTextBase::reflow(S32 start_index) LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos); bool follow_selection = mTextRect.overlaps(old_cursor_rect); // cursor is visible + old_cursor_rect.translate(-mTextRect.mLeft, -mTextRect.mBottom); + S32 first_line = getFirstVisibleLine(); // if scroll anchor not on first line, update it to first character of first line @@ -1080,6 +1094,8 @@ void LLTextBase::reflow(S32 start_index) mScrollIndex = mLineInfoList[first_line].mDocIndexStart; } LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex); + // subtract off effect of horizontal scrollbar from local position of first char + first_char_rect.translate(-mTextRect.mLeft, -mTextRect.mBottom); S32 cur_top = 0; @@ -1178,6 +1194,10 @@ void LLTextBase::reflow(S32 start_index) ++seg_iter; seg_offset = 0; } + if (force_newline) + { + line_count++; + } } // calculate visible region for diplaying text @@ -1195,7 +1215,6 @@ void LLTextBase::reflow(S32 start_index) // apply scroll constraints after reflowing text if (!hasMouseCapture() && mScroller) { - LLRect visible_content_rect = getVisibleDocumentRect(); if (scrolled_to_bottom && mTrackEnd) { // keep bottom of text buffer visible @@ -1204,18 +1223,14 @@ void LLTextBase::reflow(S32 start_index) else if (hasSelection() && follow_selection) { // keep cursor in same vertical position on screen when selecting text - LLRect new_cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos); - new_cursor_rect_doc.translate(visible_content_rect.mLeft, visible_content_rect.mBottom); + LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos); mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect); - //llassert_always(getLocalRectFromDocIndex(mCursorPos).mBottom == old_cursor_rect.mBottom); } else { // keep first line of text visible - LLRect new_first_char_rect = getLocalRectFromDocIndex(mScrollIndex); - new_first_char_rect.translate(visible_content_rect.mLeft, visible_content_rect.mBottom); + LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex); mScroller->scrollToShowRect(new_first_char_rect, first_char_rect); - //llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom); } } @@ -1464,14 +1479,16 @@ void LLTextBase::setText(const LLStringExplicit &utf8str ,const LLStyle::Params& clearSegments(); // createDefaultSegment(); - startOfDoc(); deselect(); // append the new text (supports Url linking) std::string text(utf8str); LLStringUtil::removeCRLF(text); + // appendText modifies mCursorPos... appendText(text, false, input_params); + // ...so move cursor to top after appending text + startOfDoc(); onValueChange(0, getLength()); } @@ -2065,22 +2082,22 @@ void LLTextBase::updateRects() mContentsRect.unionWith(line_iter->mRect); } - S32 delta_pos_x = -mContentsRect.mLeft; mContentsRect.mTop += mVPad; S32 delta_pos = -mContentsRect.mBottom; // move line segments to fit new document rect for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it) { - it->mRect.translate(delta_pos_x, delta_pos); + it->mRect.translate(0, delta_pos); } - mContentsRect.translate(delta_pos_x, delta_pos); + mContentsRect.translate(0, delta_pos); } // update document container dimensions according to text contents LLRect doc_rect = mContentsRect; // use old mTextRect constraint document to width of viewable region - doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth(); + doc_rect.mLeft = 0; + doc_rect.mRight = mTextRect.getWidth(); mDocumentView->setShape(doc_rect); @@ -2281,7 +2298,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, - length, rect.mRight, + length, rect.getWidth(), &right_x, mEditor.getUseEllipses()); } @@ -2298,7 +2315,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele LLFontGL::LEFT, LLFontGL::TOP, 0, mStyle->getShadowType(), - length, rect.mRight, + length, rect.getWidth(), &right_x, mEditor.getUseEllipses()); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index c376a73615..c60b040655 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -84,11 +84,13 @@ public: wrap, use_ellipses, allow_html, - parse_highlights; + parse_highlights, + clip_partial; Optional<S32> v_pad, h_pad; + Optional<LineSpacingParams> line_spacing; @@ -347,6 +349,7 @@ protected: bool mTrackEnd; // if true, keeps scroll position at end of document during resize bool mReadOnly; bool mBGVisible; // render background? + bool mClipPartial; // false if we show lines that are partially inside bounding rect S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes // support widgets diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 4c4123cf45..0bd0ab59fb 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -31,7 +31,10 @@ */ #include "linden_common.h" + +#define LLTEXTBOX_CPP #include "lltextbox.h" + #include "lluictrlfactory.h" #include "llfocusmgr.h" #include "llwindow.h" @@ -40,6 +43,10 @@ static LLDefaultChildRegistry::Register<LLTextBox> r("text"); +// Compiler optimization, generate extern template +template class LLTextBox* LLView::getChild<class LLTextBox>( + const std::string& name, BOOL recurse) const; + LLTextBox::LLTextBox(const LLTextBox::Params& p) : LLTextBase(p), mClickedCallback(NULL) diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 01b4bfa5ed..3a045534d3 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -79,4 +79,10 @@ protected: callback_t mClickedCallback; }; +// Build time optimization, generate once in .cpp file +#ifndef LLTEXTBOX_CPP +extern template class LLTextBox* LLView::getChild<class LLTextBox>( + const std::string& name, BOOL recurse) const; +#endif + #endif diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3f4ef24f82..e68affc36c 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1,6 +1,5 @@ /** * @file lltexteditor.cpp - * @brief LLTextEditor base class * * $LicenseInfo:firstyear=2001&license=viewergpl$ * @@ -34,6 +33,7 @@ #include "linden_common.h" +#define LLTEXTEDITOR_CPP #include "lltexteditor.h" #include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR @@ -73,6 +73,10 @@ // static LLDefaultChildRegistry::Register<LLTextEditor> r("simple_text_editor"); +// Compiler optimization, generate extern template +template class LLTextEditor* LLView::getChild<class LLTextEditor>( + const std::string& name, BOOL recurse) const; + // // Constants // @@ -2158,7 +2162,7 @@ void LLTextEditor::drawLineNumbers() return; } - S32 cursor_line = getLineNumFromDocIndex(mCursorPos); + S32 cursor_line = mLineInfoList[getLineNumFromDocIndex(mCursorPos)].mLineNum; if (mShowLineNumbers) { diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index fb014b86bf..043dda8fa6 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -334,5 +334,10 @@ private: LLContextMenu* mContextMenu; }; // end class LLTextEditor +// Build time optimization, generate once in .cpp file +#ifndef LLTEXTEDITOR_CPP +extern template class LLTextEditor* LLView::getChild<class LLTextEditor>( + const std::string& name, BOOL recurse) const; +#endif #endif // LL_TEXTEDITOR_ diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 959313a5b6..01c7a81309 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -228,7 +228,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) { LLButton::Params p_button; p_button.name(std::string("play_media")); - p_button.label(""); // provid label but set to empty so name does not overwrite it -angela + p_button.label(""); // provide label but set to empty so name does not overwrite it -angela TOOLTIP_PLAYBUTTON_SIZE = 16; LLRect button_rect; button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); @@ -300,9 +300,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) mTextBox->setText(p.message()); } - LLRect text_contents_rect = mTextBox->getContentsRect(); - S32 text_width = llmin(p.max_width(), text_contents_rect.getWidth()); - S32 text_height = text_contents_rect.getHeight(); + S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth()); + S32 text_height = mTextBox->getTextPixelHeight(); mTextBox->reshape(text_width, text_height); // reshape tooltip panel to fit text box diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index a30d5b4651..706712ec5e 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -31,15 +31,43 @@ * $/LicenseInfo$ */ -//#include "llviewerprecompiledheaders.h" #include "linden_common.h" + +#define LLUICTRL_CPP #include "lluictrl.h" + #include "llfocusmgr.h" #include "llpanel.h" #include "lluictrlfactory.h" static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl"); +// Compiler optimization, generate extern template +template class LLUICtrl* LLView::getChild<class LLUICtrl>( + const std::string& name, BOOL recurse) const; + +LLUICtrl::CallbackParam::CallbackParam() +: name("name"), + function_name("function"), + parameter("parameter"), + control_name("control") // Shortcut to control -> "control_name" for backwards compatability +{ + addSynonym(parameter, "userdata"); +} + +LLUICtrl::EnableControls::EnableControls() +: enabled("enabled_control"), + disabled("disabled_control") +{} + +LLUICtrl::ControlVisibility::ControlVisibility() +: visible("visibility_control"), + invisible("invisibility_control") +{ + addSynonym(visible, "visiblity_control"); + addSynonym(invisible, "invisiblity_control"); +} + LLUICtrl::Params::Params() : tab_stop("tab_stop", true), chrome("chrome", false), diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index aef1bcd519..b20ff5d798 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -75,14 +75,7 @@ public: Optional<std::string> control_name; - CallbackParam() - : name("name"), - function_name("function"), - parameter("parameter"), - control_name("control") // Shortcut to control -> "control_name" for backwards compatability - { - addSynonym(parameter, "userdata"); - } + CallbackParam(); }; struct CommitCallbackParam : public LLInitParam::Block<CommitCallbackParam, CallbackParam > @@ -105,23 +98,14 @@ public: Alternative<std::string> enabled; Alternative<std::string> disabled; - EnableControls() - : enabled("enabled_control"), - disabled("disabled_control") - {} + EnableControls(); }; struct ControlVisibility : public LLInitParam::Choice<ControlVisibility> { Alternative<std::string> visible; Alternative<std::string> invisible; - ControlVisibility() - : visible("visibility_control"), - invisible("invisibility_control") - { - addSynonym(visible, "visiblity_control"); - addSynonym(invisible, "invisiblity_control"); - } + ControlVisibility(); }; struct Params : public LLInitParam::Block<Params, LLView::Params> { @@ -328,4 +312,10 @@ private: class DefaultTabGroupFirstSorter; }; +// Build time optimization, generate once in .cpp file +#ifndef LLUICTRL_CPP +extern template class LLUICtrl* LLView::getChild<class LLUICtrl>( + const std::string& name, BOOL recurse) const; +#endif + #endif // LL_LLUICTRL_H diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 1c1450d7e9..3643bf44f7 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -32,6 +32,7 @@ #include "linden_common.h" +#define LLUICTRLFACTORY_CPP #include "lluictrlfactory.h" #include "llxmlnode.h" @@ -75,6 +76,9 @@ public: static LLDefaultChildRegistry::Register<LLUICtrlLocate> r1("locate"); +// Build time optimization, generate this once in .cpp file +template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance(); + //----------------------------------------------------------------------------- // LLUICtrlFactory() //----------------------------------------------------------------------------- diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 8a9c9e23c1..55d7d745eb 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -108,6 +108,11 @@ extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP; extern LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION; extern LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS; +// Build time optimization, generate this once in .cpp file +#ifndef LLUICTRLFACTORY_CPP +extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance(); +#endif + class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory> { private: diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index dba24ee165..23e4131e6d 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -33,6 +33,7 @@ #include "linden_common.h" +#define LLVIEW_CPP #include "llview.h" #include <cassert> @@ -76,8 +77,17 @@ std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack; BOOL LLView::sIsDrawing = FALSE; #endif +// Compiler optimization, generate extern template +template class LLView* LLView::getChild<class LLView>( + const std::string& name, BOOL recurse) const; + static LLDefaultChildRegistry::Register<LLView> r("view"); +LLView::Follows::Follows() +: string(""), + flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP) +{} + LLView::Params::Params() : name("name", std::string("unnamed")), enabled("enabled", true), diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 2607120e17..d485244a05 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -111,10 +111,7 @@ public: Alternative<std::string> string; Alternative<U32> flags; - Follows() - : string(""), - flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP) - {} + Follows(); }; struct Params : public LLInitParam::Block<Params> @@ -659,4 +656,11 @@ template <class T> T* LLView::getChild(const std::string& name, BOOL recurse) co return result; } +// Compiler optimization - don't generate these specializations inline, +// require explicit specialization. See llbutton.cpp for an example. +#ifndef LLVIEW_CPP +extern template class LLView* LLView::getChild<class LLView>( + const std::string& name, BOOL recurse) const; +#endif + #endif //LL_LLVIEW_H |