Ticket #8555: ticket_8555.patch

File ticket_8555.patch, 16.8 KB (added by ahartford, 12 years ago)

Patch updated to draw underlines correctly when link text wraps.

  • src/apps/aboutsystem/HyperTextView.cpp

    From 8d33f35cb56c4791d97fa925de088ef14eeff3f7 Mon Sep 17 00:00:00 2001
    From: Adam Hartford <adam.s.hartford@gmail.com>
    Date: Sun, 17 Jun 2012 09:11:28 +0000
    Subject: [PATCH 1/5] Italicized links on mouse over (Ticket #8555)
    
    * Added MouseEnter and MouseLeave events.
    * Added helper function to retrieve text offset positions.
    * Eating mouse button events.
    
    Signed-off-by: Adam Hartford <adam.s.hartford@gmail.com>
    ---
     src/apps/aboutsystem/HyperTextView.cpp |   61 ++++++++++++++++++++++++++++----
     src/apps/aboutsystem/HyperTextView.h   |   10 +++++
     2 files changed, 64 insertions(+), 7 deletions(-)
    
    diff --git a/src/apps/aboutsystem/HyperTextView.cpp b/src/apps/aboutsystem/HyperTextView.cpp
    index d1bc4e6..134ef70 100644
    a b HyperTextAction::Clicked(HyperTextView* view, BPoint where, BMessage* message)  
    4040}
    4141
    4242
     43void
     44HyperTextAction::MouseEnter(HyperTextView* view, BPoint where,
     45    int32 startOffset, int32 endOffset, BMessage* message)
     46{
     47    BFont font(be_plain_font);
     48    font.SetFace(B_ITALIC_FACE);
     49    view->SetFontAndColor(startOffset, endOffset, &font);
     50}
     51
     52
     53void
     54HyperTextAction::MouseLeave(HyperTextView* view, BPoint where,
     55    int32 startOffset, int32 endOffset, BMessage* message)
     56{
     57    BFont font(be_plain_font);
     58    font.SetFace(B_REGULAR_FACE);
     59    view->SetFontAndColor(startOffset, endOffset, &font);
     60}       
     61
     62
    4363// #pragma mark - HyperTextView
    4464
    4565
    void  
    114134HyperTextView::MouseDown(BPoint where)
    115135{
    116136    // We eat all mouse button events.
    117 
    118     BTextView::MouseDown(where);
    119137}
    120138
    121139
    HyperTextView::MouseUp(BPoint where)  
    127145    HyperTextAction* action = _ActionAt(where);
    128146    if (action != NULL)
    129147        action->Clicked(this, where, message);
    130 
    131     BTextView::MouseUp(where);
    132148}
    133149
    134150
    HyperTextView::MouseMoved(BPoint where, uint32 transit,  
    139155    BMessage* message = Window()->CurrentMessage();
    140156
    141157    uint32 buttons;
    142     HyperTextAction* action;
     158    const ActionInfo* info = _ActionInfoAt(where);
    143159    if (message->FindInt32("buttons", (int32*)&buttons) == B_OK
    144         && buttons == 0 && (action = _ActionAt(where)) != NULL) {
     160        && buttons == 0 && info != NULL) {
     161        HyperTextAction* action = info->action;
    145162        action->MouseOver(this, where, message);
     163        if (fActiveInfo == NULL) {
     164            fActiveInfo = info;
     165            action->MouseEnter(this, where, info->startOffset, info->endOffset,
     166                message);
     167        } else if (fActiveInfo != info) {
     168            // This is the scenario where mouse moves from one action directly
     169            // into another.
     170            action->MouseEnter(this, where, info->startOffset, info->endOffset,
     171                message);
     172            fActiveInfo->action->MouseLeave(this, where, fActiveInfo->startOffset,
     173                fActiveInfo->endOffset, message);
     174            fActiveInfo = info;
     175        }
    146176        return;
     177    } else if (fActiveInfo != NULL) {
     178        fActiveInfo->action->MouseLeave(this, where, fActiveInfo->startOffset,
     179            fActiveInfo->endOffset, message);
     180        fActiveInfo = NULL;
    147181    }
    148182
    149183    BTextView::MouseMoved(where, transit, dragMessage);
    HyperTextView::InsertHyperText(const char* inText, int32 inLength,  
    193227HyperTextAction*
    194228HyperTextView::_ActionAt(const BPoint& where) const
    195229{
     230    const ActionInfo* info = _ActionInfoAt(where);
     231    if (info != NULL) {
     232        return info->action;
     233    }
     234
     235    return NULL;
     236}
     237
     238
     239const HyperTextView::ActionInfo*
     240HyperTextView::_ActionInfoAt(const BPoint& where) const
     241{
    196242    int32 offset = OffsetAt(where);
    197243
    198244    ActionInfo pointer(offset, offset + 1, NULL);
    HyperTextView::_ActionAt(const BPoint& where) const  
    204250        BRegion textRegion;
    205251        GetTextRegion(action->startOffset, action->endOffset, &textRegion);
    206252        if (textRegion.Contains(where))
    207             return action->action;
     253            return action;
    208254    }
    209255
    210256    return NULL;
    211257}
    212258
     259
  • src/apps/aboutsystem/HyperTextView.h

    diff --git a/src/apps/aboutsystem/HyperTextView.h b/src/apps/aboutsystem/HyperTextView.h
    index b9d6c2a..f413e2f 100644
    a b public:  
    2424                                    BMessage* message);
    2525    virtual void                Clicked(HyperTextView* view, BPoint where,
    2626                                    BMessage* message);
     27    virtual void                MouseEnter(HyperTextView* view, BPoint where,
     28                                    int32 startOffset, int32 endOffset,
     29                                    BMessage* message);
     30    virtual void                MouseLeave(HyperTextView* view, BPoint where,
     31                                    int32 startOffset, int32 endOffset,
     32                                    BMessage* message);
    2733};
    2834
    2935
    private:  
    5965            class ActionInfoList;
    6066
    6167            ActionInfoList*     fActionInfos;
     68           
     69            const ActionInfo*   _ActionInfoAt(const BPoint& where) const;
     70           
     71            const ActionInfo*   fActiveInfo;
    6272};
    6373
    6474
  • src/apps/aboutsystem/HyperTextActions.cpp

    -- 
    1.7.7.2
    
    
    From 05beb8fd3ecc569b6bab23c8f35b78af9d205d74 Mon Sep 17 00:00:00 2001
    From: Adam Hartford <adam.s.hartford@gmail.com>
    Date: Sat, 30 Jun 2012 09:57:34 -0400
    Subject: [PATCH 2/5] Underline links. Lines drawn manually. (Ticket #8555)
    
    ---
     src/apps/aboutsystem/HyperTextActions.cpp |   20 +++++++++++++
     src/apps/aboutsystem/HyperTextActions.h   |    4 +++
     src/apps/aboutsystem/HyperTextView.cpp    |   43 +++++++++++++++++++++++------
     src/apps/aboutsystem/HyperTextView.h      |    6 +++-
     4 files changed, 62 insertions(+), 11 deletions(-)
    
    diff --git a/src/apps/aboutsystem/HyperTextActions.cpp b/src/apps/aboutsystem/HyperTextActions.cpp
    index 5c8770c..498a1fc 100644
    a b  
    1010#include <Roster.h>
    1111
    1212
     13static const rgb_color kDarkGrey = { 100, 100, 100, 255 };
     14static const rgb_color kLinkBlue = { 80, 80, 200, 255 };
     15
     16
    1317// #pragma mark - URLAction
    1418
    1519
    URLAction::Clicked(HyperTextView* view, BPoint where, BMessage* message)  
    3943}
    4044
    4145
     46const rgb_color
     47URLAction::GetUnderlineColor()
     48{
     49    return kLinkBlue;
     50}
     51
     52
    4253// #pragma mark - OpenFileAction
    4354
    4455
    OpenFileAction::Clicked(HyperTextView* view, BPoint where, BMessage* message)  
    7283    } else
    7384        be_roster->Launch(&ref);
    7485}
     86
     87
     88const rgb_color
     89OpenFileAction::GetUnderlineColor()
     90{
     91    return kDarkGrey;
     92}
     93
     94
  • src/apps/aboutsystem/HyperTextActions.h

    diff --git a/src/apps/aboutsystem/HyperTextActions.h b/src/apps/aboutsystem/HyperTextActions.h
    index 4f32b38..4bd2819 100644
    a b public:  
    1717
    1818    virtual void                Clicked(HyperTextView* view, BPoint where,
    1919                                    BMessage* message);
     20
     21    virtual const rgb_color     GetUnderlineColor();
    2022private:
    2123            BString             fURL;
    2224};
    public:  
    2931
    3032    virtual void                Clicked(HyperTextView* view, BPoint where,
    3133                                    BMessage* message);
     34
     35    virtual const rgb_color     GetUnderlineColor();
    3236private:
    3337            BString             fFile;
    3438};
  • src/apps/aboutsystem/HyperTextView.cpp

    diff --git a/src/apps/aboutsystem/HyperTextView.cpp b/src/apps/aboutsystem/HyperTextView.cpp
    index 134ef70..dc33d09 100644
    a b  
    1616// #pragma mark - HyperTextAction
    1717
    1818
     19static const rgb_color kDarkGrey = { 100, 100, 100, 255 };
     20
     21
    1922HyperTextAction::HyperTextAction()
    2023{
    2124}
    HyperTextAction::MouseEnter(HyperTextView* view, BPoint where,  
    4548    int32 startOffset, int32 endOffset, BMessage* message)
    4649{
    4750    BFont font(be_plain_font);
    48     font.SetFace(B_ITALIC_FACE);
     51    font.SetFace(B_UNDERSCORE_FACE);
    4952    view->SetFontAndColor(startOffset, endOffset, &font);
    5053}
    5154
    HyperTextAction::MouseLeave(HyperTextView* view, BPoint where,  
    5760    BFont font(be_plain_font);
    5861    font.SetFace(B_REGULAR_FACE);
    5962    view->SetFontAndColor(startOffset, endOffset, &font);
    60 }       
     63}
     64
     65const rgb_color
     66HyperTextAction::GetUnderlineColor()
     67{
     68    return kDarkGrey;
     69}
    6170
    6271
    6372// #pragma mark - HyperTextView
    HyperTextView::~HyperTextView()  
    131140
    132141
    133142void
     143HyperTextView::Draw(BRect updateRect)
     144{
     145    // TODO: Remove code to draw lines once B_UNDERSCORE_FACE is working.
     146
     147    BTextView::Draw(updateRect);
     148
     149    if (fActiveInfo != NULL) {
     150        BRegion textRegion;
     151        GetTextRegion(fActiveInfo->startOffset, fActiveInfo->endOffset,
     152            &textRegion);
     153
     154        BRect frame = textRegion.Frame();
     155        SetHighColor(fActiveInfo->action->GetUnderlineColor());
     156        StrokeLine(frame.LeftBottom(), frame.RightBottom());
     157    }
     158}
     159
     160
     161void
    134162HyperTextView::MouseDown(BPoint where)
    135163{
    136164    // We eat all mouse button events.
    HyperTextView::MouseMoved(BPoint where, uint32 transit,  
    167195        } else if (fActiveInfo != info) {
    168196            // This is the scenario where mouse moves from one action directly
    169197            // into another.
    170             action->MouseEnter(this, where, info->startOffset, info->endOffset,
    171                 message);
    172198            fActiveInfo->action->MouseLeave(this, where, fActiveInfo->startOffset,
    173199                fActiveInfo->endOffset, message);
    174             fActiveInfo = info;
     200            action->MouseEnter(this, where, info->startOffset, info->endOffset,
     201                message);
     202            fActiveInfo = info;
    175203        }
    176204        return;
    177205    } else if (fActiveInfo != NULL) {
    HyperTextAction*  
    228256HyperTextView::_ActionAt(const BPoint& where) const
    229257{
    230258    const ActionInfo* info = _ActionInfoAt(where);
    231     if (info != NULL) {
     259    if (info != NULL)
    232260        return info->action;
    233     }
    234261
    235262    return NULL;
    236263}
    HyperTextView::_ActionInfoAt(const BPoint& where) const  
    255282
    256283    return NULL;
    257284}
    258 
    259 
  • src/apps/aboutsystem/HyperTextView.h

    diff --git a/src/apps/aboutsystem/HyperTextView.h b/src/apps/aboutsystem/HyperTextView.h
    index f413e2f..d702a81 100644
    a b public:  
    3030    virtual void                MouseLeave(HyperTextView* view, BPoint where,
    3131                                    int32 startOffset, int32 endOffset,
    3232                                    BMessage* message);
     33    virtual const rgb_color     GetUnderlineColor();
    3334};
    3435
    3536
    public:  
    4445                                        | B_PULSE_NEEDED);
    4546    virtual                     ~HyperTextView();
    4647
     48    virtual void                Draw(BRect udateRect);
    4749    virtual void                MouseDown(BPoint where);
    4850    virtual void                MouseUp(BPoint where);
    4951    virtual void                MouseMoved(BPoint where, uint32 transit,
    private:  
    6567            class ActionInfoList;
    6668
    6769            ActionInfoList*     fActionInfos;
    68            
     70
    6971            const ActionInfo*   _ActionInfoAt(const BPoint& where) const;
    70            
     72
    7173            const ActionInfo*   fActiveInfo;
    7274};
    7375
  • src/apps/aboutsystem/HyperTextView.h

    -- 
    1.7.7.2
    
    
    From 500b567d165098084b0eb2d0688adf7266d603ad Mon Sep 17 00:00:00 2001
    From: Adam Hartford <adam.s.hartford@gmail.com>
    Date: Sat, 30 Jun 2012 10:11:33 -0400
    Subject: [PATCH 3/5] Fixed typo: udateRect to updateRect.
    
    ---
     src/apps/aboutsystem/HyperTextView.h |    2 +-
     1 files changed, 1 insertions(+), 1 deletions(-)
    
    diff --git a/src/apps/aboutsystem/HyperTextView.h b/src/apps/aboutsystem/HyperTextView.h
    index d702a81..320261d 100644
    a b public:  
    4545                                        | B_PULSE_NEEDED);
    4646    virtual                     ~HyperTextView();
    4747
    48     virtual void                Draw(BRect udateRect);
     48    virtual void                Draw(BRect updateRect);
    4949    virtual void                MouseDown(BPoint where);
    5050    virtual void                MouseUp(BPoint where);
    5151    virtual void                MouseMoved(BPoint where, uint32 transit,
  • src/apps/aboutsystem/HyperTextActions.cpp

    -- 
    1.7.7.2
    
    
    From 42d78ee4f6140824fb04123323e7d32391b74dc5 Mon Sep 17 00:00:00 2001
    From: Adam Hartford <adam.s.hartford@gmail.com>
    Date: Sun, 1 Jul 2012 22:20:12 -0400
    Subject: [PATCH 4/5] Handle underlines for wrapping text.
    
    ---
     src/apps/aboutsystem/HyperTextActions.cpp |    2 -
     src/apps/aboutsystem/HyperTextView.cpp    |   56 ++++++++++++++++++++++++++--
     2 files changed, 52 insertions(+), 6 deletions(-)
    
    diff --git a/src/apps/aboutsystem/HyperTextActions.cpp b/src/apps/aboutsystem/HyperTextActions.cpp
    index 498a1fc..b1d1d04 100644
    a b OpenFileAction::GetUnderlineColor()  
    9090{
    9191    return kDarkGrey;
    9292}
    93 
    94 
  • src/apps/aboutsystem/HyperTextView.cpp

    diff --git a/src/apps/aboutsystem/HyperTextView.cpp b/src/apps/aboutsystem/HyperTextView.cpp
    index dc33d09..437bf53 100644
    a b  
    55
    66#include "HyperTextView.h"
    77
     8#include <math.h>
     9
    810#include <Cursor.h>
     11#include <Debug.h>
    912#include <Message.h>
    1013#include <Region.h>
    1114#include <Window.h>
     
    1720
    1821
    1922static const rgb_color kDarkGrey = { 100, 100, 100, 255 };
     23static const float kCharWidth = 4.5;
    2024
    2125
    2226HyperTextAction::HyperTextAction()
    HyperTextAction::~HyperTextAction()  
    3034
    3135
    3236void
    33 HyperTextAction::MouseOver(HyperTextView* view, BPoint where, BMessage* message)
     37HyperTextAction::MouseOver(HyperTextView* view, BPoint where,
     38    BMessage* message)
    3439{
    3540    BCursor linkCursor(B_CURSOR_ID_FOLLOW_LINK);
    3641    view->SetViewCursor(&linkCursor);
    HyperTextView::Draw(BRect updateRect)  
    153158
    154159        BRect frame = textRegion.Frame();
    155160        SetHighColor(fActiveInfo->action->GetUnderlineColor());
    156         StrokeLine(frame.LeftBottom(), frame.RightBottom());
     161
     162        PRINT_OBJECT(frame);
     163
     164        int currLine = LineAt(frame.LeftTop());
     165        float lineHeight = LineHeight(currLine);
     166
     167        if (frame.Height() > lineHeight) {
     168            // Draw multiple lines if link wraps.
     169
     170            int numLines = (int)ceil(frame.Height() / lineHeight);
     171            BPoint start = BPoint(frame.LeftTop());
     172            BPoint end = BPoint(frame.RightTop());
     173
     174            for (int i = 0; i < numLines; i++) {
     175                start.y += lineHeight;
     176                end.y += lineHeight;
     177
     178                if (i == 0) {
     179                    // Start first line at proper character.
     180                    start.x = PointAt(fActiveInfo->startOffset).x;
     181
     182                    for (int i = fActiveInfo->startOffset;
     183                        i <= fActiveInfo->endOffset; i++) {
     184                        // If this character starts on a new line,
     185                        // end the underline at the previous character.
     186                        if (PointAt(i).y > frame.LeftTop().y) {
     187                            // Pad the ending point a bit.
     188                            end.x = PointAt(i - 1).x + kCharWidth;
     189                            break;
     190                        }
     191                    }
     192                } else if (i == numLines - 1) {
     193                    // End last line at proper character.
     194                    start.x = frame.LeftTop().x;
     195                    end.x = PointAt(fActiveInfo->endOffset).x;
     196                } else {
     197                    start.x = frame.LeftTop().x;
     198                    end.x = frame.RightTop().x;
     199                }
     200
     201                StrokeLine(start, end);
     202            }
     203        } else
     204            StrokeLine(frame.LeftBottom(), frame.RightBottom());
    157205    }
    158206}
    159207
    HyperTextView::MouseMoved(BPoint where, uint32 transit,  
    195243        } else if (fActiveInfo != info) {
    196244            // This is the scenario where mouse moves from one action directly
    197245            // into another.
    198             fActiveInfo->action->MouseLeave(this, where, fActiveInfo->startOffset,
    199                 fActiveInfo->endOffset, message);
     246            fActiveInfo->action->MouseLeave(this, where,
     247                fActiveInfo->startOffset, fActiveInfo->endOffset, message);
    200248            action->MouseEnter(this, where, info->startOffset, info->endOffset,
    201249                message);
    202250            fActiveInfo = info;
  • src/apps/aboutsystem/HyperTextView.cpp

    -- 
    1.7.7.2
    
    
    From 0f696bfe26bd1c66b84d689f1a1c63beeb13641c Mon Sep 17 00:00:00 2001
    From: Adam Hartford <adam.s.hartford@gmail.com>
    Date: Mon, 2 Jul 2012 21:36:15 -0400
    Subject: [PATCH 5/5] Draw underlines correctly for wrapping links.
    
    ---
     src/apps/aboutsystem/HyperTextView.cpp |   68 ++++++++++----------------------
     1 files changed, 21 insertions(+), 47 deletions(-)
    
    diff --git a/src/apps/aboutsystem/HyperTextView.cpp b/src/apps/aboutsystem/HyperTextView.cpp
    index 437bf53..216976f 100644
    a b HyperTextView::Draw(BRect updateRect)  
    152152    BTextView::Draw(updateRect);
    153153
    154154    if (fActiveInfo != NULL) {
    155         BRegion textRegion;
    156         GetTextRegion(fActiveInfo->startOffset, fActiveInfo->endOffset,
    157             &textRegion);
    158 
    159         BRect frame = textRegion.Frame();
    160155        SetHighColor(fActiveInfo->action->GetUnderlineColor());
    161156
    162         PRINT_OBJECT(frame);
    163 
    164         int currLine = LineAt(frame.LeftTop());
    165         float lineHeight = LineHeight(currLine);
    166 
    167         if (frame.Height() > lineHeight) {
    168             // Draw multiple lines if link wraps.
    169 
    170             int numLines = (int)ceil(frame.Height() / lineHeight);
    171             BPoint start = BPoint(frame.LeftTop());
    172             BPoint end = BPoint(frame.RightTop());
    173 
    174             for (int i = 0; i < numLines; i++) {
    175                 start.y += lineHeight;
    176                 end.y += lineHeight;
    177 
    178                 if (i == 0) {
    179                     // Start first line at proper character.
    180                     start.x = PointAt(fActiveInfo->startOffset).x;
    181 
    182                     for (int i = fActiveInfo->startOffset;
    183                         i <= fActiveInfo->endOffset; i++) {
    184                         // If this character starts on a new line,
    185                         // end the underline at the previous character.
    186                         if (PointAt(i).y > frame.LeftTop().y) {
    187                             // Pad the ending point a bit.
    188                             end.x = PointAt(i - 1).x + kCharWidth;
    189                             break;
    190                         }
    191                     }
    192                 } else if (i == numLines - 1) {
    193                     // End last line at proper character.
    194                     start.x = frame.LeftTop().x;
    195                     end.x = PointAt(fActiveInfo->endOffset).x;
    196                 } else {
    197                     start.x = frame.LeftTop().x;
    198                     end.x = frame.RightTop().x;
    199                 }
    200 
    201                 StrokeLine(start, end);
     157        BPoint start;
     158        BPoint end;
     159
     160        for (int i = fActiveInfo->startOffset;
     161            i < fActiveInfo->endOffset; i++) {
     162
     163            float lineHeight = LineHeight(LineAt(i));
     164
     165            start = PointAt(i);
     166            if (i + 1 <= fActiveInfo->endOffset)
     167                end = PointAt(i + 1);
     168
     169            start.y += lineHeight;
     170            end.y += lineHeight;
     171
     172            if (start.y != end.y) {
     173                end = start;
     174                end.x += kCharWidth;
    202175            }
    203         } else
    204             StrokeLine(frame.LeftBottom(), frame.RightBottom());
     176
     177            StrokeLine(start, end);
     178        }
    205179    }
    206180}
    207181