1/*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#include "config.h"
23#include "WebPopupMenu.h"
24
25#include "PlatformPopupMenuData.h"
26#include "WebCoreArgumentCoders.h"
27#include "WebPage.h"
28#include "WebPageProxyMessages.h"
29#include "WebProcess.h"
30#include <WebCore/FrameView.h>
31#include <WebCore/PopupMenuClient.h>
32
33using namespace WebCore;
34
35namespace WebKit {
36
37PassRefPtr<WebPopupMenu> WebPopupMenu::create(WebPage* page, PopupMenuClient* client)
38{
39    return adoptRef(new WebPopupMenu(page, client));
40}
41
42WebPopupMenu::WebPopupMenu(WebPage* page, PopupMenuClient* client)
43    : m_popupClient(client)
44    , m_page(page)
45{
46}
47
48WebPopupMenu::~WebPopupMenu()
49{
50}
51
52void WebPopupMenu::disconnectClient()
53{
54    m_popupClient = 0;
55}
56
57void WebPopupMenu::didChangeSelectedIndex(int newIndex)
58{
59    if (!m_popupClient)
60        return;
61
62    m_popupClient->popupDidHide();
63    if (newIndex >= 0)
64        m_popupClient->valueChanged(newIndex);
65}
66
67void WebPopupMenu::setTextForIndex(int index)
68{
69    if (!m_popupClient)
70        return;
71
72    m_popupClient->setTextFromItem(index);
73}
74
75Vector<WebPopupItem> WebPopupMenu::populateItems()
76{
77    size_t size = m_popupClient->listSize();
78
79    Vector<WebPopupItem> items;
80    items.reserveInitialCapacity(size);
81
82    for (size_t i = 0; i < size; ++i) {
83        if (m_popupClient->itemIsSeparator(i))
84            items.append(WebPopupItem(WebPopupItem::Separator));
85        else {
86            // FIXME: Add support for styling the font.
87            // FIXME: Add support for styling the foreground and background colors.
88            // FIXME: Find a way to customize text color when an item is highlighted.
89            PopupMenuStyle itemStyle = m_popupClient->itemStyle(i);
90            items.append(WebPopupItem(WebPopupItem::Item, m_popupClient->itemText(i), itemStyle.textDirection(), itemStyle.hasTextDirectionOverride(), m_popupClient->itemToolTip(i), m_popupClient->itemAccessibilityText(i), m_popupClient->itemIsEnabled(i), m_popupClient->itemIsLabel(i)));
91        }
92    }
93
94    return items;
95}
96
97void WebPopupMenu::show(const IntRect& rect, FrameView* view, int index)
98{
99    // FIXME: We should probably inform the client to also close the menu.
100    Vector<WebPopupItem> items = populateItems();
101
102    if (items.isEmpty() || !m_page) {
103        m_popupClient->popupDidHide();
104        return;
105    }
106
107    m_page->setActivePopupMenu(this);
108
109    // Move to page coordinates
110    IntRect pageCoordinates(view->contentsToWindow(rect.location()), rect.size());
111
112    PlatformPopupMenuData platformData;
113    setUpPlatformData(pageCoordinates, platformData);
114
115    WebProcess::shared().connection()->send(Messages::WebPageProxy::ShowPopupMenu(pageCoordinates, m_popupClient->menuStyle().textDirection(), items, index, platformData), m_page->pageID());
116}
117
118void WebPopupMenu::hide()
119{
120    if (!m_page || !m_popupClient)
121        return;
122
123    WebProcess::shared().connection()->send(Messages::WebPageProxy::HidePopupMenu(), m_page->pageID());
124    m_page->setActivePopupMenu(0);
125}
126
127void WebPopupMenu::updateFromElement()
128{
129#if PLATFORM(WIN)
130    if (!m_page || !m_popupClient)
131        return;
132
133    int selectedIndex = m_popupClient->selectedIndex();
134    WebProcess::shared().connection()->send(Messages::WebPageProxy::SetPopupMenuSelectedIndex(selectedIndex), m_page->pageID());
135#endif
136}
137
138} // namespace WebKit
139