/** * @file llfloater.h * @brief LLFloater base class * * $LicenseInfo:firstyear=2002&license=viewergpl$ * * Copyright (c) 2002-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$ */ // Floating "windows" within the GL display, like the inventory floater, // mini-map floater, etc. #ifndef LL_FLOATER_H #define LL_FLOATER_H #include "llpanel.h" #include "lluuid.h" #include "lltabcontainer.h" #include "llnotifications.h" #include class LLDragHandle; class LLResizeHandle; class LLResizeBar; class LLButton; class LLMultiFloater; class LLFloater; const S32 LLFLOATER_VPAD = 6; const S32 LLFLOATER_HPAD = 6; const S32 LLFLOATER_CLOSE_BOX_SIZE = 16; const S32 LLFLOATER_HEADER_SIZE = 18; const BOOL RESIZE_YES = TRUE; const BOOL RESIZE_NO = FALSE; const S32 DEFAULT_MIN_WIDTH = 100; const S32 DEFAULT_MIN_HEIGHT = 100; const BOOL DRAG_ON_TOP = FALSE; const BOOL DRAG_ON_LEFT = TRUE; const BOOL MINIMIZE_YES = TRUE; const BOOL MINIMIZE_NO = FALSE; const BOOL CLOSE_YES = TRUE; 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 floater_handle) : mFloaterHandle(floater_handle) {} LLFloater* getFloater() { return mFloaterHandle.get(); } private: LLHandle mFloaterHandle; }; class LLFloater : public LLPanel { friend class LLFloaterView; public: enum EFloaterButtons { BUTTON_CLOSE, BUTTON_RESTORE, BUTTON_MINIMIZE, BUTTON_TEAR_OFF, BUTTON_EDIT, BUTTON_COUNT }; LLFloater(); LLFloater(const std::string& name); //simple constructor for data-driven initialization LLFloater( const std::string& name, const LLRect& rect, const std::string& title, BOOL resizable = FALSE, S32 min_width = DEFAULT_MIN_WIDTH, S32 min_height = DEFAULT_MIN_HEIGHT, BOOL drag_on_left = FALSE, BOOL minimizable = TRUE, BOOL close_btn = TRUE, BOOL bordered = BORDER_NO); LLFloater( const std::string& name, const std::string& rect_control, const std::string& title, BOOL resizable = FALSE, S32 min_width = DEFAULT_MIN_WIDTH, S32 min_height = DEFAULT_MIN_HEIGHT, BOOL drag_on_left = FALSE, BOOL minimizable = TRUE, BOOL close_btn = TRUE, BOOL bordered = BORDER_NO); virtual ~LLFloater(); virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open = TRUE); /*virtual*/ void userSetShape(const LLRect& new_rect); /*virtual*/ BOOL canSnapTo(const LLView* other_view); /*virtual*/ void snappedTo(const LLView* snap_view); /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); // Can be called multiple times to reset floater parameters. // Deletes all children of the floater. virtual void initFloater(const std::string& title, BOOL resizable, S32 min_width, S32 min_height, BOOL drag_on_left, BOOL minimizable, BOOL close_btn); virtual void open(); /* Flawfinder: ignore */ // If allowed, close the floater cleanly, releasing focus. // app_quitting is passed to onClose() below. virtual void close(bool app_quitting = false); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // Release keyboard and mouse focus void releaseFocus(); // moves to center of gFloaterView void center(); // applies rectangle stored in mRectControl, if any void applyRectControl(); LLMultiFloater* getHost() { return (LLMultiFloater*)mHostHandle.get(); } void applyTitle(); const std::string& getCurrentTitle() const; void setTitle( const std::string& title); std::string getTitle(); void setShortTitle( const std::string& short_title ); std::string getShortTitle(); BOOL setTitleArg( const std::string& key, const LLStringExplicit& text ); BOOL setShortTitleArg( const std::string& key, const LLStringExplicit& text ); void setTitleVisible(bool visible); virtual void setMinimized(BOOL b); void moveResizeHandlesToFront(); void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE); void addDependentFloater(LLHandle dependent_handle, BOOL reposition = TRUE); LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); } void removeDependentFloater(LLFloater* dependent); BOOL isMinimized() { return mMinimized; } BOOL isFrontmost(); BOOL isDependent() { return !mDependeeHandle.isDead(); } void setCanMinimize(BOOL can_minimize); void setCanClose(BOOL can_close); void setCanTearOff(BOOL can_tear_off); virtual void setCanResize(BOOL can_resize); void setCanDrag(BOOL can_drag); void setHost(LLMultiFloater* host); BOOL isResizable() const { return mResizable; } void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } bool isMinimizeable() const{ return mButtonsEnabled[BUTTON_MINIMIZE]; } // Does this window have a close button, NOT can we close it right now. bool isCloseable() const{ return (mButtonsEnabled[BUTTON_CLOSE]); } bool isDragOnLeft() const{ return mDragOnLeft; } S32 getMinWidth() const{ return mMinWidth; } S32 getMinHeight() const{ return mMinHeight; } virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); virtual void draw(); virtual void onOpen() {} // Call destroy() to free memory, or setVisible(FALSE) to keep it // If app_quitting, you might not want to save your visibility. // Defaults to destroy(). virtual void onClose(bool app_quitting) { destroy(); } // This cannot be "const" until all derived floater canClose() // methods are const as well. JC virtual BOOL canClose() { return TRUE; } virtual void setVisible(BOOL visible); void setFrontmost(BOOL take_focus = TRUE); // Defaults to false. virtual BOOL canSaveAs() const { return FALSE; } virtual void saveAs() {} void setSnapTarget(LLHandle handle) { mSnappedTo = handle; } void clearSnapTarget() { mSnappedTo.markDead(); } LLHandle getSnapTarget() const { return mSnappedTo; } LLHandle getHandle() const { return mHandle; } // Return a closeable floater, if any, given the current focus. static LLFloater* getClosableFloaterFromFocus(); // Close the floater returned by getClosableFloaterFromFocus() and // handle refocusing. static void closeFocusedFloater(); LLNotification::Params contextualNotification(const std::string& name) { return LLNotification::Params(name).context(mNotificationContext); } static void onClickClose(void *userdata); static void onClickMinimize(void *userdata); static void onClickTearOff(void *userdata); static void onClickEdit(void *userdata); static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } static void setEditModeEnabled(BOOL enable); static BOOL getEditModeEnabled() { return sEditModeEnabled; } static LLMultiFloater* getFloaterHost() {return sHostp; } protected: virtual void bringToFront(S32 x, S32 y); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized const LLRect& getExpandedRect() const { return mExpandedRect; } void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened LLDragHandle* getDragHandle() const { return mDragHandle; } void destroy() { die(); } // Don't call this directly. You probably want to call close(). JC private: void setForeground(BOOL b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters void createMinimizeButton(); void updateButtons(); void buildButtons(); BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); LLRect mExpandedRect; LLDragHandle* mDragHandle; LLResizeBar* mResizeBar[4]; LLResizeHandle* mResizeHandle[4]; LLButton *mMinimizeButton; BOOL mCanTearOff; BOOL mMinimized; BOOL mForeground; LLHandle mDependeeHandle; LLUIString mTitle; LLUIString mShortTitle; BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible. BOOL mResizable; S32 mMinWidth; S32 mMinHeight; BOOL mEditing; typedef std::set > handle_set_t; typedef std::set >::iterator handle_set_iter_t; handle_set_t mDependents; bool mDragOnLeft; BOOL mButtonsEnabled[BUTTON_COUNT]; LLButton* mButtons[BUTTON_COUNT]; F32 mButtonScale; BOOL mAutoFocus; LLHandle mSnappedTo; LLHandle mHostHandle; LLHandle mLastHostHandle; static LLMultiFloater* sHostp; static BOOL sEditModeEnabled; static std::string sButtonActiveImageNames[BUTTON_COUNT]; static std::string sButtonInactiveImageNames[BUTTON_COUNT]; static std::string sButtonPressedImageNames[BUTTON_COUNT]; static std::string sButtonNames[BUTTON_COUNT]; static std::string sButtonToolTips[BUTTON_COUNT]; typedef void (*click_callback)(void *); static click_callback sButtonCallbacks[BUTTON_COUNT]; typedef std::map, LLFloater*> handle_map_t; typedef std::map, LLFloater*>::iterator handle_map_iter_t; static handle_map_t sFloaterMap; std::vector > mMinimizedHiddenChildren; BOOL mHasBeenDraggedWhileMinimized; S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; LLFloaterNotificationContext* mNotificationContext; LLRootHandle mHandle; }; ///////////////////////////////////////////////////////////// // LLFloaterView // Parent of all floating panels class LLFloaterView : public LLUICtrl { public: LLFloaterView( const std::string& name, const LLRect& rect ); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); void reshapeFloater(S32 width, S32 height, BOOL called_from_parent, BOOL adjust_vertical); /*virtual*/ void draw(); /*virtual*/ LLRect getSnapRect() const; void refresh(); void getNewFloaterPosition( S32* left, S32* top ); void resetStartingFloaterPosition(); LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ); // Given a child of gFloaterView, make sure this view can fit entirely onscreen. void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside); void getMinimizePosition( S32 *left, S32 *bottom); void restoreAll(); // un-minimize all floaters typedef std::set skip_list_t; void pushVisibleAll(BOOL visible, const skip_list_t& skip_list = skip_list_t()); void popVisibleAll(const skip_list_t& skip_list = skip_list_t()); void setCycleMode(BOOL mode) { mFocusCycleMode = mode; } BOOL getCycleMode() const { return mFocusCycleMode; } void bringToFront( LLFloater* child, BOOL give_focus = TRUE ); void highlightFocusedFloater(); void unhighlightFocusedFloater(); void focusFrontFloater(); void destroyAllChildren(); // attempt to close all floaters void closeAllChildren(bool app_quitting); BOOL allChildrenClosed(); void minimizeAllChildren(); LLFloater* getFrontmost(); LLFloater* getBackmost(); LLFloater* getParentFloater(LLView* viewp); LLFloater* getFocusedFloater(); void syncFloaterTabOrder(); // Returns z order of child provided. 0 is closest, larger numbers // are deeper in the screen. If there is no such child, the return // value is not defined. S32 getZOrder(LLFloater* child); void setSnapOffsetBottom(S32 offset) { mSnapOffsetBottom = offset; } private: S32 mColumn; S32 mNextLeft; S32 mNextTop; BOOL mFocusCycleMode; S32 mSnapOffsetBottom; }; // https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376 class LLMultiFloater : public LLFloater { public: LLMultiFloater(); LLMultiFloater(LLTabContainer::TabPosition tab_pos); LLMultiFloater(const std::string& name); LLMultiFloater(const std::string& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); LLMultiFloater(const std::string& name, const std::string& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); virtual ~LLMultiFloater() {}; virtual BOOL postBuild(); virtual LLXMLNodePtr getXML(bool save_children = true) const; /*virtual*/ void open(); /* Flawfinder: ignore */ /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void draw(); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); virtual void setCanResize(BOOL can_resize); virtual void growToFit(S32 content_width, S32 content_height); virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); virtual void showFloater(LLFloater* floaterp); virtual void removeFloater(LLFloater* floaterp); virtual void tabOpen(LLFloater* opened_floater, bool from_click); virtual void tabClose(); virtual BOOL selectFloater(LLFloater* floaterp); virtual void selectNextFloater(); virtual void selectPrevFloater(); virtual LLFloater* getActiveFloater(); virtual BOOL isFloaterFlashing(LLFloater* floaterp); virtual S32 getFloaterCount(); virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; } static void onTabSelected(void* userdata, bool); virtual void updateResizeLimits(); protected: struct LLFloaterData { S32 mWidth; S32 mHeight; BOOL mCanMinimize; BOOL mCanResize; }; LLTabContainer* mTabContainer; typedef std::map, LLFloaterData> floater_data_map_t; floater_data_map_t mFloaterDataMap; LLTabContainer::TabPosition mTabPos; BOOL mAutoResize; S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late }; // visibility policy specialized for floaters template<> class VisibilityPolicy { public: // visibility methods static bool visible(LLFloater* instance, const LLSD& key) { if (instance) { return !instance->isMinimized() && instance->isInVisibleChain(); } return FALSE; } static void show(LLFloater* instance, const LLSD& key) { if (instance) { instance->open(); if (instance->getHost()) { instance->getHost()->open(); } } } static void hide(LLFloater* instance, const LLSD& key) { if (instance) instance->close(); } }; // singleton implementation for floaters (provides visibility policy) // https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 template class LLFloaterSingleton : public LLUISingleton > { }; extern LLFloaterView* gFloaterView; #endif // LL_FLOATER_H