Reviewed by Dave.
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Feb 2004 02:44:08 +0000 (02:44 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Feb 2004 02:44:08 +0000 (02:44 +0000)
        - switched KWQComboBox, KWQListBox, and KWQLineEdit to use WebKit text measuring/rendering instead of AppKit
        - fixed width calculation for KWQListBox that made them too wide (the computation used the width of standard scroll
          bars rather than the small scroll bars they actually use)

        Speeds up cvs-base by 5%!

        * khtml/rendering/render_form.cpp: (RenderSelect::updateFromElement):
        Get rid of beginBatchInsert, and rename endBatchInsert. Use our own "append" calls instead of "insert" calls.

        * kwq/KWQComboBox.h: Replace insertItem with appendItem. Add a new populateMenu call (for internal use,
        but public). Change width member to be int instead of float. Remove updateCurrentItem(), and add a
        menuPopulated boolean and a QStringList containing the items.
        * kwq/KWQComboBox.mm:
        (QComboBox::QComboBox): Initialize currentItem directly instead of calling updateCurrentItem. Also initialize
        menuPopulated to true.
        (QComboBox::appendItem): Replaces insertItem. Put items in a string list. Don't keep the menu populated unless
        the button is highlighted (which indicates the menu is showing).
        (QComboBox::sizeHint): Compute widths using WebCoreTextRenderer, and the string list.
        (QComboBox::baselinePosition): Change ceil to ceilf, since we are dealing with floats, not doubles.
        (QComboBox::clear): Clear the items list. Also reset the currentItem field directly instead of using updateCurrentItem().
        (QComboBox::setCurrentItem): If the menu is not populated, then keep a single item with the appropriate title.
        If the menu is populated, then select the appropriate item.
        (QComboBox::itemSelected): Moved the logic from updateCurrentItem in here for simplicity.
        (QComboBox::focusPolicy): Tweaked the comment.
        (QComboBox::populateMenu): Added.
        (-[KWQPopUpButtonCell setHighlighted:]): Populate the menu when the cell is highlighted.

        * kwq/KWQLineEdit.mm:
        (QLineEdit::sizeForCharacterWidth): Put an empty string in the cell, and add in a separately-computed width
        for the string.
        (QLineEdit::baselinePosition): Use ceilf instead of ceil since we are doing floats, not doubles.

        * kwq/KWQListBox.h: Changed the items list from an NSArray to a QValueList.
        (KWQListBoxItem::KWQListBoxItem): Added a new class to keep the string and the "is label" boolean.
        (QListBox::count): Now inline.
        (QListBox::appendItem): Replaced insertItem with this.
        (QListBox::appendGroupLabel): Replaced insertGroupLabel with this.
        (QListBox::itemAtIndex): Replaced itemIsGroupLabel with this.
        * kwq/KWQListBox.mm:
        (itemTextRenderer): Replaced itemFont with this, which returns a WebCoreTextRenderer.
        (groupLabelTextRenderer): Ditto.
        (QListBox::QListBox): Removed the _insertingItems boolean, and handling of the _items list.
        (QListBox::~QListBox): Ditto.
        (QListBox::clear): Now clears the items list. Doesn't both with reloadData, since doneAppendingItems
        handles that.
        (QListBox::appendItem): Replaced insertItem. Just adds to the list. No need to construct attributed
        strings any more.
        (QListBox::doneAppendingItems): Replaced endBatchInsert. No need to clear the obsolete _insertingItems
        boolean.
        (QListBox::setEnabled): Added a call to reloadData.
        (QListBox::sizeForNumberOfLines): Compute widths using WebCoreTextRenderer, and the string list.
        Also adjust for the difference in widths between small and default scrollers and add in margins.
        (QListBox::setWritingDirection): Remove code that updates the direction in attributed strings.
        (-[KWQTableView initWithListBox:]): Compute height from font, not cell.
        (-[KWQTableView numberOfRowsInTableView:]): Get count from QListBox instead of items array.
        (-[KWQTableView tableView:objectValueForTableColumn:row:]): Return nil becase we don't want to
        create an NSString for each cell. We'll draw the appropriate thing.
        (-[KWQTableView tableView:shouldSelectRow:]): Update for change to QComboBox function.
        (-[KWQTableView drawRow:clipRect:]): Added. Draws the text in the cell, with the appropriate color
        and position, using WebCoreTextRenderer for speed.
        (-[KWQTableView _accessibilityTableCell:tableColumn:]): Set up cell with a string in this case,
        because we need the string to be seen by the accessibilty framework.

        * kwq/WebCoreTextRenderer.h: Fixed typo in comment.
        * kwq/WebCoreTextRendererFactory.m: Removed bogus inline specifiers.

        * khtml/rendering/render_layer.cpp: Fixed a couple of cases of RenderLayer::RenderLayer that just
        should have said RenderLayer.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@6049 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog-2005-08-23
WebCore/khtml/rendering/render_form.cpp
WebCore/khtml/rendering/render_layer.cpp
WebCore/kwq/KWQComboBox.h
WebCore/kwq/KWQComboBox.mm
WebCore/kwq/KWQLineEdit.mm
WebCore/kwq/KWQListBox.h
WebCore/kwq/KWQListBox.mm
WebCore/kwq/WebCoreTextRenderer.h
WebCore/kwq/WebCoreTextRendererFactory.m
WebCore/kwq/WebCoreTextRendererFactory.mm

index 3fdbd30a0f9d27bf86d1b725b4e1e050627b7cad..5d4f722ec88104cdb0f9ed86b06c305585c663ae 100644 (file)
@@ -1,3 +1,76 @@
+2004-02-07  Darin Adler  <darin@apple.com>
+
+        Reviewed by Dave.
+
+        - switched KWQComboBox, KWQListBox, and KWQLineEdit to use WebKit text measuring/rendering instead of AppKit
+        - fixed width calculation for KWQListBox that made them too wide (the computation used the width of standard scroll
+          bars rather than the small scroll bars they actually use)
+
+        Speeds up cvs-base by 5%!
+
+        * khtml/rendering/render_form.cpp: (RenderSelect::updateFromElement):
+        Get rid of beginBatchInsert, and rename endBatchInsert. Use our own "append" calls instead of "insert" calls.
+
+        * kwq/KWQComboBox.h: Replace insertItem with appendItem. Add a new populateMenu call (for internal use,
+        but public). Change width member to be int instead of float. Remove updateCurrentItem(), and add a
+        menuPopulated boolean and a QStringList containing the items.
+        * kwq/KWQComboBox.mm:
+        (QComboBox::QComboBox): Initialize currentItem directly instead of calling updateCurrentItem. Also initialize
+        menuPopulated to true.
+        (QComboBox::appendItem): Replaces insertItem. Put items in a string list. Don't keep the menu populated unless
+        the button is highlighted (which indicates the menu is showing).
+        (QComboBox::sizeHint): Compute widths using WebCoreTextRenderer, and the string list.
+        (QComboBox::baselinePosition): Change ceil to ceilf, since we are dealing with floats, not doubles.
+        (QComboBox::clear): Clear the items list. Also reset the currentItem field directly instead of using updateCurrentItem().
+        (QComboBox::setCurrentItem): If the menu is not populated, then keep a single item with the appropriate title.
+        If the menu is populated, then select the appropriate item.
+        (QComboBox::itemSelected): Moved the logic from updateCurrentItem in here for simplicity.
+        (QComboBox::focusPolicy): Tweaked the comment.
+        (QComboBox::populateMenu): Added.
+        (-[KWQPopUpButtonCell setHighlighted:]): Populate the menu when the cell is highlighted.
+
+        * kwq/KWQLineEdit.mm:
+        (QLineEdit::sizeForCharacterWidth): Put an empty string in the cell, and add in a separately-computed width
+        for the string.
+        (QLineEdit::baselinePosition): Use ceilf instead of ceil since we are doing floats, not doubles.
+
+        * kwq/KWQListBox.h: Changed the items list from an NSArray to a QValueList.
+        (KWQListBoxItem::KWQListBoxItem): Added a new class to keep the string and the "is label" boolean.
+        (QListBox::count): Now inline.
+        (QListBox::appendItem): Replaced insertItem with this.
+        (QListBox::appendGroupLabel): Replaced insertGroupLabel with this.
+        (QListBox::itemAtIndex): Replaced itemIsGroupLabel with this.
+        * kwq/KWQListBox.mm:
+        (itemTextRenderer): Replaced itemFont with this, which returns a WebCoreTextRenderer.
+        (groupLabelTextRenderer): Ditto.
+        (QListBox::QListBox): Removed the _insertingItems boolean, and handling of the _items list.
+        (QListBox::~QListBox): Ditto.
+        (QListBox::clear): Now clears the items list. Doesn't both with reloadData, since doneAppendingItems
+        handles that.
+        (QListBox::appendItem): Replaced insertItem. Just adds to the list. No need to construct attributed
+        strings any more.
+        (QListBox::doneAppendingItems): Replaced endBatchInsert. No need to clear the obsolete _insertingItems
+        boolean.
+        (QListBox::setEnabled): Added a call to reloadData.
+        (QListBox::sizeForNumberOfLines): Compute widths using WebCoreTextRenderer, and the string list.
+        Also adjust for the difference in widths between small and default scrollers and add in margins.
+        (QListBox::setWritingDirection): Remove code that updates the direction in attributed strings.
+        (-[KWQTableView initWithListBox:]): Compute height from font, not cell.
+        (-[KWQTableView numberOfRowsInTableView:]): Get count from QListBox instead of items array.
+        (-[KWQTableView tableView:objectValueForTableColumn:row:]): Return nil becase we don't want to
+        create an NSString for each cell. We'll draw the appropriate thing.
+        (-[KWQTableView tableView:shouldSelectRow:]): Update for change to QComboBox function.
+        (-[KWQTableView drawRow:clipRect:]): Added. Draws the text in the cell, with the appropriate color
+        and position, using WebCoreTextRenderer for speed.
+        (-[KWQTableView _accessibilityTableCell:tableColumn:]): Set up cell with a string in this case,
+        because we need the string to be seen by the accessibilty framework.
+
+        * kwq/WebCoreTextRenderer.h: Fixed typo in comment.
+        * kwq/WebCoreTextRendererFactory.m: Removed bogus inline specifiers.
+
+        * khtml/rendering/render_layer.cpp: Fixed a couple of cases of RenderLayer::RenderLayer that just
+        should have said RenderLayer.
+
 2004-02-07  Darin Adler  <darin@apple.com>
 
         * WebCore.pbproj/project.pbxproj: Get rid of the DEPLOYMENT_LOCATION and DEPLOYMENT_POSTPROCESSING
index c03f658e5df27d99babd80f1997a0578ba719a9c..867fac98956f9d309ef351aa38bb3756c22fa195 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) 2004 Apple Computer, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -1095,13 +1095,8 @@ void RenderSelect::updateFromElement()
         QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
         int listIndex;
 
-        if(m_useListBox) {
-#if APPLE_CHANGES
-            static_cast<KListBox*>(m_widget)->beginBatchInsert();
-#endif
+        if (m_useListBox)
             static_cast<KListBox*>(m_widget)->clear();
-        }
-
         else
             static_cast<KComboBox*>(m_widget)->clear();
 
@@ -1114,33 +1109,43 @@ void RenderSelect::updateFromElement()
                 // we give it).  We match this behavior.
                 label = label.stripWhiteSpace();
                 
-                if(m_useListBox) {
 #if APPLE_CHANGES
-                    static_cast<KListBox*>(m_widget)->insertGroupLabel(label, listIndex);
+                if (m_useListBox)
+                    static_cast<KListBox*>(m_widget)->appendGroupLabel(label);
+                else
+                    static_cast<KComboBox*>(m_widget)->appendItem(label);
 #else
+                if(m_useListBox) {
                     QListBoxText *item = new QListBoxText(label);
                     static_cast<KListBox*>(m_widget)
                         ->insertItem(item, listIndex);
                     item->setSelectable(false);
-#endif
                 }
                 else
                     static_cast<KComboBox*>(m_widget)->insertItem(label, listIndex);
+#endif
             }
             else if (listItems[listIndex]->id() == ID_OPTION) {
                 QString itemText = static_cast<HTMLOptionElementImpl*>(listItems[listIndex])->text().string();
                 itemText.replace('\\', backslashAsCurrencySymbol());
 
-                // In WinIE, an option can't start or end with whitespace.  We match this behavior.
+                // In WinIE, leading and trailing whitespace is ignored in options. We match this behavior.
                 itemText = itemText.stripWhiteSpace();
                 
                 if (listItems[listIndex]->parentNode()->id() == ID_OPTGROUP)
                     itemText.prepend("    ");
 
+#if APPLE_CHANGES
+                if (m_useListBox)
+                    static_cast<KListBox*>(m_widget)->appendItem(itemText);
+                else
+                    static_cast<KComboBox*>(m_widget)->appendItem(itemText);
+#else
                 if(m_useListBox)
                     static_cast<KListBox*>(m_widget)->insertItem(itemText, listIndex);
                 else
                     static_cast<KComboBox*>(m_widget)->insertItem(itemText, listIndex);
+#endif
             }
             else
                 KHTMLAssert(false);
@@ -1148,7 +1153,7 @@ void RenderSelect::updateFromElement()
         }
 #if APPLE_CHANGES
         if (m_useListBox)
-           static_cast<KListBox*>(m_widget)->endBatchInsert();
+           static_cast<KListBox*>(m_widget)->doneAppendingItems();
 #endif
         setNeedsLayoutAndMinMaxRecalc();
         m_optionsChanged = false;
index 072d3bf90419435280ae1926042ec2030e4e47f5..7da48c5b7a0dba797aebc86d21a7146943a4c703 100644 (file)
@@ -1078,8 +1078,8 @@ void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info)
 // Sort the buffer from lowest z-index to highest.  The common scenario will have
 // most z-indices equal, so we optimize for that case (i.e., the list will be mostly
 // sorted already).
-static void sortByZOrder(QPtrVector<RenderLayer::RenderLayer>* buffer,
-                         QPtrVector<RenderLayer::RenderLayer>* mergeBuffer,
+static void sortByZOrder(QPtrVector<RenderLayer>* buffer,
+                         QPtrVector<RenderLayer>* mergeBuffer,
                          uint start, uint end)
 {
     if (start >= end)
index 343c66c161b52c88e535445aa0b9d6641bb137ff..1e6efb6d5f3afa6128e4e32e85bb74252b0b67e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
 #define QCOMBOBOX_H_
 
 #include "KWQWidget.h"
+#include "KWQStringList.h"
 
 class QListBox;
 
@@ -42,7 +43,7 @@ public:
     ~QComboBox();
     
     void clear();
-    void insertItem(const QString &text, int index=-1);
+    void appendItem(const QString &text);
 
     int currentItem() const { return _currentItem; }
     void setCurrentItem(int);
@@ -61,16 +62,23 @@ public:
     virtual FocusPolicy focusPolicy() const;
 
     void setWritingDirection(QPainter::TextDirection);
+
+    void populateMenu();
     
 private:
-    bool updateCurrentItem() const;
     const int *dimensions() const;
     
     KWQComboBoxAdapter *_adapter;
-    mutable float _width;
+
+    mutable int _width;
     mutable bool _widthGood;
+
     mutable int _currentItem;
 
+    // A vector<QString> or QValueVector<QString> may be more efficient for large menus.
+    QStringList _items;
+    mutable bool _menuPopulated;
+
     KWQSignal _activated;
 };
 
index cbe0ff9649c5d3a211e3b64abbf0a903d38290e2..74c1d7d4796c0a50301a17b2048e8d19e9e87a32 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #import "KWQComboBox.h"
 
+#import "KWQAssertions.h"
 #import "KWQButton.h"
 #import "KWQExceptions.h"
 #import "KWQKHTMLPart.h"
-#import "KWQView.h"
-#import "KWQKHTMLPart.h"
 #import "KWQNSViewExtras.h"
+#import "KWQView.h"
 #import "WebCoreBridge.h"
-#import "khtmlview.h"
-#import "render_replaced.h"
-
-using khtml::RenderWidget;
+#import "WebCoreTextRenderer.h"
+#import "WebCoreTextRendererFactory.h"
 
 @interface NSCell (KWQComboBoxKnowsAppKitSecrets)
 - (NSMutableDictionary *)_textAttributes;
@@ -55,20 +53,18 @@ enum {
 {
     QComboBox *box;
 }
-- initWithQComboBox:(QComboBox *)b;
+- (id)initWithQComboBox:(QComboBox *)b;
 - (void)action:(id)sender;
 @end
 
 @interface KWQPopUpButtonCell : NSPopUpButtonCell <KWQWidgetHolder>
 {
-    QWidget *widget;
+    QComboBox *box;
     NSWritingDirection baseWritingDirection;
 }
-
-- (id)initWithWidget:(QWidget *)widget;
+- (id)initWithQComboBox:(QComboBox *)b;
 - (void)setBaseWritingDirection:(NSWritingDirection)direction;
 - (NSWritingDirection)baseWritingDirection;
-
 @end
 
 @interface KWQPopUpButton : NSPopUpButton <KWQWidgetHolder>
@@ -80,6 +76,8 @@ enum {
 QComboBox::QComboBox()
     : _adapter(0)
     , _widthGood(false)
+    , _currentItem(0)
+    , _menuPopulated(true)
     , _activated(this, SIGNAL(activated(int)))
 {
     KWQ_BLOCK_EXCEPTIONS;
@@ -89,7 +87,7 @@ QComboBox::QComboBox()
     setView(button);
     [button release];
     
-    KWQPopUpButtonCell *cell = [[KWQPopUpButtonCell alloc] initWithWidget:this];
+    KWQPopUpButtonCell *cell = [[KWQPopUpButtonCell alloc] initWithQComboBox:this];
     [button setCell:cell];
     [cell release];
 
@@ -99,8 +97,6 @@ QComboBox::QComboBox()
     [[button cell] setControlSize:NSSmallControlSize];
     [button setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
 
-    updateCurrentItem();
-
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
@@ -115,65 +111,64 @@ QComboBox::~QComboBox()
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
-void QComboBox::insertItem(const QString &text, int i)
+void QComboBox::appendItem(const QString &text)
 {
     KWQ_BLOCK_EXCEPTIONS;
 
-    int index = i;
-
-    KWQPopUpButton *button = (KWQPopUpButton *)getView();
-    int numItems = [button numberOfItems];
-    if (index < 0) {
-        index = numItems;
-    }
-    while (index >= numItems) {
-        [button addItemWithTitle:@""];
-        ++numItems;
+    _items.append(text);
+    if (_menuPopulated) {
+        KWQPopUpButton *button = (KWQPopUpButton *)getView();
+        if (![[button cell] isHighlighted]) {
+            _menuPopulated = false;
+        } else {
+            // We must add the item with no title and then set the title because
+            // addItemWithTitle does not allow duplicate titles.
+            [button addItemWithTitle:@""];
+            [[button lastItem] setTitle:text.getNSString()];
+        }
     }
-    // It's convenient that we added the item with an empty title,
-    // because addItemWithTitle will not allow multiple items with the
-    // same title. But this way, we can have such duplicate items.
-    [[button itemAtIndex:index] setTitle:text.getNSString()];
     _widthGood = false;
 
-    updateCurrentItem();
-
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
 QSize QComboBox::sizeHint() const 
 {
-    NSSize size = {0,0};
-
     KWQ_BLOCK_EXCEPTIONS;
 
     KWQPopUpButton *button = (KWQPopUpButton *)getView();
     
-    float width;
-    if (_widthGood) {
-        width = _width;
-    } else {
-        width = 0;
-        NSDictionary *attributes = [NSDictionary dictionaryWithObject:[button font] forKey:NSFontAttributeName];
-        NSEnumerator *e = [[button itemTitles] objectEnumerator];
-        NSString *text;
-        while ((text = [e nextObject])) {
-            NSSize size = [text sizeWithAttributes:attributes];
-            width = MAX(width, size.width);
-        }
-        _width = ceil(width);
-        if (_width < dimensions()[minimumTextWidth]) {
-            _width = dimensions()[minimumTextWidth];
+    if (!_widthGood) {
+        float width = 0;
+        QValueListConstIterator<QString> i = const_cast<const QStringList &>(_items).begin();
+        QValueListConstIterator<QString> e = const_cast<const QStringList &>(_items).end();
+        if (i != e) {
+            id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
+                rendererWithFont:[button font] usingPrinterFont:![NSGraphicsContext currentContextDrawingToScreen]];
+            WebCoreTextStyle style;
+            WebCoreInitializeEmptyTextStyle(&style);
+            do {
+                const QString &s = *i;
+                ++i;
+
+                WebCoreTextRun run;
+                int length = s.length();
+                WebCoreInitializeTextRun(&run, reinterpret_cast<const UniChar *>(s.unicode()), length, 0, length);
+
+                float textWidth = [renderer floatWidthForRun:&run style:&style widths:0];
+                width = kMax(width, textWidth);
+            } while (i != e);
         }
+        _width = kMax(static_cast<int>(ceilf(width)), dimensions()[minimumTextWidth]);
         _widthGood = true;
     }
     
-    size = [[button cell] cellSize];
+    return QSize(_width + dimensions()[widthNotIncludingText],
+        static_cast<int>([[button cell] cellSize].height) - (dimensions()[topMargin] + dimensions()[bottomMargin]));
 
     KWQ_UNBLOCK_EXCEPTIONS;
 
-    return QSize((int)_width + dimensions()[widthNotIncludingText],
-        (int)size.height - (dimensions()[topMargin] + dimensions()[bottomMargin]));
+    return QSize(0, 0);
 }
 
 QRect QComboBox::frameGeometry() const
@@ -195,7 +190,7 @@ int QComboBox::baselinePosition(int height) const
 {
     // Menu text is at the top.
     KWQPopUpButton *button = (KWQPopUpButton *)getView();
-    return (int)ceil(-dimensions()[topMargin] + dimensions()[baselineFudgeFactor] + [[button font] ascender]);
+    return static_cast<int>(ceilf(-dimensions()[topMargin] + dimensions()[baselineFudgeFactor] + [[button font] ascender]));
 }
 
 void QComboBox::clear()
@@ -203,42 +198,47 @@ void QComboBox::clear()
     KWQPopUpButton *button = (KWQPopUpButton *)getView();
     [button removeAllItems];
     _widthGood = false;
-    updateCurrentItem();
+    _currentItem = 0;
+    _items.clear();
+    _menuPopulated = true;
 }
 
 void QComboBox::setCurrentItem(int index)
 {
+    ASSERT(index < (int)_items.count());
+
     KWQ_BLOCK_EXCEPTIONS;
 
     KWQPopUpButton *button = (KWQPopUpButton *)getView();
-    [button selectItemAtIndex:index];
+    if (_menuPopulated) {
+        [button selectItemAtIndex:index];
+    } else {
+        [button removeAllItems];
+        [button addItemWithTitle:@""];
+        [[button itemAtIndex:0] setTitle:_items[index].getNSString()];
+    }
 
     KWQ_UNBLOCK_EXCEPTIONS;
 
-    updateCurrentItem();
+    _currentItem = index;
 }
 
-bool QComboBox::updateCurrentItem() const
+void QComboBox::itemSelected()
 {
-    KWQPopUpButton *button = (KWQPopUpButton *)getView();
+    ASSERT(_menuPopulated);
 
     KWQ_BLOCK_EXCEPTIONS;
-    int i = [button indexOfSelectedItem];
 
+    KWQPopUpButton *button = (KWQPopUpButton *)getView();
+    int i = [button indexOfSelectedItem];
     if (_currentItem == i) {
-        return false;
+        return;
     }
     _currentItem = i;
-    KWQ_UNBLOCK_EXCEPTIONS;
 
-    return true;
-}
+    KWQ_UNBLOCK_EXCEPTIONS;
 
-void QComboBox::itemSelected()
-{
-    if (updateCurrentItem()) {
-        _activated.call(_currentItem);
-    }
+    _activated.call(_currentItem);
 }
 
 void QComboBox::setFont(const QFont &f)
@@ -281,9 +281,7 @@ QWidget::FocusPolicy QComboBox::focusPolicy() const
 {
     KWQ_BLOCK_EXCEPTIONS;
     
-    // Add an additional check here.
-    // For now, selects are only focused when full
-    // keyboard access is turned on.
+    // Menus are only focused when full keyboard access is turned on.
     unsigned keyboardUIMode = [KWQKHTMLPart::bridgeForWidget(this) keyboardUIMode];
     if ((keyboardUIMode & WebCoreKeyboardAccessFull) == 0)
         return NoFocus;
@@ -308,9 +306,32 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
+void QComboBox::populateMenu()
+{
+    if (!_menuPopulated) {
+        KWQ_BLOCK_EXCEPTIONS;
+
+        KWQPopUpButton *button = getView();
+        [button removeAllItems];
+        QValueListConstIterator<QString> i = const_cast<const QStringList &>(_items).begin();
+        QValueListConstIterator<QString> e = const_cast<const QStringList &>(_items).end();
+        for (; i != e; ++i) {
+            // We must add the item with no title and then set the title because
+            // addItemWithTitle does not allow duplicate titles.
+            [button addItemWithTitle:@""];
+            [[button lastItem] setTitle:(*i).getNSString()];
+        }
+        [button selectItemAtIndex:_currentItem];
+
+        KWQ_UNBLOCK_EXCEPTIONS;
+
+        _menuPopulated = true;
+    }
+}
+
 @implementation KWQComboBoxAdapter
 
-- initWithQComboBox:(QComboBox *)b
+- (id)initWithQComboBox:(QComboBox *)b
 {
     box = b;
     return [super init];
@@ -325,16 +346,15 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
 
 @implementation KWQPopUpButtonCell
 
-- initWithWidget:(QWidget *)w
+- (id)initWithQComboBox:(QComboBox *)b
 {
-    [super init];
-    widget = w;
-    return self;
+    box = b;
+    return [super init];
 }
 
 - (BOOL)trackMouse:(NSEvent *)event inRect:(NSRect)rect ofView:(NSView *)view untilMouseUp:(BOOL)flag
 {
-    WebCoreBridge *bridge = [KWQKHTMLPart::bridgeForWidget(widget) retain];
+    WebCoreBridge *bridge = [KWQKHTMLPart::bridgeForWidget(box) retain];
     BOOL result = [super trackMouse:event inRect:rect ofView:view untilMouseUp:flag];
     if (result) {
         // Give KHTML a chance to fix up its event state, since the popup eats all the
@@ -348,7 +368,7 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
 
 - (QWidget *)widget
 {
-    return widget;
+    return box;
 }
 
 - (void)setBaseWritingDirection:(NSWritingDirection)direction
@@ -375,6 +395,14 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
     return attributes;
 }
 
+- (void)setHighlighted:(BOOL)highlighted
+{
+    if (highlighted) {
+        box->populateMenu();
+    }
+    [super setHighlighted:highlighted];
+}
+
 @end
 
 @implementation KWQPopUpButton
@@ -409,7 +437,7 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
     return resign;
 }
 
--(NSView *)nextKeyView
+- (NSView *)nextKeyView
 {
     QWidget *widget = [self widget];
     return widget && inNextValidKeyView
@@ -417,7 +445,7 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
         : [super nextKeyView];
 }
 
--(NSView *)previousKeyView
+- (NSView *)previousKeyView
 {
     QWidget *widget = [self widget];
     return widget && inNextValidKeyView
@@ -425,7 +453,7 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
         : [super previousKeyView];
 }
 
--(NSView *)nextValidKeyView
+- (NSView *)nextValidKeyView
 {
     inNextValidKeyView = YES;
     NSView *view = [super nextValidKeyView];
@@ -433,7 +461,7 @@ void QComboBox::setWritingDirection(QPainter::TextDirection direction)
     return view;
 }
 
--(NSView *)previousValidKeyView
+- (NSView *)previousValidKeyView
 {
     inNextValidKeyView = YES;
     NSView *view = [super previousValidKeyView];
index f3871b2447690de66b3841b53f6de8b25a88a3e2..579ccc5c5059dccc23e048a207b9daa9bf54c300 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import "KWQExceptions.h"
 #import "KWQLogging.h"
 #import "KWQTextField.h"
+#import "WebCoreTextRenderer.h"
 #import "WebCoreTextRendererFactory.h"
 
-// This replicates constants from [NSTextFieldCell drawingRectForBounds].
-#define VERTICAL_FUDGE_FACTOR 3
-
 QLineEdit::QLineEdit()
     : m_returnPressed(this, SIGNAL(returnPressed()))
     , m_textChanged(this, SIGNAL(textChanged(const QString &)))
@@ -172,28 +170,33 @@ void QLineEdit::setEdited(bool flag)
 QSize QLineEdit::sizeForCharacterWidth(int numCharacters) const
 {
     // Figure out how big a text field needs to be for a given number of characters
-    // by installing a string with that number of characters (using "0" as the nominal
-    // character) and then asking the field's cell what the size should be.
+    // (using "0" as the nominal character).
 
     KWQTextField *textField = (KWQTextField *)getView();
 
     ASSERT(numCharacters > 0);
 
-    NSSize size = {0,0};
+    NSSize size = { 0, 0 };
 
     KWQ_BLOCK_EXCEPTIONS;
-    NSMutableString *nominalWidthString = [NSMutableString stringWithCapacity:numCharacters];
-    for (int i = 0; i < numCharacters; ++i) {
-        [nominalWidthString appendString:@"0"];
-    }
 
     NSString *value = [textField stringValue];
-    int maximumLength = [textField maximumLength];
-    [textField setMaximumLength:numCharacters];
-    [textField setStringValue:nominalWidthString];
+    [textField setStringValue:@""];
     size = [[textField cell] cellSize];
-    [textField setMaximumLength:maximumLength];
     [textField setStringValue:value];
+
+    id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
+        rendererWithFont:[textField font] usingPrinterFont:![NSGraphicsContext currentContextDrawingToScreen]];
+
+    WebCoreTextStyle style;
+    WebCoreInitializeEmptyTextStyle(&style);
+
+    const UniChar zero = '0';
+    WebCoreTextRun run;
+    WebCoreInitializeTextRun(&run, &zero, 1, 0, 1);
+
+    size.width += ceilf([renderer floatWidthForRun:&run style:&style widths:0] * numCharacters);
+
     KWQ_UNBLOCK_EXCEPTIONS;
 
     return QSize(size);
@@ -206,8 +209,8 @@ int QLineEdit::baselinePosition(int height) const
     KWQ_BLOCK_EXCEPTIONS;
     NSRect bounds = [textField bounds];
     NSFont *font = [textField font];
-    return (int)ceil([[textField cell] drawingRectForBounds:bounds].origin.y - bounds.origin.y
-        + [font defaultLineHeightForFont] + [font descender]);
+    return static_cast<int>(ceilf([[textField cell] drawingRectForBounds:bounds].origin.y - bounds.origin.y
+        + [font defaultLineHeightForFont] + [font descender]));
     KWQ_UNBLOCK_EXCEPTIONS;
 
     return 0;
index 33ba8b3e4def735ffb7ac8e223046c0256f541c8..09010741e3bbd93f53a00f628e75c5b530658ab1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #define KWQLISTBOX_H_
 
 #include "KWQScrollView.h"
-#include "KWQString.h"
 #include "KWQSignal.h"
+#include "KWQString.h"
+#include "KWQValueList.h"
 
-class QListBoxItem;
+struct KWQListBoxItem
+{
+    QString string;
+    bool isGroupLabel;
 
-#ifdef __OBJC__
-@class NSMutableArray;
-@class NSObject;
-#else
-class NSMutableArray;
-class NSObject;
-#endif
+    KWQListBoxItem(const QString &s, bool isLabel) : string(s), isGroupLabel(isLabel) { }
+};
 
 class QListBox : public QScrollView {
-friend class QListBoxItem;
 public:
     enum SelectionMode { Single, Extended };
 
@@ -50,14 +48,14 @@ public:
 
     QSize sizeForNumberOfLines(int numLines) const;
     
-    uint count() const;
-    void clear();
+    uint count() const { return _items.count(); }
+
     void setSelectionMode(SelectionMode);
 
-    void beginBatchInsert();
-    void insertItem(const QString &s, int i) { insertItem(s, i, false); }
-    void insertGroupLabel(const QString &s, int i) { insertItem(s, i, true); }
-    void endBatchInsert();
+    void clear();
+    void appendItem(const QString &s) { appendItem(s, false); }
+    void appendGroupLabel(const QString &s) { appendItem(s, true); }
+    void doneAppendingItems();
 
     void setSelected(int, bool);
     bool isSelected(int) const;
@@ -65,7 +63,7 @@ public:
     void setEnabled(bool enabled);
     bool isEnabled();
     
-    bool itemIsGroupLabel(int index) const;
+    const KWQListBoxItem &itemAtIndex(int index) const { return _items[index]; }
     
     void setWritingDirection(QPainter::TextDirection);
     
@@ -77,12 +75,14 @@ public:
     virtual bool checksDescendantsForFocus() const;
     
 private:
-    void insertItem(const QString &, int index, bool isLabel);
+    void appendItem(const QString &, bool isLabel);
+
+    // A vector<QString> or QValueVector<QString> might be more efficient for large lists.
+    QValueList<KWQListBoxItem> _items;
 
-    NSMutableArray *_items;
-    bool _insertingItems;
     bool _changingSelection;
     bool _enabled;
+
     mutable float _width;
     mutable bool _widthGood;
     
index 196377a78835a0308ca37f97181fe602138bf40d..6a270fe9c8dbbe31160a5e1a73066c11c8b28a46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import "KWQView.h"
 #import "WebCoreBridge.h"
 #import "WebCoreScrollView.h"
+#import "WebCoreTextRenderer.h"
+#import "WebCoreTextRendererFactory.h"
 
-#define MIN_LINES 4 /* ensures we have a scroll bar */
+@interface NSTableView (KWQListBoxKnowsAppKitSecrets)
+- (NSCell *)_accessibilityTableCell:(int)row tableColumn:(NSTableColumn *)tableColumn;
+@end
+
+const int minLines = 4; /* ensures we have a scroll bar */
+const float bottomMargin = 1;
+const float leftMargin = 2;
+const float rightMargin = 2;
 
 @interface KWQListBoxScrollView : WebCoreScrollView
 @end
 @interface KWQTableView : NSTableView <KWQWidgetHolder>
 {
     QListBox *_box;
-    NSArray *_items;
     BOOL processingMouseEvent;
     BOOL clickedDuringMouseEvent;
     BOOL inNextValidKeyView;
     NSWritingDirection _direction;
 }
-- initWithListBox:(QListBox *)b items:(NSArray *)items;
+- (id)initWithListBox:(QListBox *)b;
 - (void)_KWQ_setKeyboardFocusRingNeedsDisplay;
 - (QWidget *)widget;
 - (void)setBaseWritingDirection:(NSWritingDirection)direction;
@@ -66,36 +74,34 @@ static NSFont *groupLabelFont()
     return font;
 }
 
-static NSParagraphStyle *paragraphStyle(NSWritingDirection direction)
+static id <WebCoreTextRenderer> itemTextRenderer()
 {
-    static NSParagraphStyle *leftStyle;
-    static NSParagraphStyle *rightStyle;
-    NSParagraphStyle **style = direction == NSWritingDirectionRightToLeft ? &rightStyle : &leftStyle;
-    if (*style == nil) {
-        NSMutableParagraphStyle *mutableStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
-        [mutableStyle setBaseWritingDirection:direction];
-        *style = [mutableStyle copy];
-        [mutableStyle release];
+    if ([NSGraphicsContext currentContextDrawingToScreen]) {
+        static id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
+            rendererWithFont:itemFont() usingPrinterFont:NO];
+        return renderer;
+    } else {
+        static id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
+            rendererWithFont:itemFont() usingPrinterFont:YES];
+        return renderer;
     }
-    return *style;
 }
 
-static NSDictionary *stringAttributes(NSWritingDirection direction, bool isGroupLabel)
+static id <WebCoreTextRenderer> groupLabelTextRenderer()
 {
-    static NSDictionary *attributeGlobals[4];
-    NSDictionary **attributes = &attributeGlobals[(direction == NSWritingDirectionRightToLeft ? 0 : 1) + (isGroupLabel ? 0 : 2)];
-    if (*attributes == nil) {
-        *attributes = [[NSDictionary dictionaryWithObjectsAndKeys:
-            isGroupLabel ? groupLabelFont() : itemFont(), NSFontAttributeName,
-            paragraphStyle(direction), NSParagraphStyleAttributeName,
-            nil] retain];
+    if ([NSGraphicsContext currentContextDrawingToScreen]) {
+        static id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
+            rendererWithFont:groupLabelFont() usingPrinterFont:NO];
+        return renderer;
+    } else {
+        static id <WebCoreTextRenderer> renderer = [[WebCoreTextRendererFactory sharedFactory]
+            rendererWithFont:groupLabelFont() usingPrinterFont:YES];
+        return renderer;
     }
-    return *attributes;
 }
 
 QListBox::QListBox(QWidget *parent)
     : QScrollView(parent)
-    , _insertingItems(false)
     , _changingSelection(false)
     , _enabled(true)
     , _widthGood(false)
@@ -104,7 +110,6 @@ QListBox::QListBox(QWidget *parent)
 {
     KWQ_BLOCK_EXCEPTIONS;
 
-    _items = [[NSMutableArray alloc] init];
     NSScrollView *scrollView = [[KWQListBoxScrollView alloc] init];
     setView(scrollView);
     [scrollView release];
@@ -124,7 +129,7 @@ QListBox::QListBox(QWidget *parent)
     // <rdar://problem/3226083>: REGRESSION (Panther): white box overlaying select lists at nvidia.com drivers page
     [[scrollView contentView] releaseGState];
     
-    KWQTableView *tableView = [[KWQTableView alloc] initWithListBox:this items:_items];
+    KWQTableView *tableView = [[KWQTableView alloc] initWithListBox:this];
     [scrollView setDocumentView:tableView];
     [tableView release];
     [scrollView setVerticalLineScroll:[tableView rowHeight]];
@@ -140,30 +145,13 @@ QListBox::~QListBox()
     NSTableView *tableView = [scrollView documentView];
     [tableView setDelegate:nil];
     [tableView setDataSource:nil];
-    [_items release];
-    KWQ_UNBLOCK_EXCEPTIONS;
-}
-
-uint QListBox::count() const
-{
-    KWQ_BLOCK_EXCEPTIONS;
-    return [_items count];
     KWQ_UNBLOCK_EXCEPTIONS;
-
-    return 0;
 }
 
 void QListBox::clear()
 {
-    KWQ_BLOCK_EXCEPTIONS;
-    [_items removeAllObjects];
-    if (!_insertingItems) {
-        NSScrollView *scrollView = getView();
-        NSTableView *tableView = [scrollView documentView];
-        [tableView reloadData];
-    }
-    KWQ_UNBLOCK_EXCEPTIONS;
-    _widthGood = NO;
+    _items.clear();
+    _widthGood = false;
 }
 
 void QListBox::setSelectionMode(SelectionMode mode)
@@ -176,47 +164,14 @@ void QListBox::setSelectionMode(SelectionMode mode)
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
-void QListBox::insertItem(const QString &text, int index, bool isLabel)
-{
-    ASSERT(index >= 0);
-
-    KWQ_BLOCK_EXCEPTIONS;
-
-    NSScrollView *scrollView = getView();
-    KWQTableView *tableView = [scrollView documentView];
-
-    NSAttributedString *s = [[NSAttributedString alloc] initWithString:text.getNSString()
-        attributes:stringAttributes([tableView baseWritingDirection], isLabel)];
-
-    int c = count();
-    if (index >= c) {
-        [_items addObject:s];
-    } else {
-        [_items replaceObjectAtIndex:index withObject:s];
-    }
-    [s release];
-
-    if (!_insertingItems) {
-        [tableView reloadData];
-    }
-
-    KWQ_UNBLOCK_EXCEPTIONS;
-
-    _widthGood = NO;
-}
-
-void QListBox::beginBatchInsert()
+void QListBox::appendItem(const QString &text, bool isLabel)
 {
-    ASSERT(!_insertingItems);
-    _insertingItems = true;
+    _items.append(KWQListBoxItem(text, isLabel));
+    _widthGood = false;
 }
 
-void QListBox::endBatchInsert()
+void QListBox::doneAppendingItems()
 {
-    ASSERT(_insertingItems);
-    _insertingItems = false;
-
     KWQ_BLOCK_EXCEPTIONS;
 
     NSScrollView *scrollView = getView();
@@ -229,7 +184,6 @@ void QListBox::endBatchInsert()
 void QListBox::setSelected(int index, bool selectIt)
 {
     ASSERT(index >= 0);
-    ASSERT(!_insertingItems);
 
     KWQ_BLOCK_EXCEPTIONS;
 
@@ -251,7 +205,6 @@ void QListBox::setSelected(int index, bool selectIt)
 bool QListBox::isSelected(int index) const
 {
     ASSERT(index >= 0);
-    ASSERT(!_insertingItems);
 
     KWQ_BLOCK_EXCEPTIONS;
 
@@ -266,12 +219,19 @@ bool QListBox::isSelected(int index) const
 
 void QListBox::setEnabled(bool enabled)
 {
-    _enabled = enabled;
-    // You would think this would work, but not until AK fixes 2177792
-    //KWQ_BLOCK_EXCEPTIONS;
-    //NSTableView *tableView = [(NSScrollView *)getView() documentView];
-    //[tableView setEnabled:enabled];
-    //KWQ_UNBLOCK_EXCEPTIONS;
+    if (enabled != _enabled) {
+        // You would think this would work, but not until AppKit bug 2177792 if fixed.
+        //KWQ_BLOCK_EXCEPTIONS;
+        //NSTableView *tableView = [(NSScrollView *)getView() documentView];
+        //[tableView setEnabled:enabled];
+        //KWQ_UNBLOCK_EXCEPTIONS;
+
+        _enabled = enabled;
+
+        NSScrollView *scrollView = getView();
+        NSTableView *tableView = [scrollView documentView];
+        [tableView reloadData];
+    }
 }
 
 bool QListBox::isEnabled()
@@ -281,37 +241,42 @@ bool QListBox::isEnabled()
 
 QSize QListBox::sizeForNumberOfLines(int lines) const
 {
-    ASSERT(!_insertingItems);
-
-    NSScrollView *scrollView = getView();
-
     NSSize size = {0,0};
 
     KWQ_BLOCK_EXCEPTIONS;
-    NSTableView *tableView = [scrollView documentView];
+
+    NSScrollView *scrollView = getView();
+    KWQTableView *tableView = [scrollView documentView];
     
-    float width;
-    if (_widthGood) {
-        width = _width;
-    } else {
-        width = 0;
-        NSCell *cell = [[[tableView tableColumns] objectAtIndex:0] dataCell];
-        NSEnumerator *e = [_items objectEnumerator];
-        NSString *text;
-        while ((text = [e nextObject])) {
-            [cell setStringValue:text];
-            NSSize size = [cell cellSize];
-            width = MAX(width, size.width);
+    if (!_widthGood) {
+        float width = 0;
+        QValueListConstIterator<KWQListBoxItem> i = const_cast<const QValueList<KWQListBoxItem> &>(_items).begin();
+        QValueListConstIterator<KWQListBoxItem> e = const_cast<const QValueList<KWQListBoxItem> &>(_items).end();
+        if (i != e) {
+            WebCoreTextStyle style;
+            WebCoreInitializeEmptyTextStyle(&style);
+            style.rtl = [tableView baseWritingDirection] == NSWritingDirectionRightToLeft;
+            do {
+                const QString &s = (*i).string;
+                id <WebCoreTextRenderer> renderer = (*i).isGroupLabel ? groupLabelTextRenderer() : itemTextRenderer();
+                ++i;
+
+                WebCoreTextRun run;
+                int length = s.length();
+                WebCoreInitializeTextRun(&run, reinterpret_cast<const UniChar *>(s.unicode()), length, 0, length);
+
+                float textWidth = [renderer floatWidthForRun:&run style:&style widths:0];
+                width = kMax(width, textWidth);
+            } while (i != e);
         }
-        _width = width;
-        _widthGood = YES;
+        _width = ceilf(width);
+        _widthGood = true;
     }
     
-    NSSize contentSize;
-    contentSize.width = ceil(width);
-    contentSize.height = ceil(([tableView rowHeight] + [tableView intercellSpacing].height) * MAX(MIN_LINES, lines));
-    size = [NSScrollView frameSizeForContentSize:contentSize
+    size = [NSScrollView frameSizeForContentSize:NSMakeSize(_width, [tableView rowHeight] * MAX(minLines, lines))
         hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSBezelBorder];
+    size.width += [NSScroller scrollerWidthForControlSize:NSSmallControlSize] - [NSScroller scrollerWidth] + leftMargin + rightMargin;
+
     KWQ_UNBLOCK_EXCEPTIONS;
 
     return QSize(size);
@@ -321,9 +286,7 @@ QWidget::FocusPolicy QListBox::focusPolicy() const
 {
     KWQ_BLOCK_EXCEPTIONS;
     
-    // Add an additional check here.
-    // For now, selects are only focused when full
-    // keyboard access is turned on.
+    // Lists are only focused when full keyboard access is turned on.
     unsigned keyboardUIMode = [KWQKHTMLPart::bridgeForWidget(this) keyboardUIMode];
     if ((keyboardUIMode & WebCoreKeyboardAccessFull) == 0)
         return NoFocus;
@@ -346,14 +309,6 @@ void QListBox::setWritingDirection(QPainter::TextDirection d)
     KWQTableView *tableView = [scrollView documentView];
     NSWritingDirection direction = d == QPainter::RTL ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight;
     if ([tableView baseWritingDirection] != direction) {
-        int n = count();
-        for (int i = 0; i < n; i++) {
-            NSAttributedString *o = [_items objectAtIndex:i];
-            NSAttributedString *s = [[NSAttributedString alloc] initWithString:[o string]
-                attributes:stringAttributes([tableView baseWritingDirection], itemIsGroupLabel(i))];
-            [_items replaceObjectAtIndex:i withObject:s];
-            [s release];
-        }
         [tableView setBaseWritingDirection:direction];
         [tableView reloadData];
     }
@@ -361,21 +316,6 @@ void QListBox::setWritingDirection(QPainter::TextDirection d)
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
-bool QListBox::itemIsGroupLabel(int index) const
-{
-    ASSERT(index >= 0);
-
-    KWQ_BLOCK_EXCEPTIONS;
-
-    NSAttributedString *s = [_items objectAtIndex:index];
-    NSFont *f = [s attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL];
-    return f == groupLabelFont();
-
-    KWQ_UNBLOCK_EXCEPTIONS;
-
-    return false;
-}
-
 @implementation KWQListBoxScrollView
 
 - (void)setFrameSize:(NSSize)size
@@ -399,16 +339,15 @@ bool QListBox::itemIsGroupLabel(int index) const
 
 @implementation KWQTableView
 
-- initWithListBox:(QListBox *)b items:(NSArray *)i
+- (id)initWithListBox:(QListBox *)b
 {
     [super init];
+
     _box = b;
-    _items = i;
 
     NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:nil];
 
     [column setEditable:NO];
-    [[column dataCell] setFont:itemFont()];
 
     [self addTableColumn:column];
 
@@ -417,7 +356,7 @@ bool QListBox::itemIsGroupLabel(int index) const
     [self setAllowsMultipleSelection:NO];
     [self setHeaderView:nil];
     [self setIntercellSpacing:NSMakeSize(0, 0)];
-    [self setRowHeight:ceil([[column dataCell] cellSize].height)];
+    [self setRowHeight:ceilf([itemFont() ascender] - [itemFont() descender] + bottomMargin)];
     
     [self setDataSource:self];
     [self setDelegate:self];
@@ -425,7 +364,7 @@ bool QListBox::itemIsGroupLabel(int index) const
     return self;
 }
 
--(void)mouseDown:(NSEvent *)event
+- (void)mouseDown:(NSEvent *)event
 {
     processingMouseEvent = TRUE;
     [super mouseDown:event];
@@ -480,21 +419,21 @@ bool QListBox::itemIsGroupLabel(int index) const
     return resign;
 }
 
--(NSView *)nextKeyView
+- (NSView *)nextKeyView
 {
     return _box && inNextValidKeyView
         ? KWQKHTMLPart::nextKeyViewForWidget(_box, KWQSelectingNext)
         : [super nextKeyView];
 }
 
--(NSView *)previousKeyView
+- (NSView *)previousKeyView
 {
     return _box && inNextValidKeyView
         ? KWQKHTMLPart::nextKeyViewForWidget(_box, KWQSelectingPrevious)
         : [super previousKeyView];
 }
 
--(NSView *)nextValidKeyView
+- (NSView *)nextValidKeyView
 {
     inNextValidKeyView = YES;
     NSView *view = [super nextValidKeyView];
@@ -502,7 +441,7 @@ bool QListBox::itemIsGroupLabel(int index) const
     return view;
 }
 
--(NSView *)previousValidKeyView
+- (NSView *)previousValidKeyView
 {
     inNextValidKeyView = YES;
     NSView *view = [super previousValidKeyView];
@@ -512,12 +451,12 @@ bool QListBox::itemIsGroupLabel(int index) const
 
 - (int)numberOfRowsInTableView:(NSTableView *)tableView
 {
-    return [_items count];
+    return _box->count();
 }
 
 - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(int)row
 {
-    return [_items objectAtIndex:row];
+    return nil;
 }
 
 - (void)tableViewSelectionDidChange:(NSNotification *)notification
@@ -534,7 +473,7 @@ bool QListBox::itemIsGroupLabel(int index) const
 
 - (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row
 {
-    return !_box->itemIsGroupLabel(row);
+    return !_box->itemAtIndex(row).isGroupLabel;
 }
 
 - (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView
@@ -542,10 +481,44 @@ bool QListBox::itemIsGroupLabel(int index) const
     return _box->isEnabled();
 }
 
-- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(int)row
+- (void)drawRow:(int)row clipRect:(NSRect)clipRect
 {
-    ASSERT([cell isKindOfClass:[NSCell class]]);
-    [(NSCell *)cell setEnabled:_box->isEnabled()];
+    const KWQListBoxItem &item = _box->itemAtIndex(row);
+
+    NSColor *color;
+    if (_box->isEnabled()) {
+        if ([self isRowSelected:row] && [[self window] firstResponder] == self && ([[self window] isKeyWindow] || ![[self window] canBecomeKeyWindow])) {
+            color = [NSColor alternateSelectedControlTextColor];
+        } else {
+            color = [NSColor controlTextColor];
+        }
+    } else {
+        color = [NSColor disabledControlTextColor];
+    }
+
+    bool RTL = _direction == NSWritingDirectionRightToLeft;
+
+    id <WebCoreTextRenderer> renderer = item.isGroupLabel ? groupLabelTextRenderer() : itemTextRenderer();
+
+    WebCoreTextStyle style;
+    WebCoreInitializeEmptyTextStyle(&style);
+    style.rtl = RTL;
+    style.textColor = color;
+
+    WebCoreTextRun run;
+    int length = item.string.length();
+    WebCoreInitializeTextRun(&run, reinterpret_cast<const UniChar *>(item.string.unicode()), length, 0, length);
+
+    NSRect cellRect = [self frameOfCellAtColumn:0 row:row];
+    NSPoint point;
+    if (!RTL) {
+        point.x = NSMinX(cellRect) + leftMargin;
+    } else {
+        point.x = NSMaxX(cellRect) - rightMargin - [renderer floatWidthForRun:&run style:&style widths:0];
+    }
+    point.y = NSMaxY(cellRect) + [itemFont() descender] - bottomMargin;
+
+    [renderer drawRun:&run style:&style atPoint:point];
 }
 
 - (void)_KWQ_setKeyboardFocusRingNeedsDisplay
@@ -568,4 +541,11 @@ bool QListBox::itemIsGroupLabel(int index) const
     return _direction;
 }
 
+- (NSCell *)_accessibilityTableCell:(int)row tableColumn:(NSTableColumn *)tableColumn
+{
+    NSCell *cell = [super _accessibilityTableCell:row tableColumn:tableColumn];
+    [cell setStringValue:_box->itemAtIndex(row).string.getNSString()];
+    return cell;
+}
+
 @end
index 6cbbd5ca59cacccf4f54517a5b355314dd0d625a..ca23132283358c8e15a8aad0e9f30360e8a0a5d6 100644 (file)
@@ -70,7 +70,7 @@ extern void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style);
 
 @protocol WebCoreTextRenderer <NSObject>
 
-// WebCoreTestRenderer must guarantee that no calls to any of these
+// WebCoreTextRenderer must guarantee that no calls to any of these
 // methods will raise any ObjC exceptions. It's too expensive to do
 // blocking for all of them at the WebCore level, and some
 // implementations may be able to guarantee no exceptions without the
index 5220f1f2a3dacecc05a5c224555fe6056e1fb09e..8153e06cbf710d53cc89ab4678c78c11ee39c854 100644 (file)
@@ -28,7 +28,7 @@
 
 #import "KWQAssertions.h"
 
-inline void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *characters, unsigned int length, int from, int to)
+void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *characters, unsigned int length, int from, int to)
 {
     run->characters = characters;
     run->length = length;
@@ -36,7 +36,7 @@ inline void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *charact
     run->to = to;
 }
 
-inline void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style)
+void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style)
 {
     style->padding = 0;
     style->textColor = nil;
index 5220f1f2a3dacecc05a5c224555fe6056e1fb09e..8153e06cbf710d53cc89ab4678c78c11ee39c854 100644 (file)
@@ -28,7 +28,7 @@
 
 #import "KWQAssertions.h"
 
-inline void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *characters, unsigned int length, int from, int to)
+void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *characters, unsigned int length, int from, int to)
 {
     run->characters = characters;
     run->length = length;
@@ -36,7 +36,7 @@ inline void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *charact
     run->to = to;
 }
 
-inline void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style)
+void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style)
 {
     style->padding = 0;
     style->textColor = nil;