WebCore:
authorbdakin <bdakin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 2 Dec 2006 02:35:12 +0000 (02:35 +0000)
committerbdakin <bdakin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 2 Dec 2006 02:35:12 +0000 (02:35 +0000)
        Reviewed by Adam.

        Support for sub-menus in WebCore context menus. This also re-
        architects the ContextMenuItem class so that it is more like
        ContextMenu in that the class is now really just a wrapper for the
        platformDescription

        * WebCore.exp:
        * WebCore.xcodeproj/project.pbxproj:
        * page/ContextMenuController.cpp:
        (WebCore::ContextMenuController::contextMenuItemSelected): Add
        place-holders for new tags for the sub-menu items. I will flesh
        these out in a separate check-in.
        * platform/ContextMenu.cpp:
        (WebCore::createFontSubMenu):
        (WebCore::createSpellingAndGrammarSubMenu):
        (WebCore::createSpellingSubMenu):
        (WebCore::createSpeechSubMenu):
        (WebCore::createWritingDirectionSubMenu):
        (WebCore::ContextMenu::populate): Call the above functions to add
        the appropriate sub-menus to editing context menus.
        * platform/ContextMenu.h:
        * platform/ContextMenuItem.h:
        (WebCore::): New tags in the ContextMenuAction enumeration.
        (WebCore::ContextMenuItem::parentMenu):
        (WebCore::ContextMenuItem::setType):
        * platform/PlatformMenuDescription.h: Added. This defines
        PlatformMenuDesciption. It needs to be its own header because we
       have to include it from ContextMenu.h and ContextMenuItem.h
        * platform/mac/ContextMenuItemMac.mm: Lots of adjustments here to
        make this class basically just be a wrapper for NSMenuItem.
        (WebCore::ContextMenuItem::ContextMenuItem):
        (WebCore::ContextMenuItem::~ContextMenuItem):
        (WebCore::ContextMenuItem::platformDescription):
        (WebCore::ContextMenuItem::action):
        (WebCore::ContextMenuItem::title):
        (WebCore::ContextMenuItem::platformSubMenu):
        (WebCore::ContextMenuItem::setAction):
        (WebCore::ContextMenuItem::setTitle):
        (WebCore::ContextMenuItem::setSubMenu):
        * platform/mac/ContextMenuMac.mm:
        (WebCore::ContextMenu::ContextMenu):
        (WebCore::getNSMenuItem): Now we only have to get the
        platformDescription of the ContextMenuItem and then set its target
        and action.
        (WebCore::ContextMenu::itemCount):

WebKit:
        Reviewed by Adam.

        Changes to support sub-menus in WebCore ContextMenus.

        * WebCoreSupport/WebContextMenuClient.mm:
        (WebContextMenuClient::contextMenuItemSelected):
        ContextMenuItem::menu() is now called parentMenu()
        * WebView/WebUIDelegatePrivate.h: New not-yet-API tags.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@17984 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
WebCore/ChangeLog
WebCore/WebCore.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/page/ContextMenuController.cpp
WebCore/platform/ContextMenu.cpp
WebCore/platform/ContextMenu.h
WebCore/platform/ContextMenuItem.h
WebCore/platform/PlatformMenuDescription.h [new file with mode: 0644]
WebCore/platform/mac/ContextMenuItemMac.mm
WebCore/platform/mac/ContextMenuMac.mm
WebKit/ChangeLog
WebKit/WebCoreSupport/WebContextMenuClient.mm
WebKit/WebView/WebUIDelegatePrivate.h

index 1846b4e576647d698eaa1d0c31e299892a47bf5f..bd5012b1a99f18455fd14020e9fd7f4dd80470b2 100644 (file)
@@ -1,3 +1,52 @@
+2006-12-01  Beth Dakin  <bdakin@apple.com>
+
+        Reviewed by Adam.
+
+        Support for sub-menus in WebCore context menus. This also re-
+        architects the ContextMenuItem class so that it is more like
+        ContextMenu in that the class is now really just a wrapper for the
+        platformDescription
+
+        * WebCore.exp:
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/ContextMenuController.cpp:
+        (WebCore::ContextMenuController::contextMenuItemSelected): Add
+        place-holders for new tags for the sub-menu items. I will flesh
+        these out in a separate check-in.
+        * platform/ContextMenu.cpp:
+        (WebCore::createFontSubMenu):
+        (WebCore::createSpellingAndGrammarSubMenu):
+        (WebCore::createSpellingSubMenu):
+        (WebCore::createSpeechSubMenu):
+        (WebCore::createWritingDirectionSubMenu):
+        (WebCore::ContextMenu::populate): Call the above functions to add
+        the appropriate sub-menus to editing context menus.
+        * platform/ContextMenu.h:
+        * platform/ContextMenuItem.h:
+        (WebCore::): New tags in the ContextMenuAction enumeration.
+        (WebCore::ContextMenuItem::parentMenu):
+        (WebCore::ContextMenuItem::setType):
+        * platform/PlatformMenuDescription.h: Added. This defines
+        PlatformMenuDesciption. It needs to be its own header because we
+       have to include it from ContextMenu.h and ContextMenuItem.h
+        * platform/mac/ContextMenuItemMac.mm: Lots of adjustments here to
+        make this class basically just be a wrapper for NSMenuItem.
+        (WebCore::ContextMenuItem::ContextMenuItem):
+        (WebCore::ContextMenuItem::~ContextMenuItem):
+        (WebCore::ContextMenuItem::platformDescription):
+        (WebCore::ContextMenuItem::action):
+        (WebCore::ContextMenuItem::title):
+        (WebCore::ContextMenuItem::platformSubMenu):
+        (WebCore::ContextMenuItem::setAction):
+        (WebCore::ContextMenuItem::setTitle):
+        (WebCore::ContextMenuItem::setSubMenu):
+        * platform/mac/ContextMenuMac.mm:
+        (WebCore::ContextMenu::ContextMenu):
+        (WebCore::getNSMenuItem): Now we only have to get the
+        platformDescription of the ContextMenuItem and then set its target
+        and action.
+        (WebCore::ContextMenu::itemCount):
+
 2006-12-01  Kevin McCullough  <KMcCullough@apple.com>
 
         Reviewed by .
index d38d5fe07496e51f34eee254c749eca4ec03743b..53db8aef84c8dd6bb715e24831a1733393cee63a 100644 (file)
@@ -359,6 +359,7 @@ __ZNK7WebCore14DocumentLoader5titleEv
 __ZNK7WebCore14DocumentLoader8responseEv
 __ZNK7WebCore14DocumentLoader9isLoadingEv
 __ZNK7WebCore14ResourceLoader11frameLoaderEv
+__ZNK7WebCore15ContextMenuItem19platformDescriptionEv
 __ZNK7WebCore15ResourceRequest12nsURLRequestEv
 __ZNK7WebCore15ResourceRequest7isEmptyEv
 __ZNK7WebCore16DeprecatedString11getNSStringEv
index e7a37acd03cdcb033503446a83d86f130ab73dfc..2ac2ab50ab36f5a40cb1634b9e0f59b931c438f8 100644 (file)
                9326DC0B09DAD5BE00AFC847 /* CharsetData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9326DC0A09DAD5BE00AFC847 /* CharsetData.h */; };
                9326DC0C09DAD5D600AFC847 /* CharsetData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 656581AC09D14EE6000E61D7 /* CharsetData.cpp */; };
                9327A94209968D1A0068A546 /* HTMLOptionsCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9327A94109968D1A0068A546 /* HTMLOptionsCollection.cpp */; };
+               932871C00B20DEB70049035A /* PlatformMenuDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 932871BF0B20DEB70049035A /* PlatformMenuDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932CA7650AAA1DF500AD1FAD /* TextDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 932CA7640AAA1DF500AD1FAD /* TextDecoder.cpp */; };
                932CA7C10AAA20C100AD1FAD /* TextCodecLatin1.h in Headers */ = {isa = PBXBuildFile; fileRef = 932CA7C00AAA20C100AD1FAD /* TextCodecLatin1.h */; };
                932CA7C50AAA20D200AD1FAD /* TextCodecLatin1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 932CA7C40AAA20D200AD1FAD /* TextCodecLatin1.cpp */; };
                93126F6009D7A736008D9626 /* StringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringHash.h; sourceTree = "<group>"; };
                9326DC0A09DAD5BE00AFC847 /* CharsetData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharsetData.h; sourceTree = "<group>"; };
                9327A94109968D1A0068A546 /* HTMLOptionsCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLOptionsCollection.cpp; sourceTree = "<group>"; };
+               932871BF0B20DEB70049035A /* PlatformMenuDescription.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PlatformMenuDescription.h; sourceTree = "<group>"; };
                932CA7420AAA198E00AD1FAD /* TextDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextDecoder.h; sourceTree = "<group>"; };
                932CA7640AAA1DF500AD1FAD /* TextDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextDecoder.cpp; sourceTree = "<group>"; };
                932CA7C00AAA20C100AD1FAD /* TextCodecLatin1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCodecLatin1.h; sourceTree = "<group>"; };
                                A70023FC0B02BEAB00170215 /* MimeTypeRegistry.h */,
                                4B2708C50AF19EE40065127F /* Pasteboard.h */,
                                935C476609AC4D4300A6AAB4 /* PlatformKeyboardEvent.h */,
+                               932871BF0B20DEB70049035A /* PlatformMenuDescription.h */,
                                935C476709AC4D4300A6AAB4 /* PlatformMouseEvent.h */,
                                93CD4FEB0995FD2A007ECC97 /* PlatformString.h */,
                                935C476A09AC4D4F00A6AAB4 /* PlatformWheelEvent.h */,
                                4B8AF4AA0B1CE02B00687690 /* ClipboardAccessPolicy.h in Headers */,
                                06027CAD0B1CBFC000884B2D /* ContextMenuItem.h in Headers */,
                                B2310B770B1F46A200D55D87 /* CgSupport.h in Headers */,
+                               932871C00B20DEB70049035A /* PlatformMenuDescription.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        mainGroup = 0867D691FE84028FC02AAC07 /* WebKit */;
                        productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
                        projectDirPath = "";
-                       projectRoot = "";
                        targets = (
                                93F198A508245E59001E9ABC /* WebCore */,
                                DD041FBE09D9DDBE0010AF2A /* Derived Sources */,
index 4546ea354e3e608ef2b3ac5675915c48dfec5269..5bc77e65b4d540513c5dfe72563da2d58fa95bd6 100644 (file)
@@ -103,7 +103,7 @@ static String makeGoogleSearchURL(String searchString)
 
 void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
 {
-    ASSERT(item->menu() == contextMenu());
+    ASSERT(item->parentMenu() == contextMenu());
     ASSERT(item->type() == ActionType);
 
     if (item->action() >= ContextMenuItemBaseApplicationTag) {
@@ -213,17 +213,30 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
             // FIXME: Some day we may be able to do this from within WebCore.
             m_client->lookUpInDictionary(frame);
             break;
-        // PDF actions. Let's take care of this later. 
-        case ContextMenuItemTagOpenWithDefaultApplication:
-        case ContextMenuItemPDFActualSize:
-        case ContextMenuItemPDFZoomIn:
-        case ContextMenuItemPDFZoomOut:
-        case ContextMenuItemPDFAutoSize:
-        case ContextMenuItemPDFSinglePage:
-        case ContextMenuItemPDFFacingPages:
-        case ContextMenuItemPDFContinuous:
-        case ContextMenuItemPDFNextPage:
-        case ContextMenuItemPDFPreviousPage:
+        case ContextMenuItemTagOpenLink:
+        // Sub-menu actions.
+#ifndef BUILDING_ON_TIGER
+        case ContextMenuItemTagShowSpellingAndGrammar:
+        case ContextMenuItemTagCheckDocumentNow:
+        case ContextMenuItemTagCheckSpellingWhileTyping:
+        case ContextMenuItemTagCheckGrammarWithSpelling:
+#else
+        case ContextMenuItemTagSpellingMenuItem:
+        case ContextMenuItemTagCheckSpelling:
+        case ContextMenuItemTagCheckSpellingWhileTyping:
+#endif
+        case ContextMenuItemTagShowFonts:
+        case ContextMenuItemTagBold:
+        case ContextMenuItemTagItalic:
+        case ContextMenuItemTagUnderline:
+        case ContextMenuItemTagOutline:
+        case ContextMenuItemTagStyles:
+        case ContextMenuItemTagShowColors:
+        case ContextMenuItemTagStartSpeaking:
+        case ContextMenuItemTagStopSpeaking:
+        case ContextMenuItemTagDefaultDirection:
+        case ContextMenuItemTagLeftToRight:
+        case ContextMenuItemTagRightToLeft:
         default:
             break;
     }
index 249240d6448a1b5f9f6506891ba925180b21fef7..89f5b4a5b4a6289c31afdff04d6acde991fb4f27 100644 (file)
@@ -49,6 +49,86 @@ ContextMenuController* ContextMenu::controller() const
     return 0;
 }
 
+static void createFontSubMenu(const HitTestResult& result, ContextMenuItem& fontMenuItem)
+{
+    static ContextMenuItem SeparatorItem(SeparatorType, ContextMenuItemTagNoAction, String());
+
+    MENU_ACTION_ITEM(ShowFonts, "Show Fonts");
+    MENU_ACTION_ITEM(Bold, "Bold");
+    MENU_ACTION_ITEM(Italic, "Italic");
+    MENU_ACTION_ITEM(Underline, "Underline");
+    MENU_ACTION_ITEM(Outline, "Outline");
+    MENU_ACTION_ITEM(Styles, "Styles...");
+    MENU_ACTION_ITEM(ShowColors, "Show Colors");
+    
+    ContextMenu* fontMenu = new ContextMenu(result);
+    fontMenu->appendItem(ShowFontsItem);
+    fontMenu->appendItem(BoldItem);
+    fontMenu->appendItem(ItalicItem);
+    fontMenu->appendItem(UnderlineItem);
+    fontMenu->appendItem(OutlineItem);
+    fontMenu->appendItem(StylesItem);
+    fontMenu->appendItem(SeparatorItem);
+    fontMenu->appendItem(ShowColorsItem);
+    fontMenuItem.setSubMenu(fontMenu);
+}
+
+#ifndef BUILDING_ON_TIGER
+static void createSpellingAndGrammarSubMenu(const HitTestResult& result, ContextMenuItem& spellingAndGrammarMenuItem)
+{
+    MENU_ACTION_ITEM(ShowSpellingAndGrammar, "Show Spelling and Grammar");
+    MENU_ACTION_ITEM(CheckDocumentNow, "Check Document Now");
+    MENU_ACTION_ITEM(CheckSpellingWhileTyping, "Check Spelling While Typing");
+    MENU_ACTION_ITEM(CheckGrammarWithSpelling, "Check Grammar With Spelling");
+
+    ContextMenu* spellingAndGrammarMenu = new ContextMenu(result);
+    spellingAndGrammarMenu->appendItem(ShowSpellingAndGrammarItem);
+    spellingAndGrammarMenu->appendItem(CheckDocumentNowItem);
+    spellingAndGrammarMenu->appendItem(CheckSpellingWhileTypingItem);
+    spellingAndGrammarMenu->appendItem(CheckGrammarWithSpellingItem);
+    spellingAndGrammarMenuItem.setSubMenu(spellingAndGrammarMenu);
+}
+#else
+static void createSpellingSubMenu(const HitTestResult& result, ContextMenuItem& spellingMenuItem)
+{
+    MENU_ACTION_ITEM(SpellingMenuItem, "Spelling...");
+    MENU_ACTION_ITEM(CheckSpelling, "Check Spelling");
+    MENU_ACTION_ITEM(CheckSpellingWhileTyping, "Check Spelling as You Type");
+
+    ContextMenu* spellingMenu = new ContextMenu(result);
+    spellingMenu->appendItem(SpellingMenuItemItem);
+    spellingMenu->appendItem(CheckSpellingItem);
+    spellingMenu->appendItem(CheckSpellingWhileTypingItem);
+    spellingMenuItem.setSubMenu(spellingMenu);
+}
+#endif
+
+#if PLATFORM(MAC)
+static void createSpeechSubMenu(const HitTestResult& result, ContextMenuItem& speechMenuItem)
+{
+    MENU_ACTION_ITEM(StartSpeaking, "Start Speaking");
+    MENU_ACTION_ITEM(StopSpeaking, "Stop Speaking");
+
+    ContextMenu* speechMenu = new ContextMenu(result);
+    speechMenu->appendItem(StartSpeakingItem);
+    speechMenu->appendItem(StopSpeakingItem);
+    speechMenuItem.setSubMenu(speechMenu);
+}
+#endif
+
+static void createWritingDirectionSubMenu(const HitTestResult& result, ContextMenuItem& writingDirectionMenuItem)
+{
+    MENU_ACTION_ITEM(DefaultDirection, "Default");
+    MENU_ACTION_ITEM(LeftToRight, "Left to Right");
+    MENU_ACTION_ITEM(RightToLeft, "Right to Left");
+
+    ContextMenu* writingDirectionMenu = new ContextMenu(result);
+    writingDirectionMenu->appendItem(DefaultDirectionItem);
+    writingDirectionMenu->appendItem(LeftToRightItem);
+    writingDirectionMenu->appendItem(RightToLeftItem);
+    writingDirectionMenuItem.setSubMenu(writingDirectionMenu);
+}
+
 void ContextMenu::populate()
 {
     static ContextMenuItem SeparatorItem(SeparatorType, ContextMenuItemTagNoAction, String());
@@ -76,7 +156,7 @@ void ContextMenu::populate()
 #endif
     MENU_ACTION_ITEM(SearchWeb, "Search in Google");
     MENU_ACTION_ITEM(LookUpInDictionary, "Look Up in Dictionary");
-    // FIXME: Add PDF action items
+    MENU_ACTION_ITEM(OpenLink, "Open Link");
 
     HitTestResult result = hitTestResult();
     
@@ -92,6 +172,7 @@ void ContextMenu::populate()
         KURL linkURL = result.absoluteLinkURL();
         if (!linkURL.isEmpty()) {
             if (loader->canHandleRequest(ResourceRequest(linkURL))) {
+                appendItem(OpenLinkItem);
                 appendItem(OpenLinkInNewWindowItem);
                 appendItem(DownloadLinkToDiskItem);
             }
@@ -171,12 +252,36 @@ void ContextMenu::populate()
             appendItem(LookUpInDictionaryItem);
             appendItem(SeparatorItem);
         }
-        
+
         appendItem(CutItem);
         appendItem(CopyItem);
         appendItem(PasteItem);
 
-        // FIXME: Add a separator, then "Spelling [and Grammar, on Leopard]", "Font", "Speech", "Writing Direction" submenus here.
+        if (!inPasswordField) {
+            appendItem(SeparatorItem);
+#ifndef BUILDING_ON_TIGER
+            ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingAndGrammarMenu,
+                "Spelling and Grammar");
+            createSpellingAndGrammarSubMenu(m_hitTestResult, SpellingAndGrammarMenuItem);
+            appendItem(SpellingAndGrammarMenuItem);
+#else
+            ContextMenuItem SpellingMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, "Spelling");
+            createSpellingSubMenu(m_hitTestResult, SpellingMenuItem);
+            appendItem(SpellingMenuItem);
+#endif
+            ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu, "Font");
+            createFontSubMenu(m_hitTestResult, FontMenuItem);
+            appendItem(FontMenuItem);
+#if PLATFORM(MAC)
+            ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, "Speech");
+            createSpeechSubMenu(m_hitTestResult, SpeechMenuItem);
+            appendItem(SpeechMenuItem);
+#endif
+            ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu,
+                "Writing Direction");
+            createWritingDirectionSubMenu(m_hitTestResult, WritingDirectionMenuItem);
+            appendItem(WritingDirectionMenuItem);
+        }
     }
 }
 
index 0552d405d46621f2e83aac67ef4c5fa8715a8c04..603176e116df41249e98df4cc366b642f76508a1 100644 (file)
 
 #include "ContextMenuItem.h"
 #include "HitTestResult.h"
+#include "PlatformMenuDescription.h"
 #include "PlatformString.h"
 #if PLATFORM(MAC)
 #include "RetainPtr.h"
 #endif
 
-#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class NSMutableArray;
-#else
-class NSMutableArray;
-#endif
-#elif PLATFORM(WIN)
-typedef struct HMENU__* HMENU;
-#elif PLATFORM(QT)
-class QMenu;
-#endif
-
 namespace WebCore {
 
     class ContextMenuController;
 
-#if PLATFORM(MAC)
-    typedef NSMutableArray* PlatformMenuDescription;
-#elif PLATFORM(WIN)
-    typedef HMENU PlatformMenuDescription;
-#elif PLATFORM(QT)
-    typedef QMenu* PlatformMenuDescription;
-#endif
-
     class ContextMenu : Noncopyable
     {
     public:
         ContextMenu(const HitTestResult&);
+        ContextMenu(const HitTestResult&, const PlatformMenuDescription);
         ~ContextMenu();
 
         void populate();
index 7fe02869487569c08f5a11cc131f4bf04aa9903b..d67d0b76993aef10013b386bff771e2afbaaaafb 100644 (file)
@@ -28,7 +28,9 @@
 
 #include <wtf/Noncopyable.h>
 
+#include "PlatformMenuDescription.h"
 #include "PlatformString.h"
+#include "RetainPtr.h"
 
 #if PLATFORM(MAC)
 #ifdef __OBJC__
@@ -88,7 +90,36 @@ namespace WebCore {
         ContextMenuItemPDFContinuous,
         ContextMenuItemPDFNextPage,
         ContextMenuItemPDFPreviousPage,
-        ContextMenuItemBaseApplicationTag = 1000
+        // These are new tags! Not a part of API!!!!
+        ContextMenuItemTagOpenLink = 1000,
+#ifndef BUILDING_ON_TIGER
+        ContextMenuItemTagSpellingAndGrammarMenu, // Spelling sub-menu
+        ContextMenuItemTagShowSpellingAndGrammar,
+        ContextMenuItemTagCheckDocumentNow,
+        ContextMenuItemTagCheckSpellingWhileTyping,
+        ContextMenuItemTagCheckGrammarWithSpelling,
+#else
+        ContextMenuItemTagSpellingMenu, // Tiger Spelling sub-menu
+        ContextMenuItemTagSpellingMenuItem,
+        ContextMenuItemTagCheckSpelling,
+        ContextMenuItemTagCheckSpellingWhileTyping,
+#endif
+        ContextMenuItemTagFontMenu, // Font sub-menu
+        ContextMenuItemTagShowFonts,
+        ContextMenuItemTagBold,
+        ContextMenuItemTagItalic,
+        ContextMenuItemTagUnderline,
+        ContextMenuItemTagOutline,
+        ContextMenuItemTagStyles,
+        ContextMenuItemTagShowColors,
+        ContextMenuItemTagSpeechMenu, // Speech sub-menu
+        ContextMenuItemTagStartSpeaking,
+        ContextMenuItemTagStopSpeaking,
+        ContextMenuItemTagWritingDirectionMenu, // Writing Direction sub-menu
+        ContextMenuItemTagDefaultDirection,
+        ContextMenuItemTagLeftToRight,
+        ContextMenuItemTagRightToLeft,
+        ContextMenuItemBaseApplicationTag = 10000
     };
 
     enum ContextMenuItemType {
@@ -100,42 +131,36 @@ namespace WebCore {
     class ContextMenuItem : Noncopyable {
     public:
         ContextMenuItem(PlatformMenuItemDescription, ContextMenu*);
-
-        ContextMenuItem(ContextMenu* menu = 0)
-            : m_menu(menu)
-            , m_platformDescription(0)
-            , m_type(SeparatorType)
-            , m_action(ContextMenuItemTagNoAction)
-            , m_title(String())
-        {
-        }
-
-        ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* menu = 0)
-            : m_menu(menu)
-            , m_platformDescription(0)
-            , m_type(type)
-            , m_action(action)
-            , m_title(title)
-        {
-        }
-
+        ContextMenuItem(ContextMenu* parentMenu = 0, ContextMenu* subMenu = 0);
+        ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* parentMenu = 0, 
+            ContextMenu* subMenu = 0);
         ~ContextMenuItem();
 
-        ContextMenu* menu() const { return m_menu; }
-        const PlatformMenuItemDescription platformDescription() const { return m_platformDescription; }
+        ContextMenu* parentMenu() const { return m_parentMenu; }
+        PlatformMenuItemDescription platformDescription() const;
+
         ContextMenuItemType type() const { return m_type; }
-        ContextMenuAction action() const { return m_action; }
-        String title() const { return m_title; }
+        void setType(ContextMenuItemType type) { m_type = type; }
+
+        ContextMenuAction action() const;
+        void setAction(ContextMenuAction action);
+
+        String title() const;
+        void setTitle(String title);
+
+        PlatformMenuDescription platformSubMenu() const;
+        void setSubMenu(ContextMenu* subMenu);
 
-        // FIXME: Need to support submenus (perhaps a Vector<ContextMenuItem>*?)
         // FIXME: Do we need a keyboard accelerator here?
 
     private:
-        ContextMenu* m_menu;
+        ContextMenu* m_parentMenu;
+#if PLATFORM(MAC)
+        RetainPtr<NSMenuItem> m_platformDescription;
+#else
         PlatformMenuItemDescription m_platformDescription;
+#endif
         ContextMenuItemType m_type;
-        ContextMenuAction m_action;
-        String m_title;
     };
 
 }
diff --git a/WebCore/platform/PlatformMenuDescription.h b/WebCore/platform/PlatformMenuDescription.h
new file mode 100644 (file)
index 0000000..3755f50
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PlatformMenuDescription_h
+#define PlatformMenuDescription_h
+
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+@class NSMutableArray;
+#else
+class NSMutableArray;
+#endif
+#elif PLATFORM(WIN)
+typedef struct HMENU__* HMENU;
+#elif PLATFORM(QT)
+class QMenu;
+#endif
+
+namespace WebCore {
+
+#if PLATFORM(MAC)
+    typedef NSMutableArray* PlatformMenuDescription;
+#elif PLATFORM(WIN)
+    typedef HMENU PlatformMenuDescription;
+#elif PLATFORM(QT)
+    typedef QMenu* PlatformMenuDescription;
+#endif
+
+} // namespace
+
+#endif // PlatformMenuDescription_h
index 3a4f2b5bf8aad90c172eb0c6f7c67d6e13b03e18..439ca9ed6321e1c6a939a37146109776ee4c5fa9 100644 (file)
 #include "config.h"
 #include "ContextMenuItem.h"
 
+#include "ContextMenu.h"
+
 namespace WebCore {
-    
-ContextMenuItem::ContextMenuItem(NSMenuItem* item, ContextMenu* menu)
-    : m_menu(menu)
-    , m_platformDescription([item retain])
+
+ContextMenuItem::ContextMenuItem(NSMenuItem* item, ContextMenu* parentMenu)
+    : m_parentMenu(parentMenu)
+    , m_platformDescription(item)
 {
-    if ([item isSeparatorItem]) {
+    if ([item isSeparatorItem])
         m_type = SeparatorType;
-        m_title = String();
-        m_action = ContextMenuItemTagNoAction;
-    } else {
+    else if ([item hasSubmenu])
+        m_type = SubmenuType;
+    else
         m_type = ActionType;
-        m_title = [item title];
-        ASSERT([item tag] >= 0);
-        m_action = static_cast<ContextMenuAction>([item tag]);
-    }
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenu* parentMenu, ContextMenu* subMenu)
+    : m_parentMenu(parentMenu)
+    , m_type(SeparatorType)
+{
+    NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:String() action:nil keyEquivalent:nil];
+    m_platformDescription = item;
+    [item release];
+
+    [m_platformDescription.get() setTag:ContextMenuItemTagNoAction];
+    if (subMenu)
+        setSubMenu(subMenu);
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* parentMenu, 
+    ContextMenu* subMenu)
+    : m_parentMenu(parentMenu)
+    , m_type(type)
+{
+    NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:nil];
+    m_platformDescription = item;
+    [item release];
+
+    [m_platformDescription.get() setTag:action];
+    if (subMenu)
+        setSubMenu(subMenu);
 }
 
 ContextMenuItem::~ContextMenuItem()
 {
-    [m_platformDescription release];
+}
+
+PlatformMenuItemDescription ContextMenuItem::platformDescription() const
+{
+    return m_platformDescription.get();
+}
+
+ContextMenuAction ContextMenuItem::action() const
+{ 
+    return static_cast<ContextMenuAction>([m_platformDescription.get() tag]);
+}
+
+String ContextMenuItem::title() const 
+{
+    return [m_platformDescription.get() title];
+}
+
+NSMutableArray* ContextMenuItem::platformSubMenu() const
+{
+    if (![m_platformDescription.get() hasSubmenu])
+        return nil;
+
+    NSMenu* subMenu = [m_platformDescription.get() submenu];
+    NSMutableArray* itemsArray = [NSMutableArray array];
+    int total = [subMenu numberOfItems];
+    for (int i = 0; i < total; i++)
+        [itemsArray addObject:[subMenu itemAtIndex:i]];
+
+    return itemsArray;
+}
+
+void ContextMenuItem::setAction(ContextMenuAction action)
+{
+    [m_platformDescription.get() setTag:action]; 
+}
+
+void ContextMenuItem::setTitle(String title)
+{
+    [m_platformDescription.get() setTitle:title];
+}
+
+void ContextMenuItem::setSubMenu(ContextMenu* menu)
+{
+    NSArray* subMenuArray = menu->platformDescription();
+    NSMenu* subMenu = [[NSMenu alloc] init];
+    for (unsigned i = 0; i < [subMenuArray count]; i++)
+        [subMenu insertItem:[subMenuArray objectAtIndex:i] atIndex:i];
+    [m_platformDescription.get() setSubmenu:subMenu];
+    [subMenu release];
 }
 
 }
index ce421200e19d0a79bc8e55764d253c85274bf4a9..c6a7011dddb67410522e10847abab1765ba423eb 100644 (file)
@@ -78,6 +78,12 @@ ContextMenu::ContextMenu(const HitTestResult& result)
     [array release];    
 }
 
+ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
+    : m_hitTestResult(result)
+    , m_platformDescription(menu)
+{
+}
+
 ContextMenu::~ContextMenu()
 {
 }
@@ -93,23 +99,12 @@ static NSMenuItem* getNSMenuItem(ContextMenu* menu, const ContextMenuItem& item)
     else if (currentController != [target menuController])
         [target setMenuController:currentController];
     
-    NSMenuItem* menuItem = 0;
-    switch (item.type()) {
-        case ActionType:
-            menuItem = [[NSMenuItem alloc] init];
-            [menuItem setTag:item.action()];
-            [menuItem setTitle:item.title()];
-            [menuItem setTarget:target];
-            [menuItem setAction:@selector(forwardContextMenuAction:)];
-            break;
-        case SeparatorType:
-            menuItem = [[NSMenuItem separatorItem] retain];
-            break;
-        default:
-            ASSERT_NOT_REACHED();
-            break;
+    NSMenuItem* menuItem = item.platformDescription();
+    if (item.type() == ActionType) {
+        [menuItem setTarget:target];
+        [menuItem setAction:@selector(forwardContextMenuAction:)];
     }
-    
+
     return menuItem;
 }
 
@@ -123,11 +118,6 @@ void ContextMenu::appendItem(const ContextMenuItem& item)
     [menuItem release];
 }
 
-unsigned ContextMenu::itemCount() const
-{
-    return [m_platformDescription.get() count];
-}
-
 void ContextMenu::insertItem(unsigned position, const ContextMenuItem& item)
 {
     NSMenuItem* menuItem = getNSMenuItem(this, item);
@@ -138,6 +128,11 @@ void ContextMenu::insertItem(unsigned position, const ContextMenuItem& item)
     [menuItem release];
 }
 
+unsigned ContextMenu::itemCount() const
+{
+    return [m_platformDescription.get() count];
+}
+
 void ContextMenu::setPlatformDescription(NSMutableArray* menu)
 {
     if (m_platformDescription.get() != menu)
index 9f58cd10deb1aa98a5117d2e298df7384bc1f959..b9b24c2f7931f49d5ed6a5fb53aaeb38c219fc5f 100644 (file)
@@ -1,3 +1,14 @@
+2006-12-01  Beth Dakin  <bdakin@apple.com>
+
+        Reviewed by Adam.
+
+        Changes to support sub-menus in WebCore ContextMenus.
+
+        * WebCoreSupport/WebContextMenuClient.mm:
+        (WebContextMenuClient::contextMenuItemSelected): 
+        ContextMenuItem::menu() is now called parentMenu()
+        * WebView/WebUIDelegatePrivate.h: New not-yet-API tags.
+
 2006-12-01  Darin Adler  <darin@apple.com>
 
         Reviewed by Mitz.
index 2a7e6f23d9ee33dd652b9b60913977a4052b00b4..1c92df5db0f1e0c423d4831cea6bfa95616fff64 100644 (file)
@@ -65,11 +65,11 @@ void WebContextMenuClient::addCustomContextMenuItems(ContextMenu* menu)
 
 void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item)
 {
-    ASSERT(item->menu());
+    ASSERT(item->parentMenu());
     
     id delegate = [m_webView UIDelegate];
     if ([delegate respondsToSelector:@selector(webView:contextMenuItemSelected:forElement:)]) {
-        NSDictionary *element = [[[WebElementDictionary alloc] initWithHitTestResult:item->menu()->hitTestResult()] autorelease];
+        NSDictionary *element = [[[WebElementDictionary alloc] initWithHitTestResult:item->parentMenu()->hitTestResult()] autorelease];
         [delegate webView:m_webView contextMenuItemSelected:item->platformDescription() forElement:element];
     }
 }
index 8224858617e15c9f1c5f0ec6dd6697c34323e755..26c0c8872d35709cf5919684218c19ab3baace93 100644 (file)
 
 #import <WebKit/WebUIDelegate.h>
 
-// FIXME: This should move to WebUIDelegate.h as part of the WebMenuItemTag enum there, when we're not in API freeze 
+// FIXME: These should move to WebUIDelegate.h as part of the WebMenuItemTag enum there, when we're not in API freeze 
 enum { 
-    WebMenuItemTagOpenLink = 1000
+    WebMenuItemTagOpenLink = 1000,
+#ifndef BUILDING_ON_TIGER
+    WebMenuItemTagSpellingAndGrammarMenu,
+    WebMenuItemTagShowSpellingAndGrammar,
+    WebMenuItemTagCheckDocumentNow,
+    WebMenuItemTagCheckSpellingWhileTyping,
+    WebMenuItemTagCheckGrammarWithSpelling,
+#else
+    WebMenuItemTagSpellingMenu,
+    WebMenuItemTagSpellingMenuItem,
+    WebMenuItemTagCheckSpelling,
+    WebMenuItemTagCheckSpellingWhileTyping,
+#endif
+    WebMenuItemTagFontMenu,
+    WebMenuItemTagShowFonts,
+    WebMenuItemTagBold,
+    WebMenuItemTagItalic,
+    WebMenuItemTagUnderline,
+    WebMenuItemTagOutline,
+    WebMenuItemTagStyles,
+    WebMenuItemTagShowColors,
+    WebMenuItemTagSpeechMenu,
+    WebMenuItemTagStartSpeaking,
+    WebMenuItemTagStopSpeaking,
+    WebMenuItemTagWritingDirectionMenu,
+    WebMenuItemTagDefaultDirection,
+    WebMenuItemTagLeftToRight,
+    WebMenuItemTagRightToLeft,
+    WebMenuItemTagBaseApplication = 10000
 };
 
 @interface NSObject (WebUIDelegatePrivate)