Changeset 147

Show
Ignore:
Timestamp:
05/05/06 11:42:43 (2 years ago)
Author:
jordi
Message:

Added the new DocumentLink? class that holds a link's rectangle (position) and the destination page. The page rendered now also gets all the links from the PDF document and adds it to the DocumentPage? class, which can be queried about the link at a given position.

The page view changes the cursor when the pointer is over a link and also when it's dragging the page.

Location:
trunk
Files:
2 added
18 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/DocumentPage.cxx

    r58 r147  
    3131    m_Data = NULL; 
    3232    m_Height = 0; 
     33    m_LinkList = NULL; 
    3334    m_Width = 0; 
    3435} 
     
    4041{ 
    4142    delete[] m_Data; 
     43    for ( GList *linkItem = g_list_first (m_LinkList) ; 
     44          NULL != linkItem ; 
     45          linkItem = g_list_next (linkItem) ) 
     46    { 
     47        DocumentLink *link = (DocumentLink *)linkItem->data; 
     48        delete link; 
     49    } 
     50    g_list_free (m_LinkList); 
     51} 
     52 
     53void 
     54DocumentPage::addLink (DocumentLink *link) 
     55{ 
     56    m_LinkList = g_list_prepend (m_LinkList, link); 
    4257} 
    4358 
     
    5873 
    5974    return m_Data; 
     75} 
     76 
     77DocumentLink * 
     78DocumentPage::getLinkAtPosition (gint x, gint y) 
     79{ 
     80    DocumentLink *link = NULL; 
     81 
     82    for ( GList *linkItem = g_list_first (m_LinkList) ; 
     83          NULL != linkItem && NULL == link; 
     84          linkItem = g_list_next (linkItem) ) 
     85    { 
     86        DocumentLink *tmpLink = (DocumentLink *)linkItem->data; 
     87        if ( tmpLink->positionIsOver (x, y) ) 
     88        { 
     89            link = tmpLink; 
     90        } 
     91    } 
     92     
     93    return link; 
    6094} 
    6195 
  • trunk/src/DocumentPage.h

    r49 r147  
    3232            DocumentPage (void); 
    3333            ~DocumentPage (void); 
    34              
     34            
     35            void addLink (DocumentLink *link); 
    3536            guchar *getData (void); 
    3637            gint getHeight (void); 
     38            DocumentLink *getLinkAtPosition (gint x, gint y); 
    3739            gint getRowStride (void); 
    3840            gint getWidth (void); 
     
    4345            gint m_Height; 
    4446            gint m_Width; 
     47            GList *m_LinkList; 
    4548    }; 
    4649} 
  • trunk/src/IDocument.cxx

    r145 r147  
    12271227} 
    12281228 
     1229gboolean 
     1230IDocument::hasLinkAtPosition (gint x, gint y) 
     1231{ 
     1232    // XXX For now only non rotated pages. 
     1233    if ( 0 == getRotation () ) 
     1234    { 
     1235        DocumentPage *page = getCurrentPage (); 
     1236        if ( NULL != page ) 
     1237        { 
     1238            return (NULL != page->getLinkAtPosition (x, y)); 
     1239        } 
     1240    } 
     1241    return FALSE; 
     1242} 
     1243 
     1244void 
     1245IDocument::activateLinkAtPosition (gint x, gint y) 
     1246{ 
     1247    DocumentPage *page = getCurrentPage (); 
     1248    // XXX For now only non rotated pages. 
     1249    if ( NULL != page && 0 == getRotation () ) 
     1250    { 
     1251        DocumentLink *link = page->getLinkAtPosition (x, y); 
     1252        if ( NULL != link ) 
     1253        { 
     1254            goToPage (link->getDestinationPage ()); 
     1255        } 
     1256    }     
     1257} 
  • trunk/src/IDocument.h

    r136 r147  
    256256            void zoomToWidth (gint width); 
    257257 
     258            gboolean hasLinkAtPosition (gint x, gint y); 
     259            void activateLinkAtPosition (gint x, gint y); 
     260 
    258261            static GQuark getErrorQuark (void); 
    259262            static gchar *getErrorMessage (DocumentError errorCode); 
  • trunk/src/IPageView.h

    r146 r147  
    2323    // Forward declarations. 
    2424    class PagePter; 
     25 
     26    enum PageCursor 
     27    { 
     28        /// Normal cursor. 
     29        PAGE_VIEW_CURSOR_NORMAL, 
     30        /// Drag cursor. 
     31        PAGE_VIEW_CURSOR_DRAG, 
     32        /// Link cursor. 
     33        PAGE_VIEW_CURSOR_LINK 
     34    }; 
    2535     
    2636    /// 
     
    8494            virtual void scrollPage (gdouble scrollX, gdouble scrollY, 
    8595                                     gint dx, gint dy) = 0; 
    86  
     96             
     97            /// 
     98            /// @brief Sets the cursor for the page view. 
     99            /// 
     100            /// The view must change the cursor for the page image. 
     101            /// If the cursor to be set is the same as the current cursor, 
     102            /// the view can ignore the petition. 
     103            /// 
     104            /// @param cursorType The cursor to set. 
     105            /// 
     106            virtual void setCursor (PageCursor cursorType) = 0; 
     107             
    87108            /// 
    88109            /// @brief Shows a document's page. 
     
    100121            /// 
    101122            virtual void showPage (DocumentPage *page, PageScroll scroll) = 0; 
    102  
    103123             
    104124        protected: 
  • trunk/src/MainPter.cxx

    r143 r147  
    589589/// @param error Where to save the error if there's one. 
    590590/// 
    591 bool 
     591gboolean 
    592592MainPter::openDocument (const gchar *fileName, const gchar *oldPassword, 
    593593                        GError **error) 
  • trunk/src/MainPter.h

    r138 r147  
    5151            void goToPageActivated (void); 
    5252            void goToPreviousPageActivated (void); 
    53             bool openDocument (const gchar *fileName, const gchar *oldPassword, 
    54                                 GError **error); 
     53            gboolean openDocument (const gchar *fileName,  
     54                                   const gchar *oldPassword, GError **error); 
    5555            void openFileActivated (void); 
    5656            void outlineActivated (DocumentOutline *outline); 
  • trunk/src/Makefile.am

    r138 r147  
    77    Config.cxx          \ 
    88    Config.h            \ 
     9    DocumentLink.cxx    \ 
     10    DocumentLink.h  \ 
    911    DocumentOutline.cxx \ 
    1012    DocumentOutline.h   \ 
  • trunk/src/PDFDocument.cxx

    r128 r147  
    233233} 
    234234 
     235void 
     236PDFDocument::setLinks (DocumentPage *renderedPage, PopplerPage *popplerPage) 
     237{ 
     238    gdouble pageHeight = 1.0; 
     239    // Get the height, to calculate the Y position as the document's origin 
     240    // is at the bottom-left corner, not the top-left as the screen does. 
     241    poppler_page_get_size (popplerPage, NULL, &pageHeight); 
     242    // We'll already calculate the positions scaled. 
     243    gdouble scale = getZoom (); 
     244    GList *pageLinks = poppler_page_get_link_mapping (popplerPage);  
     245    for (GList *pageLink = g_list_first (pageLinks) ; 
     246         NULL != pageLink ; 
     247         pageLink = g_list_next (pageLink) ) 
     248    { 
     249        PopplerLinkMapping *link = (PopplerLinkMapping *)pageLink->data; 
     250        PopplerAction *action = link->action; 
     251        // Only internal links. 
     252        if ( POPPLER_ACTION_GOTO_DEST == action->type ) 
     253        { 
     254            PopplerActionGotoDest *actionGoTo = (PopplerActionGotoDest *)action; 
     255            DocumentLink *documentLink =  
     256                new DocumentLink (link->area.x1 * scale,  
     257                                  (pageHeight - link->area.y2) * scale, 
     258                                  link->area.x2 * scale, 
     259                                  (pageHeight - link->area.y1) * scale, 
     260                                  actionGoTo->dest->page_num); 
     261            renderedPage->addLink (documentLink); 
     262        } 
     263    } 
     264} 
     265 
    235266/// 
    236267/// @brief Sets the document's outline. 
     
    311342    *width = pageWidth; 
    312343    *height = pageHeight; 
     344 
     345    g_object_unref (G_OBJECT (page)); 
    313346} 
    314347 
     
    353386                                   getRotation (), pixbuf); 
    354387    gdk_pixbuf_unref (pixbuf); 
     388    setLinks (renderedPage, page); 
     389    g_object_unref (G_OBJECT (page)); 
    355390     
    356391    return (renderedPage); 
  • trunk/src/PDFDocument.h

    r120 r147  
    2323typedef struct _PopplerIndexIter PopplerIndexIter; 
    2424typedef struct _PopplerDocument PopplerDocument; 
     25typedef struct _PopplerPage PopplerPage; 
    2526 
    2627namespace ePDFView  
     
    5152            void setOutline (DocumentOutline *outline,  
    5253                             PopplerIndexIter *childrenList); 
     54            void setLinks (DocumentPage *renderedPage, 
     55                           PopplerPage *popplerPage); 
    5356    }; 
    5457} 
  • trunk/src/PagePter.cxx

    r146 r147  
    8383    if ( 1 == button ) 
    8484    { 
    85         m_DragInfo = new DragInfo; 
    86         m_DragInfo->x = x; 
    87         m_DragInfo->y = y; 
    88         m_DragInfo->scrollX = getView ().getHorizontalScroll (); 
    89         m_DragInfo->scrollY = getView ().getVerticalScroll (); 
     85        if ( m_Document->hasLinkAtPosition (x, y) ) 
     86        { 
     87            m_Document->activateLinkAtPosition (x, y); 
     88        } 
     89        else 
     90        { 
     91            m_DragInfo = new DragInfo; 
     92            m_DragInfo->x = x; 
     93            m_DragInfo->y = y; 
     94 
     95            IPageView &view = getView (); 
     96            m_DragInfo->scrollX = view.getHorizontalScroll (); 
     97            m_DragInfo->scrollY = view.getVerticalScroll (); 
     98            view.setCursor (PAGE_VIEW_CURSOR_DRAG); 
     99        } 
    90100    } 
    91101} 
     
    98108        delete m_DragInfo; 
    99109        m_DragInfo = NULL; 
     110        getView ().setCursor (PAGE_VIEW_CURSOR_NORMAL); 
    100111    } 
    101112} 
     
    104115PagePter::mouseMoved (gint x, gint y) 
    105116{ 
    106     if ( NULL != m_DragInfo ) 
    107     { 
    108         getView ().scrollPage (m_DragInfo->scrollX, m_DragInfo->scrollY, 
    109                                x - m_DragInfo->x, y - m_DragInfo->y); 
     117    IPageView &view = getView (); 
     118    if ( NULL == m_DragInfo ) 
     119    { 
     120        if ( m_Document->hasLinkAtPosition (x, y) ) 
     121        { 
     122            view.setCursor (PAGE_VIEW_CURSOR_LINK); 
     123        } 
     124        else 
     125        { 
     126            view.setCursor (PAGE_VIEW_CURSOR_NORMAL); 
     127        } 
     128    } 
     129    else 
     130    { 
     131        view.scrollPage (m_DragInfo->scrollX, m_DragInfo->scrollY, 
     132                         x - m_DragInfo->x, y - m_DragInfo->y); 
    110133    } 
    111134} 
  • trunk/src/epdfview.h

    r138 r147  
    2424#include <Config.h> 
    2525 
     26#include <DocumentLink.h> 
    2627#include <DocumentOutline.h> 
    2728#include <DocumentPage.h> 
  • trunk/src/gtk/PageView.cxx

    r146 r147  
    4444    IPageView () 
    4545{ 
     46    // The initial cursor is normal. 
     47    m_CurrentCursor = PAGE_VIEW_CURSOR_NORMAL; 
     48 
    4649    // Create the scrolled window where the page image will be. 
    4750    m_PageScroll = gtk_scrolled_window_new (NULL, NULL); 
     
    100103            GTK_SCROLLED_WINDOW (m_PageScroll)); 
    101104    return gtk_adjustment_get_value (vAdjustment); 
     105} 
     106 
     107void 
     108PageView::setCursor (PageCursor cursorType) 
     109{ 
     110    if ( cursorType != m_CurrentCursor ) 
     111    { 
     112        GdkCursor *cursor = NULL; 
     113        switch (cursorType) 
     114        { 
     115            case PAGE_VIEW_CURSOR_LINK: 
     116                cursor = gdk_cursor_new (GDK_HAND2); 
     117                break; 
     118            case PAGE_VIEW_CURSOR_DRAG: 
     119                cursor = gdk_cursor_new (GDK_FLEUR); 
     120                break; 
     121            default: 
     122                cursor = NULL; 
     123        } 
     124        if ( NULL != m_EventBox && GDK_IS_WINDOW (m_EventBox->window) ) 
     125        { 
     126            gdk_window_set_cursor (m_EventBox->window, cursor); 
     127        } 
     128        if ( NULL != cursor ) 
     129        { 
     130            gdk_cursor_unref (cursor); 
     131        } 
     132        gdk_flush (); 
     133        m_CurrentCursor = cursorType; 
     134    } 
    102135} 
    103136 
  • trunk/src/gtk/PageView.h

    r146 r147  
    3535            void scrollPage (gdouble scrollX, gdouble scrollY, 
    3636                             gint dx, gint dy); 
     37            void setCursor (PageCursor cursorType); 
    3738            void setPresenter (PagePter *pter); 
    3839            void showPage (DocumentPage *page, PageScroll scroll); 
    3940 
    4041        protected: 
     42            PageCursor m_CurrentCursor; 
    4143            GtkWidget *m_EventBox; 
    4244            GtkWidget *m_PageImage; 
  • trunk/tests/DumbPageView.cxx

    r146 r147  
    5959 
    6060void 
     61DumbPageView::setCursor (PageCursor cursorType) 
     62{ 
     63} 
     64 
     65void 
    6166DumbPageView::showPage (DocumentPage *page, PageScroll scroll) 
    6267{ 
  • trunk/tests/DumbPageView.h

    r146 r147  
    3232            void scrollPage (gdouble scrollX, gdouble scrollY, 
    3333                             gint dx, gint dy); 
     34            void setCursor (PageCursor cursorType); 
    3435            void showPage (DocumentPage *page, PageScroll scroll); 
    3536 
  • trunk/tests/PDFDocumentTest.cxx

    r136 r147  
    604604    g_free (testFile); 
    605605} 
     606 
     607/// 
     608/// @brief Tests the document's link. 
     609/// 
     610/// If a page has a links, we should be able to ask the document if the 
     611/// mouse pointer is over any link (to be able to change the cursor) and to 
     612/// tell the document to change the current page for the page a links points 
     613/// to. 
     614/// 
     615/// All this should happen even if the page is resized but will keep things 
     616/// simple for now and only for unrotated documents. 
     617/// 
     618void 
     619PDFDocumentTest::pageLinks () 
     620{ 
     621    gchar *testFile = getTestFile ("test1.pdf"); 
     622    m_Document->load (testFile, NULL); 
     623    while ( !m_Observer->loadFinished () ) { } 
     624    CPPUNIT_ASSERT (m_Observer->notifiedLoaded ()); 
     625    CPPUNIT_ASSERT (m_Document->isLoaded ()); 
     626 
     627    // In this test PDF document there are two links on page 4. 
     628    // Both links points to page 5 and are situated at: 
     629    // ((72.00, 147.11), (134.50, 137.11)) 
     630    // ((96.00, 158.11), (145.17, 148.11)) 
     631    // 
     632    // First try with an unscaled document. 
     633    m_Document->goToPage (4); 
     634    DocumentPage *page = NULL; 
     635    while ( NULL == page || (DocumentPage *)0xdeadbeef == page ) 
     636    { 
     637        page = m_Document->getCurrentPage (); 
     638    } 
     639    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (70, 140)); 
     640    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (76, 40)); 
     641    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (136, 139)); 
     642    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (130, 160)); 
     643    CPPUNIT_ASSERT (m_Document->hasLinkAtPosition (76, 139)); 
     644    CPPUNIT_ASSERT (m_Document->hasLinkAtPosition (100, 150)); 
     645    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (90, 151)); 
     646    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (100, 130)); 
     647    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (110, 160)); 
     648    CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (150, 152)); 
     649 
     650    // Active a link and let see how the page is changed. 
     651    m_Document->activateLinkAtPosition (76, 139); 
     652    CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ()); 
     653 
     654    // Now try the same but with an scaled page. (x1.2) 
     655    // With this scale the links are now at: 
     656    // ((86.40, 176.53), (160.80, 164.53)) 
     657    // ((115.2, 189.73), (174.20, 177.73)) 
     658    // 
     659    m_Document->zoomIn (); 
     660    m_Document->goToPage (4); 
     661    page = NULL; 
     662    while ( NULL == page || (DocumentPage *)0xdeadbeef == page ) 
     663    { 
     664        page = m_Document->getCurrentPage (); 
     665    } 
     666    // Just check the first link and activate the second. 
     667    CPPUNIT_ASSERT (m_Document->hasLinkAtPosition (87, 175)); 
     668    m_Document->activateLinkAtPosition (174, 177); 
     669    CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ()); 
     670} 
  • trunk/tests/PDFDocumentTest.h

    r130 r147  
    3636        CPPUNIT_TEST (pageZoom); 
    3737        CPPUNIT_TEST (pageRender); 
     38        CPPUNIT_TEST (pageLinks); 
    3839        CPPUNIT_TEST_SUITE_END (); 
    3940 
     
    5253            void pageZoom (void); 
    5354            void pageRender (void); 
     55            void pageLinks (void); 
    5456             
    5557        private: