layout/xul/nsMenuFrame.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/xul/nsMenuFrame.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,286 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +//
    1.10 +// nsMenuFrame
    1.11 +//
    1.12 +
    1.13 +#ifndef nsMenuFrame_h__
    1.14 +#define nsMenuFrame_h__
    1.15 +
    1.16 +#include "nsIAtom.h"
    1.17 +#include "nsCOMPtr.h"
    1.18 +
    1.19 +#include "nsBoxFrame.h"
    1.20 +#include "nsFrameList.h"
    1.21 +#include "nsGkAtoms.h"
    1.22 +#include "nsMenuParent.h"
    1.23 +#include "nsXULPopupManager.h"
    1.24 +#include "nsITimer.h"
    1.25 +#include "mozilla/Attributes.h"
    1.26 +
    1.27 +nsIFrame* NS_NewMenuFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
    1.28 +nsIFrame* NS_NewMenuItemFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
    1.29 +
    1.30 +class nsIContent;
    1.31 +class nsMenuBarFrame;
    1.32 +
    1.33 +#define NS_STATE_ACCELTEXT_IS_DERIVED  NS_STATE_BOX_CHILD_RESERVED
    1.34 +
    1.35 +// the type of menuitem
    1.36 +enum nsMenuType {
    1.37 +  // a normal menuitem where a command is carried out when activated
    1.38 +  eMenuType_Normal = 0,
    1.39 +  // a menuitem with a checkmark that toggles when activated
    1.40 +  eMenuType_Checkbox = 1,
    1.41 +  // a radio menuitem where only one of it and its siblings with the same
    1.42 +  // name attribute can be checked at a time
    1.43 +  eMenuType_Radio = 2
    1.44 +};
    1.45 +
    1.46 +enum nsMenuListType {
    1.47 +  eNotMenuList,      // not a menulist
    1.48 +  eReadonlyMenuList, // <menulist/>
    1.49 +  eEditableMenuList  // <menulist editable="true"/>
    1.50 +};
    1.51 +
    1.52 +class nsMenuFrame;
    1.53 +
    1.54 +/**
    1.55 + * nsMenuTimerMediator is a wrapper around an nsMenuFrame which can be safely
    1.56 + * passed to timers. The class is reference counted unlike the underlying
    1.57 + * nsMenuFrame, so that it will exist as long as the timer holds a reference
    1.58 + * to it. The callback is delegated to the contained nsMenuFrame as long as
    1.59 + * the contained nsMenuFrame has not been destroyed.
    1.60 + */
    1.61 +class nsMenuTimerMediator MOZ_FINAL : public nsITimerCallback
    1.62 +{
    1.63 +public:
    1.64 +  nsMenuTimerMediator(nsMenuFrame* aFrame);
    1.65 +  ~nsMenuTimerMediator();
    1.66 +
    1.67 +  NS_DECL_ISUPPORTS
    1.68 +  NS_DECL_NSITIMERCALLBACK
    1.69 +
    1.70 +  void ClearFrame();
    1.71 +
    1.72 +private:
    1.73 +
    1.74 +  // Pointer to the wrapped frame.
    1.75 +  nsMenuFrame* mFrame;
    1.76 +};
    1.77 +
    1.78 +class nsMenuFrame : public nsBoxFrame
    1.79 +{
    1.80 +public:
    1.81 +  nsMenuFrame(nsIPresShell* aShell, nsStyleContext* aContext);
    1.82 +
    1.83 +  NS_DECL_QUERYFRAME_TARGET(nsMenuFrame)
    1.84 +  NS_DECL_QUERYFRAME
    1.85 +  NS_DECL_FRAMEARENA_HELPERS
    1.86 +
    1.87 +  NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
    1.88 +  virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
    1.89 +  virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
    1.90 +
    1.91 +  virtual void Init(nsIContent*      aContent,
    1.92 +                    nsIFrame*        aParent,
    1.93 +                    nsIFrame*        aPrevInFlow) MOZ_OVERRIDE;
    1.94 +
    1.95 +#ifdef DEBUG_LAYOUT
    1.96 +  virtual nsresult SetDebug(nsBoxLayoutState& aState, bool aDebug) MOZ_OVERRIDE;
    1.97 +#endif
    1.98 +
    1.99 +  // The following methods are all overridden so that the menupopup
   1.100 +  // can be stored in a separate list, so that it doesn't impact reflow of the
   1.101 +  // actual menu item at all.
   1.102 +  virtual const nsFrameList& GetChildList(ChildListID aList) const MOZ_OVERRIDE;
   1.103 +  virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE;
   1.104 +  virtual nsresult SetInitialChildList(ChildListID  aListID,
   1.105 +                                       nsFrameList& aChildList) MOZ_OVERRIDE;
   1.106 +  virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
   1.107 +
   1.108 +  // Overridden to prevent events from going to children of the menu.
   1.109 +  virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
   1.110 +                                           const nsRect&           aDirtyRect,
   1.111 +                                           const nsDisplayListSet& aLists) MOZ_OVERRIDE;
   1.112 +                                         
   1.113 +  // this method can destroy the frame
   1.114 +  virtual nsresult HandleEvent(nsPresContext* aPresContext,
   1.115 +                               mozilla::WidgetGUIEvent* aEvent,
   1.116 +                               nsEventStatus* aEventStatus) MOZ_OVERRIDE;
   1.117 +
   1.118 +  virtual nsresult  AppendFrames(ChildListID     aListID,
   1.119 +                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
   1.120 +
   1.121 +  virtual nsresult  InsertFrames(ChildListID     aListID,
   1.122 +                                 nsIFrame*       aPrevFrame,
   1.123 +                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
   1.124 +
   1.125 +  virtual nsresult  RemoveFrame(ChildListID     aListID,
   1.126 +                                nsIFrame*       aOldFrame) MOZ_OVERRIDE;
   1.127 +
   1.128 +  virtual nsIAtom* GetType() const MOZ_OVERRIDE { return nsGkAtoms::menuFrame; }
   1.129 +
   1.130 +  NS_IMETHOD SelectMenu(bool aActivateFlag);
   1.131 +
   1.132 +  virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE;
   1.133 +
   1.134 +  // Retrieve the element that the menu should be anchored to. By default this is
   1.135 +  // the menu itself. However, the anchor attribute may refer to the value of an
   1.136 +  // anonid within the menu's binding, or, if not found, the id of an element in
   1.137 +  // the document.
   1.138 +  nsIContent* GetAnchor();
   1.139 +
   1.140 +  /**
   1.141 +   * NOTE: OpenMenu will open the menu asynchronously.
   1.142 +   */
   1.143 +  void OpenMenu(bool aSelectFirstItem);
   1.144 +  // CloseMenu closes the menu asynchronously
   1.145 +  void CloseMenu(bool aDeselectMenu);
   1.146 +
   1.147 +  bool IsChecked() { return mChecked; }
   1.148 +
   1.149 +  NS_IMETHOD GetActiveChild(nsIDOMElement** aResult);
   1.150 +  NS_IMETHOD SetActiveChild(nsIDOMElement* aChild);
   1.151 +
   1.152 +  // called when the Enter key is pressed while the menuitem is the current
   1.153 +  // one in its parent popup. This will carry out the command attached to
   1.154 +  // the menuitem. If the menu should be opened, this frame will be returned,
   1.155 +  // otherwise null will be returned.
   1.156 +  nsMenuFrame* Enter(mozilla::WidgetGUIEvent* aEvent);
   1.157 +
   1.158 +  virtual void SetParent(nsIFrame* aParent) MOZ_OVERRIDE;
   1.159 +
   1.160 +  virtual nsMenuParent *GetMenuParent() { return mMenuParent; }
   1.161 +  const nsAString& GetRadioGroupName() { return mGroupName; }
   1.162 +  nsMenuType GetMenuType() { return mType; }
   1.163 +  nsMenuPopupFrame* GetPopup();
   1.164 +
   1.165 +  /**
   1.166 +   * @return true if this frame has a popup child frame.
   1.167 +   */
   1.168 +  bool HasPopup() const
   1.169 +  {
   1.170 +    return (GetStateBits() & NS_STATE_MENU_HAS_POPUP_LIST) != 0;
   1.171 +  }
   1.172 +
   1.173 +
   1.174 +  // nsMenuFrame methods 
   1.175 +
   1.176 +  bool IsOnMenuBar() { return mMenuParent && mMenuParent->IsMenuBar(); }
   1.177 +  bool IsOnActiveMenuBar() { return IsOnMenuBar() && mMenuParent->IsActive(); }
   1.178 +  virtual bool IsOpen();
   1.179 +  virtual bool IsMenu();
   1.180 +  nsMenuListType GetParentMenuListType();
   1.181 +  bool IsDisabled();
   1.182 +  void ToggleMenuState();
   1.183 +
   1.184 +  // indiciate that the menu's popup has just been opened, so that the menu
   1.185 +  // can update its open state. This method modifies the open attribute on
   1.186 +  // the menu, so the frames could be gone after this call.
   1.187 +  void PopupOpened();
   1.188 +  // indiciate that the menu's popup has just been closed, so that the menu
   1.189 +  // can update its open state. The menu should be unhighlighted if
   1.190 +  // aDeselectedMenu is true. This method modifies the open attribute on
   1.191 +  // the menu, so the frames could be gone after this call.
   1.192 +  void PopupClosed(bool aDeselectMenu);
   1.193 +
   1.194 +  // returns true if this is a menu on another menu popup. A menu is a submenu
   1.195 +  // if it has a parent popup or menupopup.
   1.196 +  bool IsOnMenu() { return mMenuParent && mMenuParent->IsMenu(); }
   1.197 +  void SetIsMenu(bool aIsMenu) { mIsMenu = aIsMenu; }
   1.198 +
   1.199 +#ifdef DEBUG_FRAME_DUMP
   1.200 +  virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
   1.201 +  {
   1.202 +      return MakeFrameName(NS_LITERAL_STRING("Menu"), aResult);
   1.203 +  }
   1.204 +#endif
   1.205 +
   1.206 +  static bool IsSizedToPopup(nsIContent* aContent, bool aRequireAlways);
   1.207 +
   1.208 +protected:
   1.209 +  friend class nsMenuTimerMediator;
   1.210 +  friend class nsASyncMenuInitialization;
   1.211 +  friend class nsMenuAttributeChangedEvent;
   1.212 +
   1.213 +  /**
   1.214 +   * Initialize the popup list to the first popup frame within
   1.215 +   * aChildList. Removes the popup, if any, from aChildList.
   1.216 +   */
   1.217 +  void SetPopupFrame(nsFrameList& aChildList);
   1.218 +
   1.219 +  /**
   1.220 +   * Get the popup frame list from the frame property.
   1.221 +   * @return the property value if it exists, nullptr otherwise.
   1.222 +   */
   1.223 +  nsFrameList* GetPopupList() const;
   1.224 +
   1.225 +  /**
   1.226 +   * Destroy the popup list property.  The list must exist and be empty.
   1.227 +   */
   1.228 +  void DestroyPopupList();
   1.229 +
   1.230 +  // set mMenuParent to the nearest enclosing menu bar or menupopup frame of
   1.231 +  // aParent (or aParent itself). This is called when initializing the frame,
   1.232 +  // so aParent should be the expected parent of this frame.
   1.233 +  void InitMenuParent(nsIFrame* aParent);
   1.234 +
   1.235 +  // Update the menu's type (normal, checkbox, radio).
   1.236 +  // This method can destroy the frame.
   1.237 +  void UpdateMenuType(nsPresContext* aPresContext);
   1.238 +  // Update the checked state of the menu, and for radios, clear any other
   1.239 +  // checked items. This method can destroy the frame.
   1.240 +  void UpdateMenuSpecialState(nsPresContext* aPresContext);
   1.241 +
   1.242 +  // Examines the key node and builds the accelerator.
   1.243 +  void BuildAcceleratorText(bool aNotify);
   1.244 +
   1.245 +  // Called to execute our command handler. This method can destroy the frame.
   1.246 +  void Execute(mozilla::WidgetGUIEvent *aEvent);
   1.247 +
   1.248 +  // This method can destroy the frame
   1.249 +  virtual nsresult AttributeChanged(int32_t aNameSpaceID,
   1.250 +                                    nsIAtom* aAttribute,
   1.251 +                                    int32_t aModType) MOZ_OVERRIDE;
   1.252 +  virtual ~nsMenuFrame() { }
   1.253 +
   1.254 +  bool SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize);
   1.255 +
   1.256 +  bool ShouldBlink();
   1.257 +  void StartBlinking(mozilla::WidgetGUIEvent* aEvent, bool aFlipChecked);
   1.258 +  void StopBlinking();
   1.259 +  void CreateMenuCommandEvent(mozilla::WidgetGUIEvent* aEvent,
   1.260 +                              bool aFlipChecked);
   1.261 +  void PassMenuCommandEventToPopupManager();
   1.262 +
   1.263 +protected:
   1.264 +#ifdef DEBUG_LAYOUT
   1.265 +  nsresult SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, bool aDebug);
   1.266 +#endif
   1.267 +  NS_HIDDEN_(nsresult) Notify(nsITimer* aTimer);
   1.268 +
   1.269 +  bool mIsMenu; // Whether or not we can even have children or not.
   1.270 +  bool mChecked;              // are we checked?
   1.271 +  bool mIgnoreAccelTextChange; // temporarily set while determining the accelerator key
   1.272 +  nsMenuType mType;
   1.273 +
   1.274 +  nsMenuParent* mMenuParent; // Our parent menu.
   1.275 +
   1.276 +  // Reference to the mediator which wraps this frame.
   1.277 +  nsRefPtr<nsMenuTimerMediator> mTimerMediator;
   1.278 +
   1.279 +  nsCOMPtr<nsITimer> mOpenTimer;
   1.280 +  nsCOMPtr<nsITimer> mBlinkTimer;
   1.281 +
   1.282 +  uint8_t mBlinkState; // 0: not blinking, 1: off, 2: on
   1.283 +  nsRefPtr<nsXULMenuCommandEvent> mDelayedMenuCommandEvent;
   1.284 +
   1.285 +  nsString mGroupName;
   1.286 +
   1.287 +}; // class nsMenuFrame
   1.288 +
   1.289 +#endif

mercurial