Mypal/widget/gtk/nsMenuContainer.cpp

157 lines
4.3 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/DebugOnly.h"
#include "mozilla/Move.h"
#include "nsGkAtoms.h"
#include "nsIAtom.h"
#include "nsIContent.h"
#include "nsDbusmenu.h"
#include "nsMenu.h"
#include "nsMenuItem.h"
#include "nsMenuSeparator.h"
#include "nsMenuContainer.h"
using namespace mozilla;
const nsMenuContainer::ChildTArray::index_type nsMenuContainer::NoIndex = nsMenuContainer::ChildTArray::NoIndex;
typedef UniquePtr<nsMenuObject> (*nsMenuObjectConstructor)(nsMenuContainer*,
nsIContent*);
template<class T>
static UniquePtr<nsMenuObject> CreateMenuObject(nsMenuContainer* aContainer,
nsIContent* aContent) {
return UniquePtr<T>(new T(aContainer, aContent));
}
static nsMenuObjectConstructor
GetMenuObjectConstructor(nsIContent* aContent) {
if (aContent->IsXULElement(nsGkAtoms::menuitem)) {
return CreateMenuObject<nsMenuItem>;
} else if (aContent->IsXULElement(nsGkAtoms::menu)) {
return CreateMenuObject<nsMenu>;
} else if (aContent->IsXULElement(nsGkAtoms::menuseparator)) {
return CreateMenuObject<nsMenuSeparator>;
}
return nullptr;
}
static bool
ContentIsSupported(nsIContent* aContent) {
return GetMenuObjectConstructor(aContent) ? true : false;
}
nsMenuContainer::nsMenuContainer(nsMenuContainer* aParent,
nsIContent* aContent) :
nsMenuObject(aParent, aContent) {
}
nsMenuContainer::nsMenuContainer(nsNativeMenuDocListener* aListener,
nsIContent* aContent) :
nsMenuObject(aListener, aContent) {
}
UniquePtr<nsMenuObject>
nsMenuContainer::CreateChild(nsIContent* aContent) {
nsMenuObjectConstructor ctor = GetMenuObjectConstructor(aContent);
if (!ctor) {
// There are plenty of node types we might stumble across that
// aren't supported
return nullptr;
}
UniquePtr<nsMenuObject> res = ctor(this, aContent);
return Move(res);
}
size_t
nsMenuContainer::IndexOf(nsIContent* aChild) const {
if (!aChild) {
return NoIndex;
}
size_t count = ChildCount();
for (size_t i = 0; i < count; ++i) {
if (ChildAt(i)->ContentNode() == aChild) {
return i;
}
}
return NoIndex;
}
void
nsMenuContainer::RemoveChildAt(size_t aIndex, bool aUpdateNative) {
MOZ_ASSERT(aIndex < ChildCount());
if (aUpdateNative) {
MOZ_ALWAYS_TRUE(
dbusmenu_menuitem_child_delete(GetNativeData(),
ChildAt(aIndex)->GetNativeData()));
}
mChildren.RemoveElementAt(aIndex);
}
void
nsMenuContainer::RemoveChild(nsIContent* aChild, bool aUpdateNative) {
size_t index = IndexOf(aChild);
if (index == NoIndex) {
return;
}
RemoveChildAt(index, aUpdateNative);
}
void
nsMenuContainer::InsertChildAfter(UniquePtr<nsMenuObject> aChild,
nsIContent* aPrevSibling,
bool aUpdateNative) {
size_t index = IndexOf(aPrevSibling);
MOZ_ASSERT(!aPrevSibling || index != NoIndex);
++index;
if (aUpdateNative) {
aChild->CreateNativeData();
MOZ_ALWAYS_TRUE(
dbusmenu_menuitem_child_add_position(GetNativeData(),
aChild->GetNativeData(),
index));
}
MOZ_ALWAYS_TRUE(mChildren.InsertElementAt(index, Move(aChild)));
}
void
nsMenuContainer::AppendChild(UniquePtr<nsMenuObject> aChild,
bool aUpdateNative) {
if (aUpdateNative) {
aChild->CreateNativeData();
MOZ_ALWAYS_TRUE(
dbusmenu_menuitem_child_append(GetNativeData(),
aChild->GetNativeData()));
}
MOZ_ALWAYS_TRUE(mChildren.AppendElement(Move(aChild)));
}
bool
nsMenuContainer::NeedsRebuild() const {
return false;
}
/* static */ nsIContent*
nsMenuContainer::GetPreviousSupportedSibling(nsIContent* aContent) {
do {
aContent = aContent->GetPreviousSibling();
} while (aContent && !ContentIsSupported(aContent));
return aContent;
}