]> git.saurik.com Git - wxWidgets.git/blobdiff - src/html/htmlcell.cpp
test popup menu help strings
[wxWidgets.git] / src / html / htmlcell.cpp
index 2e2fa772d9db080e52140e010baa3516ec2eef0b..c867b38366010622b3cfeb4a8adffce97d3276cb 100644 (file)
 #include "wx/settings.h"
 #include <stdlib.h>
 
+//-----------------------------------------------------------------------------
+// Helper classes
+//-----------------------------------------------------------------------------
+
+void wxHtmlSelection::Set(const wxPoint& fromPos, wxHtmlCell *fromCell,
+                          const wxPoint& toPos, wxHtmlCell *toCell)
+{
+    m_fromCell = fromCell;
+    m_toCell = toCell;
+    m_fromPos = fromPos;
+    m_toPos = toPos;
+}
+
+void wxHtmlSelection::Set(wxHtmlCell *fromCell, wxHtmlCell *toCell)
+{
+    wxPoint p1 = fromCell ? fromCell->GetAbsPos() : wxDefaultPosition;
+    wxPoint p2 = toCell ? toCell->GetAbsPos() : wxDefaultPosition;
+    if ( toCell )
+    {
+        p2.x += toCell->GetWidth()-1;
+        p2.y += toCell->GetHeight()-1;
+    }
+    Set(p1, fromCell, p2, toCell);
+}
 
 //-----------------------------------------------------------------------------
 // wxHtmlCell
@@ -119,12 +143,81 @@ const wxHtmlCell* wxHtmlCell::Find(int WXUNUSED(condition), const void* WXUNUSED
 wxHtmlCell *wxHtmlCell::FindCellByPos(wxCoord x, wxCoord y,
                                       unsigned flags) const
 {
-    if ( (flags & wxHTML_FIND_TERMINAL) &&
-         x >= 0 && x < m_Width && y >= 0 && y < m_Height )
+    if ( x >= 0 && x < m_Width && y >= 0 && y < m_Height )
     {
         return wxConstCast(this, wxHtmlCell);
     }
-    return NULL;
+    else
+    {
+        if ((flags & wxHTML_FIND_NEAREST_AFTER) &&
+                (y < 0 || (y == 0 && x <= 0)))
+            return wxConstCast(this, wxHtmlCell);
+        else if ((flags & wxHTML_FIND_NEAREST_BEFORE) &&
+                (y > m_Height-1 || (y == m_Height-1 && x >= m_Width)))
+            return wxConstCast(this, wxHtmlCell);
+        else
+            return NULL;
+    }
+}
+
+
+wxPoint wxHtmlCell::GetAbsPos() const
+{
+    wxPoint p(m_PosX, m_PosY);
+    for (wxHtmlCell *parent = m_Parent; parent; parent = parent->m_Parent)
+    {
+        p.x += parent->m_PosX;
+        p.y += parent->m_PosY;
+    }
+    return p;
+}
+    
+unsigned wxHtmlCell::GetDepth() const
+{
+    unsigned d = 0;
+    for (wxHtmlCell *p = m_Parent; p; p = p->m_Parent)
+        d++;
+    return d;
+}
+    
+bool wxHtmlCell::IsBefore(wxHtmlCell *cell) const
+{
+    const wxHtmlCell *c1 = this;
+    const wxHtmlCell *c2 = cell;
+    unsigned d1 = GetDepth();
+    unsigned d2 = cell->GetDepth();
+
+    if ( d1 > d2 )
+        for (; d1 != d2; d1-- )
+            c1 = c1->m_Parent;
+    else if ( d1 < d2 )
+        for (; d1 != d2; d2-- )
+            c2 = c2->m_Parent;
+
+    if ( cell == this )
+        return true;
+
+    while ( c1 && c2 )
+    {
+        if ( c1->m_Parent == c2->m_Parent )
+        {
+            while ( c1 )
+            {
+                if ( c1 == c2 )
+                    return true;
+                c1 = c1->GetNext();
+            }            
+            return false;
+        }
+        else
+        {
+            c1 = c1->m_Parent;
+            c2 = c2->m_Parent;
+        }
+    }
+
+    wxFAIL_MSG(_T("Cells are in different trees"));
+    return false;
 }
 
 
@@ -145,7 +238,7 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
                           int WXUNUSED(view_y1), int WXUNUSED(view_y2),
                           wxHtmlRenderingState& state)
 {
-    if (state.GetSelectionState() == wxHTML_SEL_IN &&
+    if (state.GetSelectionState() != wxHTML_SEL_OUT &&
         dc.GetBackgroundMode() != wxSOLID)
     {
         dc.SetBackgroundMode(wxSOLID);
@@ -162,8 +255,16 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
         dc.SetTextBackground(state.GetBgColour());
     }
 
+    // FIXME - use selection
     dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
 }
+    
+
+wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *sel) const
+{
+    // FIXME - use selection
+    return m_Word;
+}
 
 
 
@@ -245,7 +346,7 @@ bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, int* known_pagebreaks,
 
     else
     {
-        wxHtmlCell *c = GetFirstCell();
+        wxHtmlCell *c = GetFirstChild();
         bool rt = FALSE;
         int pbrk = *pagebreak - m_PosY;
 
@@ -429,7 +530,7 @@ void wxHtmlContainerCell::UpdateRenderingStatePre(wxHtmlRenderingState& state,
 {
     wxHtmlSelection *s = state.GetSelection();
     if (!s) return;
-    if (s->GetFromCell() == this || s->GetToCell() == this)
+    if (s->GetFromCell() == cell || s->GetToCell() == cell)
     {
         state.SetSelectionState(wxHTML_SEL_CHANGING);
     }
@@ -440,10 +541,10 @@ void wxHtmlContainerCell::UpdateRenderingStatePost(wxHtmlRenderingState& state,
 {
     wxHtmlSelection *s = state.GetSelection();
     if (!s) return;
-    if (s->GetFromCell() == this)
-        state.SetSelectionState(wxHTML_SEL_IN);
-    else if (s->GetToCell() == this)
+    if (s->GetToCell() == cell)
         state.SetSelectionState(wxHTML_SEL_OUT);
+    else if (s->GetFromCell() == cell)
+        state.SetSelectionState(wxHTML_SEL_IN);
 }
 
 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
@@ -616,24 +717,49 @@ const wxHtmlCell* wxHtmlContainerCell::Find(int condition, const void* param) co
 wxHtmlCell *wxHtmlContainerCell::FindCellByPos(wxCoord x, wxCoord y,
                                                unsigned flags) const
 {
-    for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
+    if ( flags & wxHTML_FIND_EXACT )
     {
-        int cx = cell->GetPosX(),
-            cy = cell->GetPosY();
+        for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
+        {
+            int cx = cell->GetPosX(),
+                cy = cell->GetPosY();
 
-        if ( (cx <= x) && (cx + cell->GetWidth() > x) &&
-             (cy <= y) && (cy + cell->GetHeight() > y) )
+            if ( (cx <= x) && (cx + cell->GetWidth() > x) &&
+                 (cy <= y) && (cy + cell->GetHeight() > y) )
+            {
+                return cell->FindCellByPos(x - cx, y - cy, flags);
+            }
+        }
+    }
+    else if ( flags & wxHTML_FIND_NEAREST_AFTER )
+    {
+        wxHtmlCell *c;
+        int y2;
+        for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
         {
-            wxHtmlCell *c = cell->FindCellByPos(x - cx, y - cy, flags);
-            if (c == NULL && (flags & wxHTML_FIND_NONTERMINAL))
-                return wxConstCast(this, wxHtmlContainerCell);
-            else
-                return c;
+            y2 = cell->GetPosY() + cell->GetHeight() - 1;
+            if (y2 < y || (y2 == y && cell->GetPosX()+cell->GetWidth()-1 < x))
+                continue;
+            c = cell->FindCellByPos(x - cell->GetPosX(), y - cell->GetPosY(),
+                                    flags);
+            if (c) return c;
+        }
+    }
+    else if ( flags & wxHTML_FIND_NEAREST_BEFORE )
+    {
+        wxHtmlCell *c;
+        for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
+        {
+            if (cell->GetPosY() > y || 
+                    (cell->GetPosY() == y && cell->GetPosX() > x))
+                break;
+            c = cell->FindCellByPos(x - cell->GetPosX(), y - cell->GetPosY(),
+                                    flags);
+            if (c) return c;
         }
     }
 
-    return (flags & wxHTML_FIND_NONTERMINAL) ? 
-                wxConstCast(this, wxHtmlContainerCell) : NULL;
+    return NULL;
 }
 
 
@@ -669,6 +795,38 @@ void wxHtmlContainerCell::GetHorizontalConstraints(int *left, int *right) const
         *right = cright;
 }
 
+    
+wxHtmlCell *wxHtmlContainerCell::GetFirstTerminal() const
+{
+    if ( m_Cells )
+    {
+        wxHtmlCell *c2;
+        for (wxHtmlCell *c = m_Cells; c; c = c->GetNext())
+        {
+            c2 = c->GetFirstTerminal();
+            if ( c2 )
+                return c2;
+        }
+    }
+    return NULL;
+}
+
+wxHtmlCell *wxHtmlContainerCell::GetLastTerminal() const
+{
+    if ( m_Cells )
+    {
+        wxHtmlCell *c, *c2 = NULL;
+        // most common case first:
+        c = m_LastCell->GetLastTerminal();
+        if ( c )
+            return c;
+        for (wxHtmlCell *c = m_Cells; c; c = c->GetNext())
+            c2 = c->GetLastTerminal();
+        return c2;
+    }
+    else
+        return NULL;
+}
 
 
 
@@ -798,4 +956,44 @@ void wxHtmlWidgetCell::Layout(int w)
     wxHtmlCell::Layout(w);
 }
 
+
+
+// ----------------------------------------------------------------------------
+// wxHtmlTerminalCellsInterator
+// ----------------------------------------------------------------------------
+
+const wxHtmlCell* wxHtmlTerminalCellsInterator::operator++()
+{
+    if ( !m_pos )
+        return NULL;
+
+    do
+    {
+        if ( m_pos == m_to )
+        {
+            m_pos = NULL;
+            return NULL;
+        }
+
+        if ( m_pos->GetNext() )
+            m_pos = m_pos->GetNext();
+        else
+        {
+            // we must go up the hierarchy until we reach container where this
+            // is not the last child, and then go down to first terminal cell:
+            while ( m_pos->GetNext() == NULL )
+            {
+                m_pos = m_pos->GetParent();
+                if ( !m_pos )
+                    return NULL;
+            }
+            m_pos = m_pos->GetNext();
+        }
+        while ( m_pos->GetFirstChild() != NULL )
+            m_pos = m_pos->GetFirstChild();
+    } while ( !m_pos->IsTerminalCell() );
+    
+    return m_pos;
+}
+
 #endif