gecko/layout/xul/base/src/nsMenuPopupFrame.h

330 lines
13 KiB
C
Raw Normal View History

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: David W. Hyatt (hyatt@netscape.com)
* Mike Pinkerton (pinkerton@netscape.com)
* Dean Tessman <dean_tessman@hotmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// nsMenuPopupFrame
//
#ifndef nsMenuPopupFrame_h__
#define nsMenuPopupFrame_h__
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsGkAtoms.h"
#include "nsCOMPtr.h"
#include "nsMenuFrame.h"
#include "nsIDOMEventTarget.h"
#include "nsBoxFrame.h"
#include "nsIMenuParent.h"
#include "nsIWidget.h"
#include "nsITimer.h"
// XUL popups can be in several different states. When opening a popup, the
// state changes as follows:
// ePopupClosed - initial state
// ePopupShowing - during the period when the popupshowing event fires
// ePopupOpen - between the popupshowing event and being visible. Creation
// of the child frames, layout and reflow occurs in this state.
// ePopupOpenAndVisible - layout is done and AdjustView is called to make
// the popup's widget visible. The popup is now
// visible and the popupshown event fires.
// When closing a popup:
// ePopupHidden - during the period when the popuphiding event fires and
// the popup is removed.
// ePopupClosed - the popup's widget is made invisible.
enum nsPopupState {
// state when a popup is not open
ePopupClosed,
// state from when a popup is requested to be shown to after the
// popupshowing event has been fired.
ePopupShowing,
// state while a popup is open but the widget is not yet visible
ePopupOpen,
// state while a popup is open and visible on screen
ePopupOpenAndVisible,
// state from when a popup is requested to be hidden to when it is closed.
ePopupHiding,
// state which indicates that the popup was hidden without firing the
// popuphiding or popuphidden events. It is used when executing a menu
// command because the menu needs to be hidden before the command event
// fires, yet the popuphiding and popuphidden events are fired after. This
// state can also occur when the popup is removed because the document is
// unloaded.
ePopupInvisible
};
// values are selected so that the direction can be flipped just by
// changing the sign
#define POPUPALIGNMENT_NONE 0
#define POPUPALIGNMENT_TOPLEFT 1
#define POPUPALIGNMENT_TOPRIGHT -1
#define POPUPALIGNMENT_BOTTOMLEFT 2
#define POPUPALIGNMENT_BOTTOMRIGHT -2
#define INC_TYP_INTERVAL 1000 // 1s. If the interval between two keypresses is shorter than this,
// treat as a continue typing
// XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose:
// nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml
// need to find a good place to put them together.
// if someone changes one, please also change the other.
nsIFrame* NS_NewMenuPopupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
class nsIViewManager;
class nsIView;
class nsIMenuParent;
class nsMenuPopupFrame;
class nsMenuPopupFrame : public nsBoxFrame, public nsIMenuParent
{
public:
nsMenuPopupFrame(nsIPresShell* aShell, nsStyleContext* aContext);
// nsIMenuParentInterface
virtual nsMenuFrame* GetCurrentMenuItem();
NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem);
virtual void CurrentMenuIsBeingDestroyed();
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, PRBool aSelectFirstItem);
// as popups are opened asynchronously, the popup pending state is used to
// prevent multiple requests from attempting to open the same popup twice
nsPopupState PopupState() { return mPopupState; }
void SetPopupState(nsPopupState aPopupState) { mPopupState = aPopupState; }
NS_IMETHOD SetActive(PRBool aActiveFlag) { return NS_OK; } // We don't care.
virtual PRBool IsActive() { return PR_FALSE; }
virtual PRBool IsMenuBar() { return PR_FALSE; }
/*
* When this popup is open, should clicks outside of it be consumed?
* Return PR_TRUE if the popup should rollup on an outside click,
* but consume that click so it can't be used for anything else.
* Return PR_FALSE to allow clicks outside the popup to activate content
* even when the popup is open.
* ---------------------------------------------------------------------
*
* Should clicks outside of a popup be eaten?
*
* Menus Autocomplete Comboboxes
* Mac Eat No Eat
* Win No No Eat
* Unix Eat No Eat
*
*/
PRBool ConsumeOutsideClicks();
virtual PRBool IsContextMenu() { return mIsContextMenu; }
virtual PRBool MenuClosed() { return PR_TRUE; }
virtual PRBool IsRecentlyClosed(nsMenuFrame* aMenuFrame) { return PR_FALSE; }
NS_IMETHOD GetWidget(nsIWidget **aWidget);
// The dismissal listener gets created and attached to the window.
void AttachedDismissalListener();
// Overridden methods
NS_IMETHOD Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
virtual void Destroy();
virtual void InvalidateInternal(const nsRect& aDamageRect,
nscoord aX, nscoord aY, nsIFrame* aForChild,
PRBool aImmediate);
void EnsureWidget();
virtual nsresult CreateWidgetForView(nsIView* aView);
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
nsIFrame* aChildList);
virtual PRBool IsLeaf() const;
// AdjustView should be called by the parent frame after the popup has been
// laid out, so that the view can be shown.
void AdjustView();
nsIView* GetRootViewForPopup(nsIFrame* aStartFrame);
// set the position of the popup either relative to the anchor aAnchorFrame
// (or the frame for mAnchorContent if aAnchorFrame is null) or at a specific
// point if a screen position (mScreenXPos and mScreenYPos) are set. The popup
// will be adjusted so that it is on screen.
nsresult SetPopupPosition(nsIFrame* aAnchorFrame);
PRBool HasGeneratedChildren() { return mGeneratedChildren; }
void SetGeneratedChildren() { mGeneratedChildren = PR_TRUE; }
// called when the Enter key is pressed while the popup is open. This will
// just pass the call down to the current menu, if any. Also, calling Enter
// will reset the current incremental search string, calculated in
// FindMenuWithShortcut
nsMenuFrame* Enter();
nsPopupType PopupType() const { return mPopupType; }
PRBool IsMenu() { return mPopupType == ePopupTypeMenu; }
PRBool IsOpen() { return mPopupState == ePopupOpen || mPopupState == ePopupOpenAndVisible; }
PRBool HasOpenChanged() { return mIsOpenChanged; }
// returns true if the popup is in a content shell, or false for a popup in
// a chrome shell
PRBool IsInContentShell() { return mInContentShell; }
// the Initialize methods are used to set the anchor position for
// each way of opening a popup.
void InitializePopup(nsIContent* aAnchorContent,
const nsAString& aPosition,
PRInt32 aXPos, PRInt32 aYPos,
PRBool aAttributesOverride);
void InitializePopupAtScreen(PRInt32 aXPos, PRInt32 aYPos);
void InitializePopupWithAnchorAlign(nsIContent* aAnchorContent,
nsAString& aAnchor,
nsAString& aAlign,
PRInt32 aXPos, PRInt32 aYPos);
// indicate that the popup should be opened
PRBool ShowPopup(PRBool aIsContextMenu, PRBool aSelectFirstItem);
// indicate that the popup should be hidden. The new state should either be
// ePopupClosed or ePopupInvisible.
void HidePopup(PRBool aDeselectMenu, nsPopupState aNewState);
// locate and return the menu frame that should be activated for the
// supplied key event. If doAction is set to true by this method,
// then the menu's action should be carried out, as if the user had pressed
// the Enter key. If doAction is false, the menu should just be highlighted.
// This method also handles incremental searching in menus so the user can
// type the first few letters of an item/s name to select it.
nsMenuFrame* FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, PRBool& doAction);
void ClearIncrementalString() { mIncrementalString.Truncate(); }
virtual nsIAtom* GetType() const { return nsGkAtoms::menuPopupFrame; }
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("MenuPopup"), aResult);
}
#endif
void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
// This sets 'left' and 'top' attributes.
// May kill the frame.
void MoveTo(PRInt32 aLeft, PRInt32 aTop);
void GetAutoPosition(PRBool* aShouldAutoPosition);
void SetAutoPosition(PRBool aShouldAutoPosition);
void SetConsumeRollupEvent(PRUint32 aConsumeMode);
nsIScrollableView* GetScrollableView(nsIFrame* aStart);
protected:
// Move without updating attributes.
void MoveToInternal(PRInt32 aLeft, PRInt32 aTop);
// redefine to tell the box system not to move the views.
virtual void GetLayoutFlags(PRUint32& aFlags);
void InitPositionFromAnchorAlign(const nsAString& aAnchor,
const nsAString& aAlign);
void AdjustPositionForAnchorAlign ( PRInt32* ioXPos, PRInt32* ioYPos, const nsRect & inParentRect,
PRBool* outFlushWithTopBottom ) ;
PRBool IsMoreRoomOnOtherSideOfParent ( PRBool inFlushAboveBelow, PRInt32 inScreenViewLocX, PRInt32 inScreenViewLocY,
const nsRect & inScreenParentFrameRect, PRInt32 inScreenTopTwips, PRInt32 inScreenLeftTwips,
PRInt32 inScreenBottomTwips, PRInt32 inScreenRightTwips ) ;
void MovePopupToOtherSideOfParent ( PRBool inFlushAboveBelow, PRInt32* ioXPos, PRInt32* ioYPos,
PRInt32* ioScreenViewLocX, PRInt32* ioScreenViewLocY,
const nsRect & inScreenParentFrameRect, PRInt32 inScreenTopTwips, PRInt32 inScreenLeftTwips,
PRInt32 inScreenBottomTwips, PRInt32 inScreenRightTwips ) ;
// Move the popup to the position specified in its |left| and |top| attributes.
void MoveToAttributePosition();
// the content that the popup is anchored to, if any, which may be in a
// different document than the popup.
nsCOMPtr<nsIContent> mAnchorContent;
nsMenuFrame* mCurrentMenu; // The current menu that is active.
// popup alignment relative to the anchor node
PRInt8 mPopupAlignment;
PRInt8 mPopupAnchor;
// the position of the popup. The screen coordinates, if set to values other
// than -1, override mXPos and mYPos.
PRInt32 mXPos;
PRInt32 mYPos;
PRInt32 mScreenXPos;
PRInt32 mScreenYPos;
nsPopupType mPopupType; // type of popup
nsPopupState mPopupState; // open state of the popup
PRPackedBool mIsOpenChanged; // true if the open state changed since the last layout
PRPackedBool mIsContextMenu; // true for context menus
PRPackedBool mGeneratedChildren; // true if the contents have been created
PRPackedBool mMenuCanOverlapOSBar; // can we appear over the taskbar/menubar?
PRPackedBool mShouldAutoPosition; // Should SetPopupPosition be allowed to auto position popup?
PRPackedBool mConsumeRollupEvent; // Should the rollup event be consumed?
PRPackedBool mInContentShell; // True if the popup is in a content shell
nsString mIncrementalString; // for incremental typing navigation
}; // class nsMenuPopupFrame
#endif