00001
00032 #ifndef LL_LLVIEW_H
00033 #define LL_LLVIEW_H
00034
00035
00036
00037
00038
00039 #include "llcoord.h"
00040 #include "llfontgl.h"
00041 #include "llmortician.h"
00042 #include "llmousehandler.h"
00043 #include "llnametable.h"
00044 #include "llsd.h"
00045 #include "llstring.h"
00046 #include "llrect.h"
00047 #include "llui.h"
00048 #include "lluistring.h"
00049 #include "lluixmltags.h"
00050 #include "llviewquery.h"
00051 #include "llxmlnode.h"
00052 #include "stdenums.h"
00053 #include "lluistring.h"
00054
00055 const U32 FOLLOWS_NONE = 0x00;
00056 const U32 FOLLOWS_LEFT = 0x01;
00057 const U32 FOLLOWS_RIGHT = 0x02;
00058 const U32 FOLLOWS_TOP = 0x10;
00059 const U32 FOLLOWS_BOTTOM = 0x20;
00060 const U32 FOLLOWS_ALL = 0x33;
00061
00062 const BOOL MOUSE_OPAQUE = TRUE;
00063 const BOOL NOT_MOUSE_OPAQUE = FALSE;
00064
00065 const U32 GL_NAME_UI_RESERVED = 2;
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 class LLUICtrlFactory;
00150
00151
00152 class LLWidgetClassRegistry : public LLSingleton<LLWidgetClassRegistry>
00153 {
00154 friend class LLSingleton<LLWidgetClassRegistry>;
00155 public:
00156 typedef LLView* (*factory_func_t)(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
00157 typedef std::map<LLString, factory_func_t> factory_map_t;
00158
00159 void registerCtrl(const LLString& xml_tag, factory_func_t function);
00160 BOOL isTagRegistered(const LLString& xml_tag);
00161 factory_func_t getCreatorFunc(const LLString& xml_tag);
00162
00163
00164 template <class T> std::string getTag()
00165 {
00166 factory_map_t::iterator it;
00167 for(it = mCreatorFunctions.begin(); it != mCreatorFunctions.end(); ++it)
00168 {
00169 if (it->second == T::fromXML)
00170 {
00171 return it->first;
00172 }
00173 }
00174
00175 return "";
00176 }
00177
00178 private:
00179 LLWidgetClassRegistry();
00180 virtual ~LLWidgetClassRegistry() {};
00181
00182 typedef std::set<LLString> ctrl_name_set_t;
00183 ctrl_name_set_t mUICtrlNames;
00184
00185
00186 factory_map_t mCreatorFunctions;
00187 };
00188
00189 template<class T>
00190 class LLRegisterWidget
00191 {
00192 public:
00193 LLRegisterWidget(const std::string& tag)
00194 {
00195 LLWidgetClassRegistry* registry = LLWidgetClassRegistry::getInstance();
00196 if (registry->isTagRegistered(tag))
00197 {
00198
00199 llerrs << "Widget named " << tag << " already registered!" << llendl;
00200 }
00201 else
00202 {
00203 registry->registerCtrl(tag, T::fromXML);
00204 }
00205 }
00206 };
00207
00208 class LLView : public LLMouseHandler, public LLMortician
00209 {
00210
00211 public:
00212 #if LL_DEBUG
00213 static BOOL sIsDrawing;
00214 #endif
00215 enum ESoundFlags
00216 {
00217 SILENT = 0,
00218 MOUSE_DOWN = 1,
00219 MOUSE_UP = 2
00220 };
00221
00222 enum ESnapType
00223 {
00224 SNAP_PARENT,
00225 SNAP_SIBLINGS,
00226 SNAP_PARENT_AND_SIBLINGS
00227 };
00228
00229 enum ESnapEdge
00230 {
00231 SNAP_LEFT,
00232 SNAP_TOP,
00233 SNAP_RIGHT,
00234 SNAP_BOTTOM
00235 };
00236
00237 typedef std::list<LLView*> child_list_t;
00238 typedef child_list_t::iterator child_list_iter_t;
00239 typedef child_list_t::const_iterator child_list_const_iter_t;
00240 typedef child_list_t::reverse_iterator child_list_reverse_iter_t;
00241 typedef child_list_t::const_reverse_iterator child_list_const_reverse_iter_t;
00242
00243 typedef std::vector<class LLUICtrl *> ctrl_list_t;
00244
00245 typedef std::pair<S32, S32> tab_order_t;
00246 typedef std::pair<LLUICtrl *, tab_order_t> tab_order_pair_t;
00247
00248 typedef std::map<const LLUICtrl*, tab_order_t> child_tab_order_t;
00249 typedef child_tab_order_t::iterator child_tab_order_iter_t;
00250 typedef child_tab_order_t::const_iterator child_tab_order_const_iter_t;
00251 typedef child_tab_order_t::reverse_iterator child_tab_order_reverse_iter_t;
00252 typedef child_tab_order_t::const_reverse_iterator child_tab_order_const_reverse_iter_t;
00253
00254 LLView();
00255 LLView(const LLString& name, BOOL mouse_opaque);
00256 LLView(const LLString& name, const LLRect& rect, BOOL mouse_opaque, U32 follows=FOLLOWS_NONE);
00257
00258 virtual ~LLView();
00259
00260
00261 BOOL isView() const;
00262
00263
00264
00265
00266 virtual BOOL isCtrl() const;
00267
00268 virtual BOOL isPanel() const;
00269
00270
00271
00272
00273 void setMouseOpaque( BOOL b ) { mMouseOpaque = b; }
00274 BOOL getMouseOpaque() const { return mMouseOpaque; }
00275 void setToolTip( const LLStringExplicit& msg );
00276 BOOL setToolTipArg( const LLStringExplicit& key, const LLStringExplicit& text );
00277 void setToolTipArgs( const LLString::format_map_t& args );
00278
00279 virtual void setRect(const LLRect &rect);
00280 void setFollows(U32 flags) { mReshapeFlags = flags; }
00281
00282
00283 void setFollowsNone() { mReshapeFlags = FOLLOWS_NONE; }
00284 void setFollowsLeft() { mReshapeFlags |= FOLLOWS_LEFT; }
00285 void setFollowsTop() { mReshapeFlags |= FOLLOWS_TOP; }
00286 void setFollowsRight() { mReshapeFlags |= FOLLOWS_RIGHT; }
00287 void setFollowsBottom() { mReshapeFlags |= FOLLOWS_BOTTOM; }
00288 void setFollowsAll() { mReshapeFlags |= FOLLOWS_ALL; }
00289
00290 void setSoundFlags(U8 flags) { mSoundFlags = flags; }
00291 void setName(LLString name) { mName = name; }
00292 void setUseBoundingRect( BOOL use_bounding_rect );
00293 BOOL getUseBoundingRect();
00294
00295 const LLString& getToolTip() const { return mToolTipMsg.getString(); }
00296
00297 void sendChildToFront(LLView* child);
00298 void sendChildToBack(LLView* child);
00299 void moveChildToFrontOfTabGroup(LLUICtrl* child);
00300 void moveChildToBackOfTabGroup(LLUICtrl* child);
00301
00302 void addChild(LLView* view, S32 tab_group = 0);
00303 void addChildAtEnd(LLView* view, S32 tab_group = 0);
00304
00305 void removeChild(LLView* view, BOOL deleteIt = FALSE);
00306
00307 virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group);
00308 virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group);
00309 virtual void removeCtrl( LLUICtrl* ctrl);
00310
00311 child_tab_order_t getCtrlOrder() const { return mCtrlOrder; }
00312 ctrl_list_t getCtrlList() const;
00313 ctrl_list_t getCtrlListSorted() const;
00314
00315 void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; }
00316 S32 getDefaultTabGroup() const { return mDefaultTabGroup; }
00317
00318 BOOL isInVisibleChain() const;
00319 BOOL isInEnabledChain() const;
00320
00321 void setFocusRoot(BOOL b) { mIsFocusRoot = b; }
00322 BOOL isFocusRoot() const { return mIsFocusRoot; }
00323 virtual BOOL canFocusChildren() const;
00324
00325 BOOL focusNextRoot();
00326 BOOL focusPrevRoot();
00327
00328
00329
00330
00331 virtual void deleteAllChildren();
00332
00333 virtual void setTentative(BOOL b);
00334 virtual BOOL getTentative() const;
00335 void setAllChildrenEnabled(BOOL b);
00336
00337 virtual void setVisible(BOOL visible);
00338 BOOL getVisible() const { return mVisible; }
00339 virtual void setEnabled(BOOL enabled);
00340 BOOL getEnabled() const { return mEnabled; }
00341 U8 getSoundFlags() const { return mSoundFlags; }
00342
00343 virtual BOOL setLabelArg( const LLString& key, const LLStringExplicit& text );
00344
00345 virtual void onVisibilityChange ( BOOL curVisibilityIn );
00346
00347 void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); }
00348 void popVisible() { setVisible(mLastVisible); mLastVisible = TRUE; }
00349
00350 LLHandle<LLView> getHandle() { mHandle.bind(this); return mHandle; }
00351
00352 U32 getFollows() const { return mReshapeFlags; }
00353 BOOL followsLeft() const { return mReshapeFlags & FOLLOWS_LEFT; }
00354 BOOL followsRight() const { return mReshapeFlags & FOLLOWS_RIGHT; }
00355 BOOL followsTop() const { return mReshapeFlags & FOLLOWS_TOP; }
00356 BOOL followsBottom() const { return mReshapeFlags & FOLLOWS_BOTTOM; }
00357 BOOL followsAll() const { return mReshapeFlags & FOLLOWS_ALL; }
00358
00359 const LLRect& getRect() const { return mRect; }
00360 const LLRect& getBoundingRect() const { return mBoundingRect; }
00361 LLRect getLocalBoundingRect() const;
00362 LLRect getScreenRect() const;
00363 LLRect getLocalRect() const;
00364 virtual LLRect getSnapRect() const;
00365 LLRect getLocalSnapRect() const;
00366
00367
00368 virtual LLRect getRequiredRect();
00369 void updateBoundingRect();
00370
00371 LLView* getRootView();
00372 LLView* getParent() const { return mParentView; }
00373 LLView* getFirstChild() const { return (mChildList.empty()) ? NULL : *(mChildList.begin()); }
00374 S32 getChildCount() const { return (S32)mChildList.size(); }
00375 template<class _Pr3> void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); }
00376 BOOL hasAncestor(const LLView* parentp) const;
00377 BOOL hasChild(const LLString& childname, BOOL recurse = FALSE) const;
00378 BOOL childHasKeyboardFocus( const LLString& childname ) const;
00379
00380
00381
00382
00383
00384
00385
00386 virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
00387 virtual void translate( S32 x, S32 y );
00388 void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
00389 BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside );
00390 void centerWithin(const LLRect& bounds);
00391
00392 virtual void userSetShape(const LLRect& new_rect);
00393 virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0);
00394 virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0);
00395
00396 virtual BOOL canSnapTo(const LLView* other_view);
00397
00398 virtual void snappedTo(const LLView* snap_view);
00399
00400 virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
00401 virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
00402 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
00403 EDragAndDropType cargo_type,
00404 void* cargo_data,
00405 EAcceptance* accept,
00406 LLString& tooltip_msg);
00407
00408 LLString getShowNamesToolTip();
00409
00410 virtual void draw();
00411
00412 virtual LLXMLNodePtr getXML(bool save_children = true) const;
00413
00414 static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
00415 virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
00416 void parseFollowsFlags(LLXMLNodePtr node);
00417
00418
00419 BOOL getSaveToXML() const { return mSaveToXML; }
00420 void setSaveToXML(BOOL b) { mSaveToXML = b; }
00421
00422 virtual void onFocusLost();
00423 virtual void onFocusReceived();
00424
00425 typedef enum e_hit_test_type
00426 {
00427 HIT_TEST_USE_BOUNDING_RECT,
00428 HIT_TEST_IGNORE_BOUNDING_RECT
00429 }EHitTestType;
00430
00431 BOOL parentPointInView(S32 x, S32 y, EHitTestType type = HIT_TEST_USE_BOUNDING_RECT) const;
00432 BOOL pointInView(S32 x, S32 y, EHitTestType type = HIT_TEST_USE_BOUNDING_RECT) const;
00433 BOOL blockMouseEvent(S32 x, S32 y) const;
00434
00435
00436 BOOL localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view) const;
00437 BOOL localRectToOtherView( const LLRect& local, LLRect* other, LLView* other_view ) const;
00438 void screenRectToLocal( const LLRect& screen, LLRect* local ) const;
00439 void localRectToScreen( const LLRect& local, LLRect* screen ) const;
00440
00441
00442 LLSimpleListener* getListenerByName(const LLString &callback_name);
00443 void registerEventListener(LLString name, LLSimpleListener* function);
00444 void deregisterEventListener(LLString name);
00445 LLString findEventListener(LLSimpleListener *listener) const;
00446 void addListenerToControl(LLEventDispatcher *observer, const LLString& name, LLSD filter, LLSD userdata);
00447
00448 void addBoolControl(LLString name, bool initial_value);
00449 LLControlVariable *getControl(LLString name);
00450 LLControlVariable *findControl(LLString name);
00451
00452 bool setControlValue(const LLSD& value);
00453 virtual void setControlName(const LLString& control, LLView *context);
00454 virtual LLString getControlName() const { return mControlName; }
00455
00456 virtual void setValue(const LLSD& value);
00457 virtual LLSD getValue() const;
00458
00459 const child_list_t* getChildList() const { return &mChildList; }
00460
00461
00462
00463 BOOL handleHover(S32 x, S32 y, MASK mask);
00464 BOOL handleMouseUp(S32 x, S32 y, MASK mask);
00465 BOOL handleMouseDown(S32 x, S32 y, MASK mask);
00466 BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
00467 BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
00468 BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
00469 BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
00470 BOOL handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect);
00471 const LLString& getName() const;
00472 void onMouseCaptureLost();
00473 BOOL hasMouseCapture();
00474 BOOL isView();
00475 void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
00476 void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
00477
00478 template <class T> T* getChild(const LLString& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const
00479 {
00480 LLView* child = getChildView(name, recurse, FALSE);
00481 T* result = dynamic_cast<T*>(child);
00482 if (!result)
00483 {
00484
00485 if (child)
00486 {
00487 llwarns << "Found child named " << name << " but of wrong type" << llendl;
00488 }
00489 if (create_if_missing)
00490 {
00491
00492 result = createDummyWidget<T>(name);
00493 }
00494 }
00495 return result;
00496 }
00497
00498 virtual LLView* getChildView(const LLString& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
00499
00500 template <class T> T* createDummyWidget(const LLString& name) const
00501 {
00502 T* widget = getDummyWidget<T>(name);
00503 if (!widget)
00504 {
00505
00506 LLString xml_tag = LLWidgetClassRegistry::getInstance()->getTag<T>();
00507 if (xml_tag.empty())
00508 {
00509 llwarns << "No xml tag registered for this class " << llendl;
00510 return NULL;
00511 }
00512
00513 LLXMLNodePtr new_node_ptr = new LLXMLNode(xml_tag, FALSE);
00514 new_node_ptr->createChild("name", TRUE)->setStringValue(name);
00515
00516 widget = dynamic_cast<T*>(createWidget(new_node_ptr));
00517 if (widget)
00518 {
00519
00520 llwarns << "Making dummy " << xml_tag << " named " << name << " in " << getName() << llendl;
00521 const_cast<LLView*>(this)->mDummyWidgets.insert(std::make_pair(name, widget));
00522 }
00523 else
00524 {
00525
00526 llwarns << "Failed to create dummy widget of requested type " << llendl;
00527 return NULL;
00528 }
00529 }
00530 return widget;
00531 }
00532
00533 template <class T> T* getDummyWidget(const LLString& name) const
00534 {
00535 dummy_widget_map_t::const_iterator found_it = mDummyWidgets.find(name);
00536 if (found_it == mDummyWidgets.end())
00537 {
00538 return NULL;
00539 }
00540 return dynamic_cast<T*>(found_it->second);
00541 }
00542
00543 LLView* createWidget(LLXMLNodePtr xml_node) const;
00544
00545
00546
00547 static U32 createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect = LLRect());
00548
00549 static LLFontGL* selectFont(LLXMLNodePtr node);
00550 static LLFontGL::HAlign selectFontHAlign(LLXMLNodePtr node);
00551 static LLFontGL::VAlign selectFontVAlign(LLXMLNodePtr node);
00552 static LLFontGL::StyleFlags selectFontStyle(LLXMLNodePtr node);
00553
00554
00555
00556 static void addColorXML(LLXMLNodePtr node, const LLColor4& color,
00557 const LLString& xml_name, const LLString& control_name);
00558 static void saveColorToXML(std::ostream& out, const LLColor4& color,
00559 const LLString& xml_name, const LLString& control_name,
00560 const LLString& indent);
00561
00562
00563 static LLWString escapeXML(const LLWString& xml);
00564
00565
00566
00567 static LLString escapeXML(const LLString& xml, LLString& indent);
00568
00569
00570 static BOOL focusNext(LLView::child_list_t & result);
00571
00572 static BOOL focusPrev(LLView::child_list_t & result);
00573
00574
00575 static const LLCtrlQuery & getTabOrderQuery();
00576
00577 static const LLCtrlQuery & getFocusRootsQuery();
00578
00579 static BOOL deleteViewByHandle(LLHandle<LLView> handle);
00580 static LLWindow* getWindow(void) { return LLUI::sWindow; }
00581
00582
00583 protected:
00584 virtual BOOL handleKeyHere(KEY key, MASK mask);
00585 virtual BOOL handleUnicodeCharHere(llwchar uni_char);
00586
00587 void drawDebugRect();
00588 void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);
00589
00590 LLView* childrenHandleKey(KEY key, MASK mask);
00591 LLView* childrenHandleUnicodeChar(llwchar uni_char);
00592 LLView* childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
00593 BOOL drop,
00594 EDragAndDropType type,
00595 void* data,
00596 EAcceptance* accept,
00597 LLString& tooltip_msg);
00598
00599 LLView* childrenHandleHover(S32 x, S32 y, MASK mask);
00600 LLView* childrenHandleMouseUp(S32 x, S32 y, MASK mask);
00601 LLView* childrenHandleMouseDown(S32 x, S32 y, MASK mask);
00602 LLView* childrenHandleDoubleClick(S32 x, S32 y, MASK mask);
00603 LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
00604 LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
00605 LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
00606
00607 static bool controlListener(const LLSD& newvalue, LLHandle<LLView> handle, std::string type);
00608
00609 typedef std::map<LLString, LLControlVariable*> control_map_t;
00610 control_map_t mFloaterControls;
00611
00612 private:
00613 LLView* mParentView;
00614 child_list_t mChildList;
00615
00616 LLString mName;
00617
00618 LLRect mRect;
00619 LLRect mBoundingRect;
00620
00621 U32 mReshapeFlags;
00622
00623 child_tab_order_t mCtrlOrder;
00624 S32 mDefaultTabGroup;
00625
00626 BOOL mEnabled;
00627
00628 BOOL mMouseOpaque;
00629 LLUIString mToolTipMsg;
00630
00631 U8 mSoundFlags;
00632 BOOL mSaveToXML;
00633
00634 BOOL mIsFocusRoot;
00635 BOOL mUseBoundingRect;
00636
00637 LLRootHandle<LLView> mHandle;
00638 BOOL mLastVisible;
00639
00640 BOOL mVisible;
00641
00642 S32 mNextInsertionOrdinal;
00643
00644 static LLWindow* sWindow;
00645
00646 typedef std::map<LLString, LLPointer<LLSimpleListener> > dispatch_list_t;
00647 dispatch_list_t mDispatchList;
00648
00649 LLString mControlName;
00650
00651 typedef std::map<LLString, LLView*> dummy_widget_map_t;
00652 dummy_widget_map_t mDummyWidgets;
00653
00654 boost::signals::connection mControlConnection;
00655
00656 public:
00657 static BOOL sDebugRects;
00658 static BOOL sDebugKeys;
00659 static S32 sDepth;
00660 static BOOL sDebugMouseHandling;
00661 static LLString sMouseHandlerMessage;
00662 static S32 sSelectID;
00663 static BOOL sEditingUI;
00664 static LLView* sEditingUIView;
00665 static S32 sLastLeftXML;
00666 static S32 sLastBottomXML;
00667 static BOOL sForceReshape;
00668 };
00669
00670 class LLCompareByTabOrder
00671 {
00672 public:
00673 LLCompareByTabOrder(LLView::child_tab_order_t order) : mTabOrder(order) {}
00674 virtual ~LLCompareByTabOrder() {}
00675 bool operator() (const LLView* const a, const LLView* const b) const;
00676 private:
00677 virtual bool compareTabOrders(const LLView::tab_order_t & a, const LLView::tab_order_t & b) const { return a < b; }
00678 LLView::child_tab_order_t mTabOrder;
00679 };
00680
00681
00682 #endif //LL_LLVIEW_H