summaryrefslogtreecommitdiffstats
path: root/widget/gtk/nsMenuContainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gtk/nsMenuContainer.cpp')
-rw-r--r--widget/gtk/nsMenuContainer.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/widget/gtk/nsMenuContainer.cpp b/widget/gtk/nsMenuContainer.cpp
new file mode 100644
index 000000000..081e98a6a
--- /dev/null
+++ b/widget/gtk/nsMenuContainer.cpp
@@ -0,0 +1,156 @@
+/* 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;
+}