1/*
2 * This file is part of the popup menu implementation for <select> elements in WebCore.
3 *
4 * Copyright (C) 2008 Apple Computer, Inc.
5 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB.  If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "PopupMenuWx.h"
26
27#include "Frame.h"
28#include "FrameView.h"
29#include "PopupMenuClient.h"
30#include "PlatformString.h"
31
32#include <wx/defs.h>
33#if __WXMSW__
34#include <wx/msw/winundef.h>
35#endif
36#include <wx/event.h>
37#include <wx/menu.h>
38
39static int s_menuStartId = wxNewId();
40
41namespace WebCore {
42
43class PopupMenuEventHandler : public wxEvtHandler
44{
45public:
46    PopupMenuEventHandler(PopupMenuClient* client) :
47        m_client(client)
48    {}
49
50    void OnMenuItemSelected(wxCommandEvent& event)
51    {
52        if (m_client) {
53            m_client->valueChanged(event.GetId() - s_menuStartId);
54            m_client->popupDidHide();
55        }
56        // TODO: Do we need to call Disconnect here? Do we have a ref to the native window still?
57    }
58
59private:
60    PopupMenuClient* m_client;
61
62};
63
64PopupMenuWx::PopupMenuWx(PopupMenuClient* client)
65    : m_popupClient(client)
66    , m_menu(0)
67{
68    PopupMenuEventHandler m_popupHandler(client);
69}
70
71PopupMenuWx::~PopupMenuWx()
72{
73    delete m_menu;
74}
75
76void PopupMenuWx::disconnectClient()
77{
78    m_popupClient = 0;
79}
80
81void PopupMenuWx::show(const IntRect& r, FrameView* v, int index)
82{
83    // just delete and recreate
84    delete m_menu;
85    ASSERT(client());
86
87    wxWindow* nativeWin = v->platformWidget();
88
89    if (nativeWin) {
90        // construct the menu
91        m_menu = new wxMenu();
92
93        int size = client()->listSize();
94        for (int i = 0; i < size; i++) {
95            int id = s_menuStartId + i;
96
97            if (client()->itemIsSeparator(i)) {
98                m_menu->AppendSeparator();
99            }
100            else {
101                // FIXME: appending a menu item with an empty label asserts in
102                // wx. This needs to be fixed at wx level so that we can have
103                // the concept of "no selection" in choice boxes, etc.
104                if (!client()->itemText(i).isEmpty())
105                    m_menu->Append(s_menuStartId + i, client()->itemText(i));
106            }
107        }
108        nativeWin->Connect(s_menuStartId, s_menuStartId + (size-1), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(PopupMenuEventHandler::OnMenuItemSelected), 0, m_popupHandler);
109        nativeWin->PopupMenu(m_menu, r.x() - v->scrollX(), r.y() - v->scrollY());
110        nativeWin->Disconnect(s_menuStartId, s_menuStartId + (size-1), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(PopupMenuEventHandler::OnMenuItemSelected), 0, m_popupHandler);
111    }
112}
113
114void PopupMenuWx::hide()
115{
116    // we don't need to do anything here, the native control only exists during the time
117    // show is called
118}
119
120void PopupMenuWx::updateFromElement()
121{
122    client()->setTextFromItem(m_popupClient->selectedIndex());
123}
124
125}
126