249240d6448a1b5f9f6506891ba925180b21fef7
[WebKit-https.git] / WebCore / platform / ContextMenu.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "ContextMenu.h"
28
29 #include "ContextMenuController.h"
30 #include "Document.h"
31 #include "Frame.h"
32 #include "FrameLoader.h"
33 #include "KURL.h"
34 #include "Node.h"
35 #include "Page.h"
36 #include "ResourceRequest.h"
37 #include "SelectionController.h"
38
39 namespace WebCore {
40
41 #define MENU_ACTION_ITEM(action, title) static ContextMenuItem action##Item(ActionType, ContextMenuItemTag##action, String(title))
42
43 ContextMenuController* ContextMenu::controller() const
44 {
45     if (Node* node = m_hitTestResult.innerNonSharedNode())
46         if (Frame* frame = node->document()->frame())
47             if (Page* page = frame->page())
48                 return page->contextMenuController();
49     return 0;
50 }
51
52 void ContextMenu::populate()
53 {
54     static ContextMenuItem SeparatorItem(SeparatorType, ContextMenuItemTagNoAction, String());
55
56     MENU_ACTION_ITEM(OpenLinkInNewWindow, "Open Link in New Window");
57     MENU_ACTION_ITEM(DownloadLinkToDisk, "Download Linked File");
58     MENU_ACTION_ITEM(CopyLinkToClipboard, "Copy Link");
59     MENU_ACTION_ITEM(OpenImageInNewWindow, "Open Image in New Window");
60     MENU_ACTION_ITEM(DownloadImageToDisk, "Download Image");
61     MENU_ACTION_ITEM(CopyImageToClipboard, "Copy Image");
62     MENU_ACTION_ITEM(OpenFrameInNewWindow, "Open Frame in New Window");
63     MENU_ACTION_ITEM(Copy, "Copy");
64     MENU_ACTION_ITEM(GoBack, "Back");
65     MENU_ACTION_ITEM(GoForward, "Forward");
66     MENU_ACTION_ITEM(Stop, "Stop");
67     MENU_ACTION_ITEM(Reload, "Reload");
68     MENU_ACTION_ITEM(Cut, "Cut");
69     MENU_ACTION_ITEM(Paste, "Paste");
70     MENU_ACTION_ITEM(SpellingGuess, "");
71     MENU_ACTION_ITEM(NoGuessesFound, "No Guesses Found");
72     MENU_ACTION_ITEM(IgnoreSpelling, "Ignore Spelling");
73     MENU_ACTION_ITEM(LearnSpelling, "Learn Spelling");
74 #if PLATFORM(MAC)
75     MENU_ACTION_ITEM(SearchInSpotlight, "Search in Spotlight");
76 #endif
77     MENU_ACTION_ITEM(SearchWeb, "Search in Google");
78     MENU_ACTION_ITEM(LookUpInDictionary, "Look Up in Dictionary");
79     // FIXME: Add PDF action items
80
81     HitTestResult result = hitTestResult();
82     
83     Node* node = m_hitTestResult.innerNonSharedNode();
84     if (!node)
85         return;
86     Frame* frame = node->document()->frame();
87     if (!frame)
88         return;
89
90     if (!result.isContentEditable()) {
91         FrameLoader* loader = frame->loader();
92         KURL linkURL = result.absoluteLinkURL();
93         if (!linkURL.isEmpty()) {
94             if (loader->canHandleRequest(ResourceRequest(linkURL))) {
95                 appendItem(OpenLinkInNewWindowItem);
96                 appendItem(DownloadLinkToDiskItem);
97             }
98             appendItem(CopyLinkToClipboardItem);
99         }
100
101         KURL imageURL = result.absoluteImageURL();
102         if (!imageURL.isEmpty()) {
103             if (!linkURL.isEmpty())
104                 appendItem(SeparatorItem);
105
106             appendItem(OpenImageInNewWindowItem);
107             appendItem(DownloadImageToDiskItem);
108             if (imageURL.isLocalFile()) // FIXME: Should be checking if the image is local or we have a file wrapper for it
109                 appendItem(CopyImageToClipboardItem);
110         }
111
112         if (imageURL.isEmpty() && linkURL.isEmpty()) {
113             if (result.isSelected()) {
114 #if PLATFORM(MAC)
115                 appendItem(SearchInSpotlightItem);
116 #endif
117                 appendItem(SearchWebItem);
118                 appendItem(SeparatorItem);
119                 appendItem(LookUpInDictionaryItem);
120                 appendItem(SeparatorItem);
121                 appendItem(CopyItem);
122             } else {
123                 if (loader->canGoBackOrForward(-1))
124                     appendItem(GoBackItem);
125
126                 if (loader->canGoBackOrForward(1))
127                     appendItem(GoForwardItem);
128                 
129                 if (loader->isLoading())
130                     appendItem(StopItem);
131                 else
132                     appendItem(ReloadItem);
133
134                 if (frame->page() && frame != frame->page()->mainFrame())
135                     appendItem(OpenFrameInNewWindowItem);
136             }
137         }
138     } else { // Make an editing context menu
139         SelectionController* selectionController = frame->selectionController();
140         bool inPasswordField = selectionController->isInPasswordField();
141
142         // Add spelling-related context menu items.
143         if (frame->isSelectionMisspelled() && !inPasswordField) {
144             Vector<String> guesses = frame->guessesForMisspelledSelection();
145             unsigned size = guesses.size();
146             if (size == 0)
147                 appendItem(NoGuessesFoundItem);
148             else {
149                 for (unsigned i = 0; i < size; i++) {
150                     String guess = guesses[i];
151                     if (!guess.isNull()) {
152                         ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
153                         appendItem(item);
154                     }
155                 }
156             }                
157
158             appendItem(SeparatorItem);
159             appendItem(IgnoreSpellingItem);
160             appendItem(LearnSpellingItem);
161             appendItem(SeparatorItem);
162         }
163
164         if (result.isSelected() && !inPasswordField) {
165 #if PLATFORM(MAC)
166             appendItem(SearchInSpotlightItem);
167 #endif
168             appendItem(SearchWebItem);
169             appendItem(SeparatorItem);
170      
171             appendItem(LookUpInDictionaryItem);
172             appendItem(SeparatorItem);
173         }
174         
175         appendItem(CutItem);
176         appendItem(CopyItem);
177         appendItem(PasteItem);
178
179         // FIXME: Add a separator, then "Spelling [and Grammar, on Leopard]", "Font", "Speech", "Writing Direction" submenus here.
180     }
181 }
182
183 }