aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llui/llview.cpp')
-rw-r--r--linden/indra/llui/llview.cpp215
1 files changed, 145 insertions, 70 deletions
diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp
index e5415f8..c9828dd 100644
--- a/linden/indra/llui/llview.cpp
+++ b/linden/indra/llui/llview.cpp
@@ -49,7 +49,16 @@
49#include "lluictrl.h" 49#include "lluictrl.h"
50#include "llwindow.h" 50#include "llwindow.h"
51#include "v3color.h" 51#include "v3color.h"
52#include "lluictrlfactory.h"
52 53
54// for ui edit hack
55#include "llbutton.h"
56#include "lllineeditor.h"
57#include "lltexteditor.h"
58#include "lltextbox.h"
59
60//HACK: this allows you to instantiate LLView from xml with "<view/>" which we don't want
61static LLRegisterWidget<LLView> r("view");
53 62
54BOOL LLView::sDebugRects = FALSE; 63BOOL LLView::sDebugRects = FALSE;
55BOOL LLView::sDebugKeys = FALSE; 64BOOL LLView::sDebugKeys = FALSE;
@@ -153,6 +162,8 @@ LLView::~LLView()
153 162
154 std::for_each(mFloaterControls.begin(), mFloaterControls.end(), 163 std::for_each(mFloaterControls.begin(), mFloaterControls.end(),
155 DeletePairedPointer()); 164 DeletePairedPointer());
165 std::for_each(mDummyWidgets.begin(), mDummyWidgets.end(),
166 DeletePairedPointer());
156} 167}
157 168
158// virtual 169// virtual
@@ -716,7 +727,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_scre
716 tool_tip = getShowNamesToolTip(); 727 tool_tip = getShowNamesToolTip();
717 } 728 }
718 729
719 BOOL showNamesTextBox = LLUI::sShowXUINames && (getWidgetType() == WIDGET_TYPE_TEXT_BOX); 730 BOOL showNamesTextBox = LLUI::sShowXUINames && dynamic_cast<LLTextBox*>(this) != NULL;
720 731
721 if( !handled && (blockMouseEvent(x, y) || showNamesTextBox) && !tool_tip.empty()) 732 if( !handled && (blockMouseEvent(x, y) || showNamesTextBox) && !tool_tip.empty())
722 { 733 {
@@ -741,23 +752,21 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
741{ 752{
742 BOOL handled = FALSE; 753 BOOL handled = FALSE;
743 754
744 if( called_from_parent ) 755 if (getVisible() && getEnabled())
745 { 756 {
746 // Downward traversal 757 if( called_from_parent )
747 if (getVisible() && getEnabled())
748 { 758 {
759 // Downward traversal
749 handled = childrenHandleKey( key, mask ) != NULL; 760 handled = childrenHandleKey( key, mask ) != NULL;
750 } 761 }
751 }
752 762
753 // JC: Must pass to disabled views, since they could have 763 if (!handled)
754 // keyboard focus, which requires the escape key to exit.
755 if (!handled && getVisible())
756 {
757 handled = handleKeyHere( key, mask, called_from_parent );
758 if (handled && LLView::sDebugKeys)
759 { 764 {
760 llinfos << "Key handled by " << getName() << llendl; 765 handled = handleKeyHere( key, mask );
766 if (handled && LLView::sDebugKeys)
767 {
768 llinfos << "Key handled by " << getName() << llendl;
769 }
761 } 770 }
762 } 771 }
763 772
@@ -771,7 +780,7 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
771 780
772// Called from handleKey() 781// Called from handleKey()
773// Handles key in this object. Checking parents and children happens in handleKey() 782// Handles key in this object. Checking parents and children happens in handleKey()
774BOOL LLView::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) 783BOOL LLView::handleKeyHere(KEY key, MASK mask)
775{ 784{
776 return FALSE; 785 return FALSE;
777} 786}
@@ -780,25 +789,24 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
780{ 789{
781 BOOL handled = FALSE; 790 BOOL handled = FALSE;
782 791
783 if( called_from_parent ) 792 if (getVisible() && getEnabled())
784 { 793 {
785 // Downward traversal 794 if( called_from_parent )
786 if (getVisible() && getEnabled())
787 { 795 {
796 // Downward traversal
788 handled = childrenHandleUnicodeChar( uni_char ) != NULL; 797 handled = childrenHandleUnicodeChar( uni_char ) != NULL;
789 } 798 }
790 }
791 799
792 if (!handled && getVisible()) 800 if (!handled)
793 {
794 handled = handleUnicodeCharHere(uni_char, called_from_parent);
795 if (handled && LLView::sDebugKeys)
796 { 801 {
797 llinfos << "Unicode key handled by " << getName() << llendl; 802 handled = handleUnicodeCharHere(uni_char);
803 if (handled && LLView::sDebugKeys)
804 {
805 llinfos << "Unicode key handled by " << getName() << llendl;
806 }
798 } 807 }
799 } 808 }
800 809
801
802 if (!handled && !called_from_parent && mParentView) 810 if (!handled && !called_from_parent && mParentView)
803 { 811 {
804 // Upward traversal 812 // Upward traversal
@@ -809,7 +817,7 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
809} 817}
810 818
811 819
812BOOL LLView::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent ) 820BOOL LLView::handleUnicodeCharHere(llwchar uni_char )
813{ 821{
814 return FALSE; 822 return FALSE;
815} 823}
@@ -903,11 +911,14 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
903 if (sEditingUI && handled_view) 911 if (sEditingUI && handled_view)
904 { 912 {
905 // need to find leaf views, big hack 913 // need to find leaf views, big hack
906 EWidgetType type = handled_view->getWidgetType(); 914 LLButton* buttonp = dynamic_cast<LLButton*>(handled_view);
907 if (type == WIDGET_TYPE_BUTTON 915 LLLineEditor* line_editorp = dynamic_cast<LLLineEditor*>(handled_view);
908 || type == WIDGET_TYPE_LINE_EDITOR 916 LLTextEditor* text_editorp = dynamic_cast<LLTextEditor*>(handled_view);
909 || type == WIDGET_TYPE_TEXT_EDITOR 917 LLTextBox* text_boxp = dynamic_cast<LLTextBox*>(handled_view);
910 || type == WIDGET_TYPE_TEXT_BOX) 918 if (buttonp
919 || line_editorp
920 || text_editorp
921 || text_boxp)
911 { 922 {
912 sEditingUIView = handled_view; 923 sEditingUIView = handled_view;
913 } 924 }
@@ -971,8 +982,10 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
971 LLView* viewp = *child_it; 982 LLView* viewp = *child_it;
972 S32 local_x = x - viewp->getRect().mLeft; 983 S32 local_x = x - viewp->getRect().mLeft;
973 S32 local_y = y - viewp->getRect().mBottom; 984 S32 local_y = y - viewp->getRect().mBottom;
974 if (viewp->pointInView(local_x, local_y) && 985 if (viewp->pointInView(local_x, local_y)
975 viewp->handleScrollWheel( local_x, local_y, clicks )) 986 && viewp->getVisible()
987 && viewp->getEnabled()
988 && viewp->handleScrollWheel( local_x, local_y, clicks ))
976 { 989 {
977 if (sDebugMouseHandling) 990 if (sDebugMouseHandling)
978 { 991 {
@@ -1528,7 +1541,7 @@ BOOL LLView::hasAncestor(const LLView* parentp) const
1528 1541
1529BOOL LLView::childHasKeyboardFocus( const LLString& childname ) const 1542BOOL LLView::childHasKeyboardFocus( const LLString& childname ) const
1530{ 1543{
1531 LLView *child = getChildByName(childname); 1544 LLView *child = getChildView(childname, TRUE, FALSE);
1532 if (child) 1545 if (child)
1533 { 1546 {
1534 return gFocusMgr.childHasKeyboardFocus(child); 1547 return gFocusMgr.childHasKeyboardFocus(child);
@@ -1543,16 +1556,17 @@ BOOL LLView::childHasKeyboardFocus( const LLString& childname ) const
1543 1556
1544BOOL LLView::hasChild(const LLString& childname, BOOL recurse) const 1557BOOL LLView::hasChild(const LLString& childname, BOOL recurse) const
1545{ 1558{
1546 return getChildByName(childname, recurse) != NULL; 1559 return getChildView(childname, recurse, FALSE) != NULL;
1547} 1560}
1548 1561
1549//----------------------------------------------------------------------------- 1562//-----------------------------------------------------------------------------
1550// getChildByName() 1563// getChildView()
1551//----------------------------------------------------------------------------- 1564//-----------------------------------------------------------------------------
1552LLView* LLView::getChildByName(const LLString& name, BOOL recurse) const 1565LLView* LLView::getChildView(const LLString& name, BOOL recurse, BOOL create_if_missing) const
1553{ 1566{
1554 if(name.empty()) 1567 //richard: should we allow empty names?
1555 return NULL; 1568 //if(name.empty())
1569 // return NULL;
1556 child_list_const_iter_t child_it; 1570 child_list_const_iter_t child_it;
1557 // Look for direct children *first* 1571 // Look for direct children *first*
1558 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) 1572 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
@@ -1569,13 +1583,18 @@ LLView* LLView::getChildByName(const LLString& name, BOOL recurse) const
1569 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) 1583 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
1570 { 1584 {
1571 LLView* childp = *child_it; 1585 LLView* childp = *child_it;
1572 LLView* viewp = childp->getChildByName(name, recurse); 1586 LLView* viewp = childp->getChildView(name, recurse, FALSE);
1573 if ( viewp ) 1587 if ( viewp )
1574 { 1588 {
1575 return viewp; 1589 return viewp;
1576 } 1590 }
1577 } 1591 }
1578 } 1592 }
1593
1594 if (create_if_missing)
1595 {
1596 return createDummyWidget<LLView>(name);
1597 }
1579 return NULL; 1598 return NULL;
1580} 1599}
1581 1600
@@ -1692,7 +1711,6 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
1692 if( getRect().mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) 1711 if( getRect().mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
1693 { 1712 {
1694 delta_x = constraint.mRight - (getRect().mLeft + KEEP_ONSCREEN_PIXELS); 1713 delta_x = constraint.mRight - (getRect().mLeft + KEEP_ONSCREEN_PIXELS);
1695 delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() );
1696 } 1714 }
1697 1715
1698 if( getRect().mTop > constraint.mTop ) 1716 if( getRect().mTop > constraint.mTop )
@@ -1703,7 +1721,6 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
1703 if( getRect().mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) 1721 if( getRect().mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
1704 { 1722 {
1705 delta_y = constraint.mBottom - (getRect().mTop - KEEP_ONSCREEN_PIXELS); 1723 delta_y = constraint.mBottom - (getRect().mTop - KEEP_ONSCREEN_PIXELS);
1706 delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() );
1707 } 1724 }
1708 } 1725 }
1709 else 1726 else
@@ -1716,6 +1733,7 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
1716 if( getRect().mRight > constraint.mRight ) 1733 if( getRect().mRight > constraint.mRight )
1717 { 1734 {
1718 delta_x = constraint.mRight - getRect().mRight; 1735 delta_x = constraint.mRight - getRect().mRight;
1736 // compensate for left edge possible going off screen
1719 delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() ); 1737 delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() );
1720 } 1738 }
1721 1739
@@ -1727,6 +1745,7 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
1727 if( getRect().mBottom < constraint.mBottom ) 1745 if( getRect().mBottom < constraint.mBottom )
1728 { 1746 {
1729 delta_y = constraint.mBottom - getRect().mBottom; 1747 delta_y = constraint.mBottom - getRect().mBottom;
1748 // compensate for top edge possible going off screen
1730 delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() ); 1749 delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() );
1731 } 1750 }
1732 } 1751 }
@@ -1832,9 +1851,8 @@ BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* o
1832// virtual 1851// virtual
1833LLXMLNodePtr LLView::getXML(bool save_children) const 1852LLXMLNodePtr LLView::getXML(bool save_children) const
1834{ 1853{
1835 const LLString& type_name = getWidgetTag(); 1854 //FIXME: need to provide actual derived type tag, probably outside this method
1836 1855 LLXMLNodePtr node = new LLXMLNode("view", FALSE);
1837 LLXMLNodePtr node = new LLXMLNode(type_name, FALSE);
1838 1856
1839 node->createChild("name", TRUE)->setStringValue(getName()); 1857 node->createChild("name", TRUE)->setStringValue(getName());
1840 node->createChild("width", TRUE)->setIntValue(getRect().getWidth()); 1858 node->createChild("width", TRUE)->setIntValue(getRect().getWidth());
@@ -1897,6 +1915,14 @@ LLXMLNodePtr LLView::getXML(bool save_children) const
1897 return node; 1915 return node;
1898} 1916}
1899 1917
1918//static
1919LLView* LLView::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
1920{
1921 LLView* viewp = new LLView();
1922 viewp->initFromXML(node, parent);
1923 return viewp;
1924}
1925
1900// static 1926// static
1901void LLView::addColorXML(LLXMLNodePtr node, const LLColor4& color, 1927void LLView::addColorXML(LLXMLNodePtr node, const LLColor4& color,
1902 const LLString& xml_name, const LLString& control_name) 1928 const LLString& xml_name, const LLString& control_name)
@@ -2426,16 +2452,7 @@ LLSimpleListener* LLView::getListenerByName(const LLString& callback_name)
2426 return callback; 2452 return callback;
2427} 2453}
2428 2454
2429void LLView::addListenerToControl(LLEventDispatcher *dispatcher, const LLString& name, LLSD filter, LLSD userdata) 2455LLControlVariable *LLView::findControl(LLString name)
2430{
2431 LLSimpleListener* listener = getListenerByName(name);
2432 if (listener)
2433 {
2434 dispatcher->addListener(listener, filter, userdata);
2435 }
2436}
2437
2438LLControlBase *LLView::findControl(LLString name)
2439{ 2456{
2440 control_map_t::iterator itor = mFloaterControls.find(name); 2457 control_map_t::iterator itor = mFloaterControls.find(name);
2441 if (itor != mFloaterControls.end()) 2458 if (itor != mFloaterControls.end())
@@ -2791,9 +2808,15 @@ LLFontGL::StyleFlags LLView::selectFontStyle(LLXMLNodePtr node)
2791 return gl_font_style; 2808 return gl_font_style;
2792} 2809}
2793 2810
2794void LLView::setControlValue(const LLSD& value) 2811bool LLView::setControlValue(const LLSD& value)
2795{ 2812{
2796 LLUI::sConfigGroup->setValue(getControlName(), value); 2813 LLString ctrlname = getControlName();
2814 if (!ctrlname.empty())
2815 {
2816 LLUI::sConfigGroup->setValue(ctrlname, value);
2817 return true;
2818 }
2819 return false;
2797} 2820}
2798 2821
2799//virtual 2822//virtual
@@ -2804,43 +2827,57 @@ void LLView::setControlName(const LLString& control_name, LLView *context)
2804 context = this; 2827 context = this;
2805 } 2828 }
2806 2829
2807 // Unregister from existing listeners
2808 if (!mControlName.empty()) 2830 if (!mControlName.empty())
2809 { 2831 {
2810 clearDispatchers(); 2832 llwarns << "setControlName called twice on same control!" << llendl;
2833 mControlConnection.disconnect(); // disconnect current signal
2834 mControlName.clear();
2811 } 2835 }
2812 2836
2813 // Register new listener 2837 // Register new listener
2814 if (!control_name.empty()) 2838 if (!control_name.empty())
2815 { 2839 {
2816 LLControlBase *control = context->findControl(control_name); 2840 LLControlVariable *control = context->findControl(control_name);
2817 if (control) 2841 if (control)
2818 { 2842 {
2819 mControlName = control_name; 2843 mControlName = control_name;
2820 LLSD state = control->registerListener(this, "DEFAULT"); 2844 mControlConnection = control->getSignal()->connect(boost::bind(&controlListener, _1, getHandle(), std::string("value")));
2821 setValue(state); 2845 setValue(control->getValue());
2822 } 2846 }
2823 } 2847 }
2824} 2848}
2825 2849
2826// virtual 2850// static
2827bool LLView::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) 2851bool LLView::controlListener(const LLSD& newvalue, LLHandle<LLView> handle, std::string type)
2828{ 2852{
2829 if (userdata.asString() == "DEFAULT" && event->desc() == "value_changed") 2853 LLView* view = handle.get();
2854 if (view)
2830 { 2855 {
2831 LLSD state = event->getValue(); 2856 if (type == "value")
2832 setValue(state); 2857 {
2833 return TRUE; 2858 view->setValue(newvalue);
2859 return true;
2860 }
2861 else if (type == "enabled")
2862 {
2863 view->setEnabled(newvalue.asBoolean());
2864 return true;
2865 }
2866 else if (type == "visible")
2867 {
2868 view->setVisible(newvalue.asBoolean());
2869 return true;
2870 }
2834 } 2871 }
2835 return FALSE; 2872 return false;
2836} 2873}
2837 2874
2838void LLView::addBoolControl(LLString name, bool initial_value) 2875void LLView::addBoolControl(LLString name, bool initial_value)
2839{ 2876{
2840 mFloaterControls[name] = new LLControl(name, TYPE_BOOLEAN, initial_value, "Internal floater control"); 2877 mFloaterControls[name] = new LLControlVariable(name, TYPE_BOOLEAN, initial_value, "Internal floater control");
2841} 2878}
2842 2879
2843LLControlBase *LLView::getControl(LLString name) 2880LLControlVariable *LLView::getControl(LLString name)
2844{ 2881{
2845 control_map_t::iterator itor = mFloaterControls.find(name); 2882 control_map_t::iterator itor = mFloaterControls.find(name);
2846 if (itor != mFloaterControls.end()) 2883 if (itor != mFloaterControls.end())
@@ -2860,3 +2897,41 @@ LLSD LLView::getValue() const
2860{ 2897{
2861 return LLSD(); 2898 return LLSD();
2862} 2899}
2900
2901LLView* LLView::createWidget(LLXMLNodePtr xml_node) const
2902{
2903 // forward requests to ui ctrl factory
2904 return LLUICtrlFactory::getInstance()->createCtrlWidget(NULL, xml_node);
2905}
2906
2907//
2908// LLWidgetClassRegistry
2909//
2910
2911LLWidgetClassRegistry::LLWidgetClassRegistry()
2912{
2913}
2914
2915void LLWidgetClassRegistry::registerCtrl(const LLString& tag, LLWidgetClassRegistry::factory_func_t function)
2916{
2917 LLString lower_case_tag = tag;
2918 LLString::toLower(lower_case_tag);
2919
2920 mCreatorFunctions[lower_case_tag] = function;
2921}
2922
2923BOOL LLWidgetClassRegistry::isTagRegistered(const LLString &tag)
2924{
2925 return mCreatorFunctions.find(tag) != mCreatorFunctions.end();
2926}
2927
2928LLWidgetClassRegistry::factory_func_t LLWidgetClassRegistry::getCreatorFunc(const LLString& ctrl_type)
2929{
2930 factory_map_t::const_iterator found_it = mCreatorFunctions.find(ctrl_type);
2931 if (found_it == mCreatorFunctions.end())
2932 {
2933 return NULL;
2934 }
2935 return found_it->second;
2936}
2937