| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2006, 2008, 2010, 2011 Apple Inc. All rights reserved. | |
| 3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | |
| 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 #import "config.h" | |
| 22 #import "PopupMenuMac.h" | |
| 23 | |
| 24 #import "AXObjectCache.h" | |
| 25 #import "Chrome.h" | |
| 26 #import "ChromeClient.h" | |
| 27 #import "EventHandler.h" | |
| 28 #import "Frame.h" | |
| 29 #import "FrameView.h" | |
| 30 #import "HTMLNames.h" | |
| 31 #import "HTMLOptGroupElement.h" | |
| 32 #import "HTMLOptionElement.h" | |
| 33 #import "HTMLSelectElement.h" | |
| 34 #import "Page.h" | |
| 35 #import "PopupMenuClient.h" | |
| 36 #import "SimpleFontData.h" | |
| 37 #import "WebCoreSystemInterface.h" | |
| 38 | |
| 39 namespace WebCore { | |
| 40 | |
| 41 using namespace HTMLNames; | |
| 42 | |
| 43 PopupMenuMac::PopupMenuMac(PopupMenuClient* client) | |
| 44 : m_popupClient(client) | |
| 45 { | |
| 46 } | |
| 47 | |
| 48 PopupMenuMac::~PopupMenuMac() | |
| 49 { | |
| 50 if (m_popup) | |
| 51 [m_popup.get() setControlView:nil]; | |
| 52 } | |
| 53 | |
| 54 void PopupMenuMac::clear() | |
| 55 { | |
| 56 if (m_popup) | |
| 57 [m_popup.get() removeAllItems]; | |
| 58 } | |
| 59 | |
| 60 void PopupMenuMac::populate() | |
| 61 { | |
| 62 if (m_popup) | |
| 63 clear(); | |
| 64 else { | |
| 65 m_popup = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:!client(
)->shouldPopOver()]; | |
| 66 [m_popup.get() release]; // release here since the RetainPtr has retaine
d the object already | |
| 67 [m_popup.get() setUsesItemFromMenu:NO]; | |
| 68 [m_popup.get() setAutoenablesItems:NO]; | |
| 69 } | |
| 70 | |
| 71 BOOL messagesEnabled = [[m_popup.get() menu] menuChangedMessagesEnabled]; | |
| 72 [[m_popup.get() menu] setMenuChangedMessagesEnabled:NO]; | |
| 73 | |
| 74 // For pullDown menus the first item is hidden. | |
| 75 if (!client()->shouldPopOver()) | |
| 76 [m_popup.get() addItemWithTitle:@""]; | |
| 77 | |
| 78 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 | |
| 79 TextDirection menuTextDirection = client()->menuStyle().textDirection(); | |
| 80 [m_popup.get() setUserInterfaceLayoutDirection:menuTextDirection == LTR ? NS
UserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToL
eft]; | |
| 81 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 | |
| 82 | |
| 83 ASSERT(client()); | |
| 84 int size = client()->listSize(); | |
| 85 | |
| 86 for (int i = 0; i < size; i++) { | |
| 87 if (client()->itemIsSeparator(i)) | |
| 88 [[m_popup.get() menu] addItem:[NSMenuItem separatorItem]]; | |
| 89 else { | |
| 90 PopupMenuStyle style = client()->itemStyle(i); | |
| 91 NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init]
; | |
| 92 if (style.font() != Font()) { | |
| 93 NSFont *font = style.font().primaryFont()->getNSFont(); | |
| 94 if (!font) { | |
| 95 CGFloat size = style.font().primaryFont()->platformData().si
ze(); | |
| 96 font = style.font().weight() < FontWeightBold ? [NSFont syst
emFontOfSize:size] : [NSFont boldSystemFontOfSize:size]; | |
| 97 } | |
| 98 [attributes setObject:font forKey:NSFontAttributeName]; | |
| 99 } | |
| 100 | |
| 101 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 | |
| 102 RetainPtr<NSMutableParagraphStyle> paragraphStyle(AdoptNS, [[NSParag
raphStyle defaultParagraphStyle] mutableCopy]); | |
| 103 [paragraphStyle.get() setAlignment:menuTextDirection == LTR ? NSLeft
TextAlignment : NSRightTextAlignment]; | |
| 104 NSWritingDirection writingDirection = style.textDirection() == LTR ?
NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft; | |
| 105 [paragraphStyle.get() setBaseWritingDirection:writingDirection]; | |
| 106 if (style.hasTextDirectionOverride()) { | |
| 107 RetainPtr<NSNumber> writingDirectionValue(AdoptNS, [[NSNumber al
loc] initWithInteger:writingDirection + NSTextWritingDirectionOverride]); | |
| 108 RetainPtr<NSArray> writingDirectionArray(AdoptNS, [[NSArray allo
c] initWithObjects:writingDirectionValue.get(), nil]); | |
| 109 [attributes setObject:writingDirectionArray.get() forKey:NSWriti
ngDirectionAttributeName]; | |
| 110 } | |
| 111 [attributes setObject:paragraphStyle.get() forKey:NSParagraphStyleAt
tributeName]; | |
| 112 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 | |
| 113 | |
| 114 // FIXME: Add support for styling the foreground and background colo
rs. | |
| 115 // FIXME: Find a way to customize text color when an item is highlig
hted. | |
| 116 NSAttributedString *string = [[NSAttributedString alloc] initWithStr
ing:client()->itemText(i) attributes:attributes]; | |
| 117 [attributes release]; | |
| 118 | |
| 119 [m_popup.get() addItemWithTitle:@""]; | |
| 120 NSMenuItem *menuItem = [m_popup.get() lastItem]; | |
| 121 [menuItem setAttributedTitle:string]; | |
| 122 // We set the title as well as the attributed title here. The attrib
uted title will be displayed in the menu, | |
| 123 // but typeahead will use the non-attributed string that doesn't con
tain any leading or trailing whitespace. | |
| 124 [menuItem setTitle:[[string string] stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]]]; | |
| 125 [menuItem setEnabled:client()->itemIsEnabled(i)]; | |
| 126 [menuItem setToolTip:client()->itemToolTip(i)]; | |
| 127 [string release]; | |
| 128 | |
| 129 // Allow the accessible text of the item to be overriden if necessar
y. | |
| 130 if (AXObjectCache::accessibilityEnabled()) { | |
| 131 NSString *accessibilityOverride = client()->itemAccessibilityTex
t(i); | |
| 132 if ([accessibilityOverride length]) | |
| 133 [menuItem accessibilitySetOverrideValue:accessibilityOverrid
e forAttribute:NSAccessibilityDescriptionAttribute]; | |
| 134 } | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 [[m_popup.get() menu] setMenuChangedMessagesEnabled:messagesEnabled]; | |
| 139 } | |
| 140 | |
| 141 void PopupMenuMac::show(const IntRect& r, FrameView* v, int index) | |
| 142 { | |
| 143 populate(); | |
| 144 int numItems = [m_popup.get() numberOfItems]; | |
| 145 if (numItems <= 0) { | |
| 146 if (client()) | |
| 147 client()->popupDidHide(); | |
| 148 return; | |
| 149 } | |
| 150 ASSERT(numItems > index); | |
| 151 | |
| 152 // Workaround for crazy bug where a selected index of -1 for a menu with onl
y 1 item will cause a blank menu. | |
| 153 if (index == -1 && numItems == 2 && !client()->shouldPopOver() && ![[m_popup
.get() itemAtIndex:1] isEnabled]) | |
| 154 index = 0; | |
| 155 | |
| 156 NSView* view = v->documentView(); | |
| 157 | |
| 158 [m_popup.get() attachPopUpWithFrame:r inView:view]; | |
| 159 [m_popup.get() selectItemAtIndex:index]; | |
| 160 | |
| 161 NSMenu* menu = [m_popup.get() menu]; | |
| 162 | |
| 163 NSPoint location; | |
| 164 NSFont* font = client()->menuStyle().font().primaryFont()->getNSFont(); | |
| 165 | |
| 166 // These values were borrowed from AppKit to match their placement of the me
nu. | |
| 167 const int popOverHorizontalAdjust = -10; | |
| 168 const int popUnderHorizontalAdjust = 6; | |
| 169 const int popUnderVerticalAdjust = 6; | |
| 170 if (client()->shouldPopOver()) { | |
| 171 NSRect titleFrame = [m_popup.get() titleRectForBounds:r]; | |
| 172 if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0) | |
| 173 titleFrame = r; | |
| 174 float vertOffset = roundf((NSMaxY(r) - NSMaxY(titleFrame)) + NSHeight(ti
tleFrame)); | |
| 175 // Adjust for fonts other than the system font. | |
| 176 NSFont* defaultFont = [NSFont systemFontOfSize:[font pointSize]]; | |
| 177 vertOffset += [font descender] - [defaultFont descender]; | |
| 178 vertOffset = fminf(NSHeight(r), vertOffset); | |
| 179 | |
| 180 location = NSMakePoint(NSMinX(r) + popOverHorizontalAdjust, NSMaxY(r) -
vertOffset); | |
| 181 } else | |
| 182 location = NSMakePoint(NSMinX(r) + popUnderHorizontalAdjust, NSMaxY(r) +
popUnderVerticalAdjust); | |
| 183 | |
| 184 // Save the current event that triggered the popup, so we can clean up our e
vent | |
| 185 // state after the NSMenu goes away. | |
| 186 RefPtr<Frame> frame = v->frame(); | |
| 187 NSEvent* event = [frame->eventHandler()->currentNSEvent() retain]; | |
| 188 | |
| 189 RefPtr<PopupMenuMac> protector(this); | |
| 190 | |
| 191 RetainPtr<NSView> dummyView(AdoptNS, [[NSView alloc] initWithFrame:r]); | |
| 192 [view addSubview:dummyView.get()]; | |
| 193 location = [dummyView.get() convertPoint:location fromView:view]; | |
| 194 | |
| 195 if (Page* page = frame->page()) | |
| 196 page->chrome()->client()->willPopUpMenu(menu); | |
| 197 wkPopupMenu(menu, location, roundf(NSWidth(r)), dummyView.get(), index, font
); | |
| 198 | |
| 199 [m_popup.get() dismissPopUp]; | |
| 200 [dummyView.get() removeFromSuperview]; | |
| 201 | |
| 202 if (client()) { | |
| 203 int newIndex = [m_popup.get() indexOfSelectedItem]; | |
| 204 client()->popupDidHide(); | |
| 205 | |
| 206 // Adjust newIndex for hidden first item. | |
| 207 if (!client()->shouldPopOver()) | |
| 208 newIndex--; | |
| 209 | |
| 210 if (index != newIndex && newIndex >= 0) | |
| 211 client()->valueChanged(newIndex); | |
| 212 | |
| 213 // Give the frame a chance to fix up its event state, since the popup ea
ts all the | |
| 214 // events during tracking. | |
| 215 frame->eventHandler()->sendFakeEventsAfterWidgetTracking(event); | |
| 216 } | |
| 217 | |
| 218 [event release]; | |
| 219 } | |
| 220 | |
| 221 void PopupMenuMac::hide() | |
| 222 { | |
| 223 [m_popup.get() dismissPopUp]; | |
| 224 } | |
| 225 | |
| 226 void PopupMenuMac::updateFromElement() | |
| 227 { | |
| 228 } | |
| 229 | |
| 230 void PopupMenuMac::disconnectClient() | |
| 231 { | |
| 232 m_popupClient = 0; | |
| 233 } | |
| 234 | |
| 235 } | |
| OLD | NEW |