• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the popup menu implementation for <select> elements in WebCore.
3  *
4  * Copyright 2009, The Android Open Source Project
5  * Copyright (C) 2006 Apple Computer, Inc.
6  * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24 
25 #include "config.h"
26 #include "PopupMenuAndroid.h"
27 
28 #include "IntRect.h"
29 #include "PopupMenuClient.h"
30 #include "SkTDArray.h"
31 #include "WebViewCore.h"
32 
33 using namespace WebCore;
34 
35 class PopupReply : public android::WebCoreReply {
36 public:
PopupReply(const IntRect & rect,android::WebViewCore * view,ListPopupMenuClient * client)37     PopupReply(const IntRect& rect, android::WebViewCore* view, ListPopupMenuClient* client)
38         : m_rect(rect)
39         , m_viewImpl(view)
40         , m_popupClient(client)
41     {
42     }
43 
~PopupReply()44     virtual ~PopupReply() {}
45 
replyInt(int value)46     virtual void replyInt(int value)
47     {
48         if (m_popupClient) {
49             m_popupClient->popupDidHide();
50             // -2 is a special value signaling that the popup was canceled.
51             if (-2 == value)
52                 return;
53             m_popupClient->valueChanged(value, true);
54         }
55         if (m_viewImpl)
56             m_viewImpl->contentInvalidate(m_rect);
57     }
58 
replyIntArray(const int * values,int count)59     virtual void replyIntArray(const int* values, int count)
60     {
61         if (m_popupClient) {
62             m_popupClient->popupDidHide();
63             if (0 == count) {
64                 m_popupClient->valueChanged(-1, true);
65             } else {
66                 for (int i = 0; i < count; i++) {
67                     m_popupClient->listBoxSelectItem(values[i],
68                         i != 0 /* allowMultiplySelection */,
69                         false /* shift */,
70                         i == count - 1 /* fireOnChangeNow */);
71                 }
72             }
73         }
74         if (m_viewImpl)
75             m_viewImpl->contentInvalidate(m_rect);
76     }
77 
disconnectClient()78     void disconnectClient()
79     {
80         m_popupClient = 0;
81         m_viewImpl = 0;
82     }
83 private:
84     IntRect m_rect;
85     // FIXME: Do not need this if we handle ChromeClientAndroid::formStateDidChange
86     android::WebViewCore* m_viewImpl;
87     ListPopupMenuClient* m_popupClient;
88 };
89 
90 namespace WebCore {
91 
PopupMenuAndroid(ListPopupMenuClient * menuList)92 PopupMenuAndroid::PopupMenuAndroid(ListPopupMenuClient* menuList)
93     : m_popupClient(menuList)
94     , m_reply(0)
95 {
96 }
~PopupMenuAndroid()97 PopupMenuAndroid::~PopupMenuAndroid()
98 {
99     disconnectClient();
100 }
101 
disconnectClient()102 void PopupMenuAndroid::disconnectClient()
103 {
104     m_popupClient = 0;
105     if (m_reply) {
106         m_reply->disconnectClient();
107         Release(m_reply);
108         m_reply = 0;
109     }
110 }
111 
112 // Convert a WTF::String into an array of characters where the first
113 // character represents the length, for easy conversion to java.
stringConverter(const WTF::String & text)114 static uint16_t* stringConverter(const WTF::String& text)
115 {
116     size_t length = text.length();
117     uint16_t* itemName = new uint16_t[length+1];
118     itemName[0] = (uint16_t)length;
119     uint16_t* firstChar = &(itemName[1]);
120     memcpy((void*)firstChar, text.characters(), sizeof(UChar)*length);
121     return itemName;
122 }
123 
show(const IntRect & rect,FrameView * frameView,int)124 void PopupMenuAndroid::show(const IntRect& rect, FrameView* frameView, int)
125 {
126     android::WebViewCore* viewImpl = android::WebViewCore::getWebViewCore(frameView);
127     m_reply = new PopupReply(rect, viewImpl, m_popupClient);
128     Retain(m_reply);
129 
130     SkTDArray<const uint16_t*> names;
131     // Possible values for enabledArray.  Keep in Sync with values in
132     // InvokeListBox.Container in WebView.java
133     enum OptionStatus {
134         OPTGROUP = -1,
135         OPTION_DISABLED = 0,
136         OPTION_ENABLED = 1,
137     };
138     SkTDArray<int> enabledArray;
139     SkTDArray<int> selectedArray;
140     int size = m_popupClient->listSize();
141     bool multiple = m_popupClient->multiple();
142     for (int i = 0; i < size; i++) {
143         *names.append() = stringConverter(m_popupClient->itemText(i));
144         if (m_popupClient->itemIsSeparator(i)) {
145             *enabledArray.append() = OPTION_DISABLED;
146         } else if (m_popupClient->itemIsLabel(i)) {
147             *enabledArray.append() = OPTGROUP;
148         } else {
149             // Must be an Option
150             *enabledArray.append() = m_popupClient->itemIsEnabled(i)
151                     ? OPTION_ENABLED : OPTION_DISABLED;
152             if (multiple && m_popupClient->itemIsSelected(i))
153                 *selectedArray.append() = i;
154         }
155     }
156 
157     viewImpl->listBoxRequest(m_reply,
158                              names.begin(),
159                              size,
160                              enabledArray.begin(),
161                              enabledArray.count(),
162                              multiple,
163                              selectedArray.begin(),
164                              multiple ? selectedArray.count() : m_popupClient->selectedIndex());
165 }
166 
167 } // namespace WebCore
168