/** * @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 "llnotifications.h" #include <set> class LLDragHandle; class LLResizeHandle; class LLResizeBar; class LLButton; class LLMultiFloater; class LLFloater; const BOOL RESIZE_YES = TRUE; const BOOL RESIZE_NO = FALSE; 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<LLFloater> floater_handle) : mFloaterHandle(floater_handle) {} LLFloater* getFloater() { return mFloaterHandle.get(); } private: LLHandle<LLFloater> mFloaterHandle; }; class LLFloater : public LLPanel { friend class LLFloaterView; friend class LLFloaterReg; friend class LLMultiFloater; public: struct KeyCompare { static bool compare(const LLSD& a, const LLSD& b); static bool equate(const LLSD& a, const LLSD& b); bool operator()(const LLSD& a, const LLSD& b) const { return compare(a, b); } }; enum EFloaterButtons { BUTTON_CLOSE = 0, BUTTON_RESTORE, BUTTON_MINIMIZE, BUTTON_TEAR_OFF, BUTTON_DOCK, BUTTON_UNDOCK, BUTTON_HELP, BUTTON_COUNT }; struct Params : public LLInitParam::Block<Params, LLPanel::Params> { Optional<std::string> title, short_title; Optional<bool> single_instance, auto_tile, can_resize, can_minimize, can_close, can_drag_on_left, can_tear_off, save_rect, save_visibility, can_dock; Optional<CommitCallbackParam> open_callback, close_callback; Params(); }; // use this to avoid creating your own default LLFloater::Param instance static const Params& getDefaultParams(); // Load translations for tooltips for standard buttons static void initClass(); LLFloater(const LLSD& key, const Params& params = getDefaultParams()); virtual ~LLFloater(); // Don't export top/left for rect, only height/width static void setupParamsForExport(Params& p, LLView* parent); void initFromParams(const LLFloater::Params& p); void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); /*virtual*/ BOOL canSnapTo(const LLView* other_view); /*virtual*/ void setSnappedTo(const LLView* snap_view); /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); /*virtual*/ void setRect(const LLRect &rect); void initFloater(); void openFloater(const LLSD& key = LLSD()); // If allowed, close the floater cleanly, releasing focus. void closeFloater(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(); LLMultiFloater* getHost(); void applyTitle(); const std::string& getCurrentTitle() const; void setTitle( const std::string& title); std::string getTitle() const; void setShortTitle( const std::string& short_title ); std::string getShortTitle() const; void setTitleVisible(bool visible); virtual void setMinimized(BOOL b); void moveResizeHandlesToFront(); void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE); void addDependentFloater(LLHandle<LLFloater> 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 mCanMinimize; } bool isCloseable() const{ return mCanClose; } 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(); // *TODO: Eliminate this in favor of mOpenSignal virtual void onOpen(const LLSD& key) {} // 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); // do not override /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override void setFrontmost(BOOL take_focus = TRUE); // Defaults to false. virtual BOOL canSaveAs() const { return FALSE; } virtual void saveAs() {} void setSnapTarget(LLHandle<LLFloater> handle) { mSnappedTo = handle; } void clearSnapTarget() { mSnappedTo.markDead(); } LLHandle<LLFloater> getSnapTarget() const { return mSnappedTo; } LLHandle<LLFloater> getHandle() const { return mHandle; } const LLSD& getKey() { return mKey; } BOOL matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } const std::string& getInstanceName() { return mInstanceName; } bool isDockable() const { return mCanDock; } void setCanDock(bool b); bool isDocked() const { return mDocked; } virtual void setDocked(bool docked, bool pop_on_undock = true); // 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(LLFloater* floater); static void onClickMinimize(LLFloater* floater); static void onClickTearOff(LLFloater* floater); static void onClickDock(LLFloater* floater); static void onClickHelp(LLFloater* floater); static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } static LLMultiFloater* getFloaterHost() {return sHostp; } protected: void setRectControl(const std::string& rectname) { mRectControl = rectname; }; void applyRectControl(); void storeRectControl(); void storeVisibilityControl(); void setKey(const LLSD& key); void setInstanceName(const std::string& name); 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 closeFloater() 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); void addResizeCtrls(); void addDragHandle(); protected: std::string mRectControl; std::string mVisibilityControl; commit_signal_t mOpenSignal; // Called when floater is opened, passes mKey commit_signal_t mCloseSignal; // Called when floater is closed, passes app_qitting as LLSD() LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg LLDragHandle* mDragHandle; LLResizeBar* mResizeBar[4]; LLResizeHandle* mResizeHandle[4]; private: LLRect mExpandedRect; LLUIString mTitle; LLUIString mShortTitle; BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater std::string mInstanceName; // Store the instance name so we can remove ourselves from the list BOOL mAutoTile; // TRUE if placement of new instances tiles BOOL mCanTearOff; BOOL mCanMinimize; BOOL mCanClose; BOOL mDragOnLeft; BOOL mResizable; S32 mMinWidth; S32 mMinHeight; BOOL mMinimized; BOOL mForeground; LLHandle<LLFloater> mDependeeHandle; BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible. typedef std::set<LLHandle<LLFloater> > handle_set_t; typedef std::set<LLHandle<LLFloater> >::iterator handle_set_iter_t; handle_set_t mDependents; BOOL mButtonsEnabled[BUTTON_COUNT]; LLButton* mButtons[BUTTON_COUNT]; F32 mButtonScale; BOOL mAutoFocus; LLHandle<LLFloater> mSnappedTo; LLHandle<LLFloater> mHostHandle; LLHandle<LLFloater> mLastHostHandle; bool mCanDock; bool mDocked; 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]; typedef void(*click_callback)(LLFloater*); static click_callback sButtonCallbacks[BUTTON_COUNT]; typedef std::map<LLHandle<LLFloater>, LLFloater*> handle_map_t; typedef std::map<LLHandle<LLFloater>, LLFloater*>::iterator handle_map_iter_t; static handle_map_t sFloaterMap; std::vector<LLHandle<LLView> > mMinimizedHiddenChildren; BOOL mHasBeenDraggedWhileMinimized; S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; LLFloaterNotificationContext* mNotificationContext; LLRootHandle<LLFloater> mHandle; }; ///////////////////////////////////////////////////////////// // LLFloaterView // Parent of all floating panels class LLFloaterView : public LLUICtrl { protected: LLFloaterView (const Params& p); friend class LLUICtrlFactory; public: /*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; /*virtual*/ void refresh(); 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<LLView*> 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(); LLFloater* getFrontmost() const; LLFloater* getBackmost() const; LLFloater* getParentFloater(LLView* viewp) const; LLFloater* getFocusedFloater() const; 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; } void setSnapOffsetRight(S32 offset) { mSnapOffsetRight = offset; } private: S32 mColumn; S32 mNextLeft; S32 mNextTop; BOOL mFocusCycleMode; S32 mSnapOffsetBottom; S32 mSnapOffsetRight; }; // // Globals // extern LLFloaterView* gFloaterView; #endif // LL_FLOATER_H